/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 值。r
in表示“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 框匹配,并且我们使用该行(与您在 中使用的相同),我们将在. 同样,如果我们按照行(与您的相同),我们得到. 这给了我们:00
EAX
RAX
call [rax]
10
ECX
RCX
call [rcx]
11
FF 10 call [rax]
FF 11 call [rcx]
请注意,该表也显示了 r/m 值:000
forrax
和001
for rcx
。这给了我们最终的 ModRM 字节。
ModRM for hex
00.010.000 rax 10
00.010.001 rcx 11
还要注意,如果你这样做call [eax]
,它的前缀67
是十六进制:
67 FF 01
这对应于“地址大小覆盖前缀”。