rbp 不允许作为 SIB 基础?

2024-02-22

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

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

mov    [rbp+rcx], al

汇编器当前正在生成:

88 04 0D

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

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


也可以看看https://wiki.osdev.org/X86-64_Instruction_Encoding#32.2F64-bit_addressing_2 https://wiki.osdev.org/X86-64_Instruction_Encoding#32.2F64-bit_addressing_2或英特尔的第 2 卷手册,了解这些特殊情况的编码表和脚注。这个答案指出了特殊情况,并讨论了为什么这些设计选择有意义,即他们需要解决什么设计问题。


编码意味着rbp是无基址寄存器的转义码(只是 SIB 中的 disp32 或 ModRM 中与 RIP 相关的 rel32)。大多数组装工组装[rbp] into [rbp + disp8=0].

由于您不需要缩放它,因此使用[rcx + rbp]而是为了避免需要 disp8=0,因为rbp can成为一个索引。

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


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

(来自我写的一个答案为什么rbp和rsp被称为通用寄存器? https://stackoverflow.com/questions/36529449/why-are-rbp-and-rsp-called-general-purpose-registers/51347294#51347294)。这个问题看起来是复制或移植本节的最佳位置。

rbp/r13不能是没有位移的基址寄存器:该编码意味着:(在 ModRM 中)rel32(RIP 相关),或(在 SIB 中)disp32没有基址寄存器。 (r13在 ModRM/SIB 中使用相同的 3 位,因此此选择通过不使指令长度解码器查看来简化解码REX.B 位 https://wiki.osdev.org/X86-64_Instruction_Encoding#Encoding获取第四个基址寄存器位)。[r13]组装到[r13 + disp8=0]. [r13+rdx]组装到[rdx+r13](当可以选择时通过交换基数/索引来避免问题)。

rsp/r12作为基址寄存器总是需要一个 SIB 字节。 (base=RSP 的 ModR/M 编码是转义码,用于表示 SIB 字节,同样,更多解码器必须关心 REX 前缀,如果r12的处理方式有所不同)。

rsp不能是索引寄存器。这使得编码成为可能[rsp],这比[rsp + rsp]。 (Intel 可以为 32 位寻址模式设计 ModRM/SIB 编码(386 中的新功能),因此只有在 base=ESP 的情况下才可能实现无索引的 SIB。这将使[eax + esp*4]可能且仅排除[esp + esp*1/2/4/8]。但这没有用,因此他们通过将 index=ESP 设为无索引的代码(无论基数如何)来简化硬件。这允许两种冗余方式对任何基址或基址+显示寻址模式进行编码:带或不带 SIB。)

r12 can是一个索引寄存器。与其他情况不同,这不会影响指令长度解码。此外,它无法像其他情况那样使用更长的编码来解决。 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

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


其他类似的操作码似乎也会发生这种情况。

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

rbp 不允许作为 SIB 基础? 的相关文章

随机推荐