commit 3f422c60b225b4f33692c2d1d53e6478cc3df284
parent 737e79b6123809afd234141474f9e06fbd964276
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Tue, 21 Apr 2026 15:25:20 -0700
amd64 sib fix
Diffstat:
1 file changed, 11 insertions(+), 9 deletions(-)
diff --git a/src/p1_gen.py b/src/p1_gen.py
@@ -158,14 +158,14 @@ def amd_mem_rm(opcode, reg, base, disp):
if -128 <= disp <= 127:
mod = 1
d = byte(disp)
- elif b == 4: # SIB required for rsp
- mod = 2
- d = (disp & 0xFFFFFFFF).to_bytes(4, 'little').hex().upper()
else:
mod = 2
d = (disp & 0xFFFFFFFF).to_bytes(4, 'little').hex().upper()
- # rsp as base requires SIB byte (rm=4 with no SIB is rip-relative).
- if b == 4:
+ # Any base whose low 3 bits are 100 — rsp (4) or r12 (12) — forces a
+ # SIB byte when mod != 00; rm=100 without SIB is the [*] / SIB-follows
+ # special form. REX.B already distinguishes rsp from r12 in the SIB
+ # base field, so the SIB byte is 24 in both cases.
+ if (b & 7) == 4:
return prefix + modrm(mod, r, 4) + '24' + d
return prefix + modrm(mod, r, b) + d
@@ -178,17 +178,19 @@ def amd_mov_rm_b(reg, base, disp, store):
else:
mod = 2
d = (disp & 0xFFFFFFFF).to_bytes(4, 'little').hex().upper()
+ # rsp (4) and r12 (12) share rm bits 100, which forces a SIB byte when
+ # mod != 00; REX.B distinguishes them in the SIB base field. See
+ # amd_mem_rm for the same rule.
+ need_sib = (b & 7) == 4
+ sib = '24' if need_sib else ''
+ rmv = 4 if need_sib else b
if store:
# MOV r/m8, r8 — 88 /r. Requires REX to address dil/sil/bpl/spl.
prefix = rex(1, r >> 3, 0, b >> 3) + '88'
- sib = '24' if b == 4 else ''
- rmv = 4 if b == 4 else b
return prefix + modrm(mod, r, rmv) + sib + d
else:
# MOVZX r64, r/m8 — REX.W 0F B6 /r.
prefix = rex(1, r >> 3, 0, b >> 3) + '0FB6'
- sib = '24' if b == 4 else ''
- rmv = 4 if b == 4 else b
return prefix + modrm(mod, r, rmv) + sib + d