boot2

Playing with the boostrap
git clone https://git.ryansepassi.com/git/boot2.git
Log | Files | Refs

commit 3f422c60b225b4f33692c2d1d53e6478cc3df284
parent 737e79b6123809afd234141474f9e06fbd964276
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Tue, 21 Apr 2026 15:25:20 -0700

amd64 sib fix

Diffstat:
Msrc/p1_gen.py | 20+++++++++++---------
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