不允许rbp作为SIB基础吗? [英] rbp not allowed as SIB base?

查看:93
本文介绍了不允许rbp作为SIB基础吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆