使用 x64 中的 RSP 寄存器对内存操作数进行编码 - 需要 SIB 字节吗?

Encoding memory operands using the RSP register in x64 - SIB byte needed?

我正在尝试了解如何在 x86-64 中对 RSP 寄存器上的读取进行编码。

例如,我有这样的代码:

.section __TEXT,__text
.global _main

_main:
  push %rsp
  push (%rsp)
  mov %rsp, %rax
  mov (%rsp), %rax

当我 assemble 并转储输出时,它看起来像这样:

$ as -o thing.o thing.s && objdump -d thing.o
                                                      
thing.o:        file format mach-o 64-bit x86-64      
                                                      
                                                      
Disassembly of section __TEXT,__text:                 
                                                      
0000000000000000 <add2>:                              
       0: 54                            pushq   %rsp  
       1: ff 34 24                      pushq   (%rsp)
       4: 48 89 e0                      movq    %rsp, %rax
       7: 48 8b 04 24                   movq    (%rsp), %rax

push (%rsp) 变为 ff 34 24。据我了解,0xFF是PUSH的操作码,0x34是Mod/RM编码。我不明白 0x24 来自哪里。这是 SIB 字节吗?这条指令是如何编码的?我似乎无法很好地遵循英特尔手册来弄清楚这个字节的来源。我在 mov (%rsp), %rax.

中看到相同的字节

要对 push (%rsp) 进行编码,请在指令集参考中查找 push 指令。您会看到它被列为 FF /6。然后转到章节 3.1 解释指令参考页 ,特别是指令摘要 Table 中的 3.1.1.1 操作码列部分,其中你会看到:

/digit A digit between 0 and 7 indicates that the ModR/M byte of the instruction uses only the r/m (register or memory) operand. The reg field contains the digit that provides an extension to the instruction's opcode.

要对 (%rsp)(或英特尔语法中的 [rsp])进行编码,您将需要一个 SIB 字节。查阅Table 2-2。具有 ModR/M 字节 的 32 位寻址形式。虽然它说的是 32 位,但它主要适用于 64 位以及逻辑扩展。由于该指令具有 /6 查看倒数第二列,并且带有脚注的 [--][--] 行告诉您这是允许您指定 SIB 字节的行。此单元格中的值为 34(十六进制),因此这就是它的来源。至于SIB字节本身,请参考下Table2-3。具有 SIB 字节 的 32 位寻址形式。您想要标题为 ESP 的列(相当于 RSP 的 32 位)和行 none,它为您提供 24.