/2英特尔文档第 2A 卷中表 2-2 中的平均值查找(表和卷中的 2 与/2那里没有关系)。在左上角的那个表中有/digit. 因此,转到右侧的列并找到/2. 我们会回到那个。
现在,如果您查看call指令定义,您将看到Op/En“操作数编码”。
Op/En Operand 1 Operand 2 Operand 3 Operand 4
D Offset NA NA NA
M ModRM:r/m (r) NA NA NA
还要注意call第一个表中的签名,例如这个,它是 64 位对应的rax用法:
Opcode Instruction Op/En
FF /2 CALL r/m64 M
这M告诉我们M在下面的“操作数编码”(Op/En)表中查找,即:
Op/En Operand 1 Operand 2 Operand 3 Operand 4
M ModRM:r/m (r) NA NA NA
所以操作数 1 是ModRM:r/m (r)。这(r)意味着读取(不写入)操作数。ModRM:r/m 表示操作数有一个 ModRM 字节,带有一个 r/m 值。rin表示“r/m寄存器”,m表示“内存”。
所以回到/2表 2-2 中的列,我们有010,就在说 的那一行REG。这是指 ModRM 中间“reg”段。
据此,我们有:
mod description (relevant to us)
00 register indirect addressing mode
01 one-byte signed displacement follows addressing mode byte(s)
10 four-byte signed displacement follows addressing mode byte(s)
11 register addressing mode
由于我们使用[rax]的是寄存器间接寻址方式,所以00。
所以我们有了 mod 和 reg,现在我们需要 r/m 来完成 ModRM 字节。
从网络上的其他地方:r/m 字段编码使用哪个寄存器。如果我们回到表 2-2 和该列,并将其与左侧/2的 Mod 框匹配,并且我们使用该行(与您在 中使用的相同),我们将在. 同样,如果我们按照行(与您的相同),我们得到. 这给了我们:00EAXRAXcall [rax]10ECXRCXcall [rcx]11
FF 10 call [rax]
FF 11 call [rcx]
请注意,该表也显示了 r/m 值:000forrax和001for rcx。这给了我们最终的 ModRM 字节。
ModRM for hex
00.010.000 rax 10
00.010.001 rcx 11
还要注意,如果你这样做call [eax],它的前缀67是十六进制:
67 FF 01
这对应于“地址大小覆盖前缀”。