不允许rbp作为SIB基础吗?

时间:2018-09-26 16:42:02

标签: assembly x86 x86-64 machine-code addressing-mode

我对x86-64二进制编码非常陌生。我正在尝试修复一些旧的“汇编程序”代码。

无论如何,我正在尝试执行以下操作(Intel语法):

mov    [rbp+rcx], al

汇编器当前正在生成此:

88 04 0D

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

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

1 个答案:

答案 0 :(得分: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寻址模式编码的特殊情况

(根据我在Why are rbp and rsp called general purpose registers?上写的答案)。这个问题看起来像是复制或移植此部分的理想位置。

rbp / r13不能是没有位移的基址寄存器:该编码的意思是:(在ModRM中)rel32(相对于RIP ),或(在SIB中)disp32,没有基址寄存器。 (r13在ModRM / SIB中使用相同的3位,因此此选择通过不使指令长度解码器查看the REX.B bit来获得第4个基寄存器位来简化解码)。 [r13]组合为[r13 + disp8=0][r13+rdx]会与[rdx+r13]组合在一起(可以选择通过交换基数/索引来避免此问题)。

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

rsp不能是索引寄存器。这样就可以对[rsp]进行编码,该编码比[rsp + rsp]更有用。 (英特尔本可以为32位寻址模式(386中的新增功能)设计ModRM / SIB编码,因此只有在base = ESP时才可以使用没有索引的SIB。这将使[eax + esp*4]成为可能,并且仅排除{ {1}},但这没有用,因此他们通过使index = ESP成为不带索引的代码来简化硬件,而不考虑基础,这允许两种冗余方式来编码任何基础或base + disp寻址模式:有或没有SIB。)

[esp + esp*1/2/4/8] 可以是索引寄存器。与其他情况不同,这不会影响指令长度解码。而且,不能像其他情况一样使用更长的编码来解决。 AMD希望AMD64的寄存器组尽可能正交,因此在索引/无索引解码中,他们花了一些额外的晶体管来检查REX.X才有意义。例如,r12需要index = r12,因此[rsp + r12*4]的用途不完全会导致AMD64成为较差的编译器目标。

r12

这些都同样适用于32位寻址模式。除了没有EIP相对编码外,其他编码都是相同的,只有两种冗余的方法可以对disp32进行编码,而无需任何基础。

另请参阅https://wiki.osdev.org/X86-64_Instruction_Encoding#32.2F64-bit_addressing_2,以获取类似于英特尔第2卷手册中的表格。


  

这似乎在其他类似的操作码中发生。

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

有一些罕见的操作码,例如 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 ,它们的操作数完全不使用ModRM编码,但是任何使用相同格式的操作码。