您如何理解 x86-64 汇编的“REX.W + B8+ rd io”形式?

Hap*_*rry 2 assembly x86-64 nasm machine-code instruction-encoding

我最初试图生成立即移动到 64 位寄存器的字节。我想要的具体操作是

mov rdi, 0x1337
Run Code Online (Sandbox Code Playgroud)

使用https://www.felixcloutier.com/x86/mov,我看到的唯一非符号扩展指令是

REX.W + B8+ rd io
Run Code Online (Sandbox Code Playgroud)

这让我很困惑,所以我创建了一个小型汇编程序来查看汇编器会生成什么

          global    _start

          section   .text
_start:   
          mov       rdi, 0x1337 
          syscall                           
          mov       rax, 60                 
          xor       rdi, rdi                
          syscall                           
Run Code Online (Sandbox Code Playgroud)

我必须关闭优化,以便迁移到 64 位寄存器。所以我编译nasm -felf64 -O0 main.asm && ld main.o并生成了一个a.out. 我看着objdump -M intel -d ./a.out这行

48 bf 37 13 00 00 00    movabs rdi,0x1337  
Run Code Online (Sandbox Code Playgroud)

那条线看起来一点也不像

REX.W + B8+ rd io
Run Code Online (Sandbox Code Playgroud)

大部头书?另外,经过一些研究,我发现该命令应该是 10 个字节。你如何从 得到它REX.W + B8+ rd io

har*_*old 5

B8+ rd表示操作数(寄存器)编码在操作码的低 3 位中,而不是 ModR/M 字节中。

\n

从英特尔软件开发人员手册中,

\n
\n

+rb, +rw, +rd, +ro \xe2\x80\x94 表示操作码字节的低 3 位用于对寄存器操作数进行编码,\n不带 modR/M 字节。该指令列出了低3位操作码字节对应的十六进制值为000b。在非 64 位模式下,寄存器代码(从 0 到 7)将添加到操作码字节的十六进制值中。在64位模式下,表示REX.b的四位字段,opcode[2:0]字段编码指令的寄存器\操作数。\xe2\x80\x9c+ro\xe2\x80\x9d 仅适用于 64 位模式。

\n
\n

看起来 Intel 想要使用+ro以这种方式编码的 64 位操作数,但实际上并没有这样做。不仅在mov引理中,而且在我能找到的任何地方。例如 64 位push,本来pop可以有+ ro,但他们也有+ rd。而“Indicate d ”很可能是一个拼写错误,文本的其余部分使用现在时。

\n

寄存器(e/r)di编号为 7, 和B8 + 7 = BF,解释操作码。

\n

io代表 qword 立即数(o 代表 octo,也许是 8 个字节?)。

\n

REX 前缀(40 表示基本前缀,+8 设置 W 位,可选 +1 设置 B 位以访问 R8..R15)、操作码、ModR/M 字节和 8 字节立即数,加起来最多 10 个字节。

\n