不允许rbp作为SIB基础吗? [英] rbp not allowed as SIB base?
问题描述
我对x86-64二进制编码非常陌生。我正在尝试修复一些旧的汇编程序代码。
I'm quite new to x86-64 binary encoding. I'm trying to fix some old "assembler" code.
无论如何,我正在尝试执行以下操作(Intel语法):
Anyways, I'm trying to do something like this (Intel syntax):
mov [rbp+rcx], al
汇编器当前正在生成:
88 04 0D
但这似乎不是有效的说明。如果我将SIB字节的基数从 rbp
更改为其他寄存器,则可以正常工作。另一种使其工作的方法是添加一个零字节的字节位移( 88 44 0D 00
)。
but that doesn't seem to be a valid instruction. If I change out the base in the SIB-byte from rbp
to some other register, it works fine. Another way to make it work is to add a one byte displacement of zero (88 44 0D 00
). This seems to happen with other similar opcodes.
为什么我不能在<$ c $中使用 rbp
呢? c> mod = 00 ?
Why can't I use rbp
there with mod=00
?
推荐答案
表示 rbp的编码
是没有基址寄存器的转义码(SIB中只有disp32或ModRM中只有RIP相对rel32)。大多数汇编程序将 [rbp]
组装为 [rbp + disp8 = 0]
。
The encoding that would mean rbp
is an escape code for no base register (just a disp32 in SIB or RIP-relative rel32 in ModRM). Most assemblers assemble [rbp]
into [rbp + disp8=0]
.
由于不需要缩放,请使用 [rcx + rbp]
代替避免需要disp8 = 0,因为 rbp
可以是索引。
Since you don't need it scaled, use [rcx + rbp]
instead to avoid needing a disp8=0, because rbp
can be an index.
(SS和DS在长模式下总是等效的,因此base = RBP表示SS而base = RCX表示使用DS段并不重要。)
(SS and DS are always equivalent in long mode, so it doesn't matter that base=RBP implies SS while base=RCX implies using the DS segment.)
(摘自我在为什么rbp和rsp称为通用寄存器? )。这个问题看起来像是复制或移植此部分的理想位置。
(from an answer I wrote on Why are rbp and rsp called general purpose registers?). This question looks like the perfect place to copy or transplant this section.
rbp
/ r13
不能是没有位移的基址寄存器:该编码的意思是:(在ModRM中) rel32
(相对于RIP),或(在SIB中) disp32
(无基址寄存器)。 ( r13
在ModRM / SIB中使用相同的3位,因此此选择通过不使指令长度解码器查看 REX.B位以获取第4个基寄存器位)。 [r13]
组合为 [r13 + disp8 = 0]
。 [r13 + rdx]
汇编为 [rdx + r13]
(通过在此情况下交换基数/索引来避免此问题选项)。
rbp
/r13
can't be a base register with no displacement: that encoding instead means: (in ModRM) rel32
(RIP-relative), or (in SIB) disp32
with no base register. (r13
uses the same 3 bits in ModRM/SIB, so this choice simplifies decoding by not making the instruction-length decoder look at the REX.B bit to get the 4th base-register bit). [r13]
assembles to [r13 + disp8=0]
. [r13+rdx]
assembles to [rdx+r13]
(avoiding the problem by swapping base/index when that's an option).
rsp
/ r12
因为基址寄存器总是需要一个SIB字节。 (base = RSP的ModR / M编码是转义信号,用于指示SIB字节,而且,如果 r12
为,则更多的解码器将不得不关心REX前缀。
rsp
/r12
as a base register always needs a SIB byte. (The ModR/M encoding of base=RSP is escape code to signal a SIB byte, and again, more of the decoder would have to care about the REX prefix if r12
was handled differently).
rsp
不能是索引寄存器。这样就可以对 [rsp]
进行编码,这比 [rsp + rsp]
有用。 (英特尔可以为32位寻址模式(386中的新增功能)设计ModRM / SIB编码,因此只有在base = ESP时才可以使用没有索引的SIB。这将使 [eax + esp * 4]
可能,并且仅排除 [esp + esp * 1/2/4/8]
。但这没有用,因此他们简化了硬件,通过使index = ESP成为不带索引的代码,而不考虑基数。这允许两种冗余方式来编码任何基数或基数+显示寻址模式:有或没有SIB。)
rsp
can't be an index register. This makes it possible to encode [rsp]
, which is more useful than [rsp + rsp]
. (Intel could have designed the ModRM/SIB encodings for 32-bit addressing modes (new in 386) so SIB-with-no-index was only possible with base=ESP. That would make [eax + esp*4]
possible and only exclude [esp + esp*1/2/4/8]
. But that's not useful, so they simplified the hardware by making index=ESP the code for no index regardless of the base. This allows two redundant ways to encode any base or base+disp addressing mode: with or without a SIB.)
r12
可以是索引寄存器。与其他情况不同,这不会影响指令长度的解码。而且,无法像其他情况一样使用更长的编码来解决。 AMD希望AMD64的寄存器组尽可能正交,因此在索引/无索引解码中,他们花了一些额外的晶体管来检查REX.X才有意义。例如, [rsp + r12 * 4]
要求index = r12,所以 r12
的用途不完全会导致AMD64是较差的编译器目标。
r12
can be an index register. Unlike the other cases, this doesn't affect instruction-length decoding. Also, it can't be worked around with a longer encoding like the other cases. AMD wanted AMD64's register set to be as orthogonal as possible, so it makes sense they'd spend a few extra transistors to check REX.X as part of the index / no-index decoding. For example, [rsp + r12*4]
requires index=r12, so having r12
not fully generally purpose would make AMD64 a worse compiler target.
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
这些都同样适用于32位寻址模式;除没有EIP相对编码外,其他所有编码均相同,只是两种冗余编码,可以对没有基数的disp32进行编码。
These all apply to 32-bit addressing modes as well; the encoding is identical except there's no EIP-relative encoding, just two redundant ways to encode disp32 with no base.
另请参见 https://wiki.osdev.org/X86-64_Instruction_Encoding#32.2F64-bit_addressing_2
See also https://wiki.osdev.org/X86-64_Instruction_Encoding#32.2F64-bit_addressing_2 for tables like the ones in Intel's vol.2 manual.
其他类似的操作码。
This seems to happen with other similar opcodes.
r / m操作数的ModRM编码始终相同。有些操作码需要一个寄存器操作数,有些需要内存,但是实际的ModRM +可选的SIB +可选的位移是固定的,因此无论指令如何,相同的硬件都可以对其进行解码。
ModRM encoding of r/m operands is always the same. Some opcodes require a register operand, and some require memory, but the actual ModRM + optional SIB + optional displacement is fixed so the same hardware can decode it regardless of the instruction.
有几种罕见的操作码,例如 mov al / ax / eax / rax,[qword absolute_address]
,它们的操作数根本不使用ModRM编码,但是任何确实使用相同的格式。
There are a few rare opcodes like mov al/ax/eax/rax, [qword absolute_address]
that don't use ModRM encoding at all for their operands, but any that do use the same format.
这篇关于不允许rbp作为SIB基础吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!