rbp不允许作为SIB基础?

oll*_*lpu 1 x86 assembly x86-64 machine-code addressing-mode

我对x86-64二进制编码很新.我正在尝试修复一些旧的"汇编程序"代码.

无论如何,我正在尝试做这样的事情(英特尔语法):

mov    [rbp+rcx], al
Run Code Online (Sandbox Code Playgroud)

汇编程序目前正在生成:

88 04 0D
Run Code Online (Sandbox Code Playgroud)

但这似乎不是一个有效的指示.如果我将SIB字节中的基数更改rbp为其他寄存器,则可以正常工作.另一种使其工作的方法是添加一个零字节的位移(88 44 0D 00).这似乎与其他类似的操作码一起发生.

为什么我不能rbp在那里使用mod=00

Pet*_*des 5

编码意味着rbp没有基址寄存器的转义码(只是SIB中的disp32或ModRM中的RIP相对rel32).大多数装配工装[rbp]配成[rbp + disp8=0].


由于您不需要缩放,因此请使用[rcx + rbp]以避免需要disp8 = 0,因为它rbp 可以是索引.

(SS和DS在长模式下始终是等效的,因此base = RBP意味着SS而base = RCX意味着使用DS段并不重要.)


x86/x86-64 ModRM寻址模式编码特殊情况

(从我写的答案为什么rbp和rsp称为通用寄存器?).这个问题看起来像是复制或移植这一部分的理想场所.

rbp/ r13不能是没有位移的基址寄存器:该编码代替:(在ModRM中)rel32(RIP相对),或(在SIB中)disp32没有基址寄存器.(r13在ModRM/SIB中使用相同的3位,因此该选择通过不使指令长度解码器查看REX.B位以获得第4个基址寄存器位来简化解码). [r13]装配到[r13 + disp8=0]. [r13+rdx]汇编到[rdx+r13](当这是一个选项时,通过交换base/index 来避免问题).

rsp/ r12作为基址寄存器总是需要一个SIB字节.(base = RSP的ModR/M编码是用于发信号通知SIB字节的转义码,并且如果r12处理不同,则更多的解码器将不得不关心REX前缀).

rsp不能成为索引注册.这使得编码成为可能[rsp],这比编码更有用[rsp + rsp].(英特尔本可以设计用于32位寻址模式的ModRM/SIB编码(386中的新功能),因此只能使用base = ESP进行SIB-no-index.这样就[eax + esp*4]可以并且只能排除[esp + esp*1/2/4/8].但这没有用,所以他们简化了硬件,使index = ESP成为无索引的代码,无论基数如何.这允许两种冗余方式对任何base或base + disp寻址模式进行编码:有或没有SIB.)

r12 可以是索引寄存器.与其他情况不同,这不会影响指令长度解码.此外,它不能像其他情况一样使用更长的编码.AMD希望AMD64的寄存器设置尽可能正交,因此有必要花一些额外的晶体管来检查REX.X作为索引/无索引解码的一部分.例如,[rsp + r12*4]要求index = r12,因此r12没有完全通用的目的会使AMD64成为更糟糕的编译器目标.

   0:   41 8b 03                mov    eax,DWORD PTR [r11]
   3:   41 8b 04 24             mov    eax,DWORD PTR [r12]      # needs a SIB like RSP
   7:   41 8b 45 00             mov    eax,DWORD PTR [r13+0x0]  # needs a disp8 like RBP
   b:   41 8b 06                mov    eax,DWORD PTR [r14]
   e:   41 8b 07                mov    eax,DWORD PTR [r15]
  11:   43 8b 04 e3             mov    eax,DWORD PTR [r11+r12*8] # *can* be an index
Run Code Online (Sandbox Code Playgroud)

这些都适用于32位寻址模式; 编码是相同的,除了没有EIP相关编码,只有两种冗余方式来编码没有基数的disp32.

有关像英特尔vol.2手册中的表格,请参阅https://wiki.osdev.org/X86-64_Instruction_Encoding#32.2F64-bit_addressing_2.


这似乎与其他类似的操作码一起发生.

r/m操作数的ModRM编码始终相同.某些操作码需要一个寄存器操作数,有些需要内存,但实际的ModRM +可选SIB +可选位移是固定的,因此无论指令如何,相同的硬件都可以对其进行解码.

有一些罕见的操作码,例如mov al/ax/eax/rax, [qword absolute_address]根本不使用ModRM编码作为操作数,但任何使用相同格式的操作码.

  • 啊,可以查看这里的表格:https://wiki.osdev.org/X86-64_Instruction_Encoding#32.2F64-bit_addressing_2。谢谢。 (2认同)