是的,正如您所发现的,它遵循简单的二进制编号,使用 REX 位作为前导位,将 ModRM 位作为低 3 位来对寄存器编号进行编码。 8 = 二进制的 1000,这就是 R8 的编码。
https://wiki.osdev.org/X86-64_Instruction_Encoding#Encoding解释得很好,并且https://wiki.osdev.org/X86-64_Instruction_Encoding#Registers甚至还有一张桌子。
我搜索了英特尔的第 2 卷 PDFr14
(这对于任何事情来说都不是“特殊”的,并且可能只会出现在表格中)。那里are第 2 卷中的一些表,但不是简单 ModRM 本身的表。 (合并后的 PDF 太大,无法使用)。
Vol.2 does清楚地描述了REX字段如何与ModRM字段结合以构成4位寄存器numbers。 (例如,图 2-4 显示了 REX.B 和 ModRM.rm 以及 REX.R 和 ModRM.r 的串联)。我没有检查第 1 卷 - 如果有关寄存器的一些声明我不会感到惊讶names(由汇编器使用)可以在那里找到匹配的二进制寄存器号。名称仅对汇编程序有意义,在机器代码中没有意义,这一点在第 2 卷中有明确记录。
然而,信息is第2卷中有:
它确实有表 3-1。与 +rb、+rw、+rd、+ro 相关的寄存器代码(续)对于没有 ModRM 的指令,其中操作码字节的低 3 位是寄存器编号的低 3 位。 (如push/pop r64 的短编码)。
Reg |
REX.B |
Reg field |
R13B |
Yes |
5 |
R14B |
Yes |
6 |
依此类推,每个寄存器都有行,还有 R14W、R14D、R14 的字、双字和 qword 大小的 3 组列。因此,如果您对二进制数映射到寄存器名称的事实有疑问,该表会清楚地说明这一点。 (如果假设寄存器编号在这里与其他上下文中的工作方式不同,那就太疯狂了。)
还有一字节操作码的操作码映射,其中push rSI/r14
共享一个条目 (0x58),与 2 字节操作码映射中的 xchg-with-(e)ax、mov-immediate 到 byte-reg、pop、mov-immediate 到 word/dword/qword-reg 以及 bswap 相同。同样,如果这些寄存器编号的工作方式与其他地方的寄存器编号不同,那将是疯狂的。
有一整桌表 2-8。 VEX.vvvv 注册名称映射,带有 xmm/ymm0..15 和 RAX/EAX .. R15/R15D。 (VEX.vvvv 可以为 BMI 指令编码整数寄存器,例如andn,是的,它们仅针对 dword 或 qword 进行记录,不能使用 a 覆盖字操作数大小66
字首。)
表 2-13。 SIB 字节的 32 位 VSIB 寻址形式也是相关的,显示 ESI/R14D 等列。 (在 64 位模式下,您通常不会使用 67 地址大小的前缀vpgatherdd
或其他什么,但你可以。 64 位地址大小没有单独的表。)该表没有明确提及howVEX.B 在两个寄存器之间选择给定的位 2:0 值,但这显然应该来自其他情况。