翻译一段机器码时遇到的问题
根据INTER IA32手册里call r32
翻译成机器码 应该是 FF /2
请问这个"/2" 是什么意思呢? 看手册前面的说明。
这应该是指令的op/reg/mm字段中op字段的值吧,很久没看,记不清了。 intel 和 AMD文档里没有你标识的这种写法
正确的操作数标识法是:
1、CALL Ap
代表调用目标直接编码在指令编码里,根据指令格式可能是一个远程调用。
2、CALL Jz
代表调用目标是 EIP 寄存器的一个偏移量,偏移量根据指令操作数的有效值可以是 16、32 或 64 位
3、CALL Ev
代表调用目标是内存操作数或者是寄存器操作数,大小依赖有指令数操作有效值。
4、CALL Ep
代表调用目标是内存操作数或者是寄存器操作数,根据指令格式可能是一个远程调用。
一般情况下,编译器生成的格式是 CALL Jz 这种格式,也就是说目标地址依赖于 EIP值。
象以下这条指令:
call *%eax
将会产生 CALL Ev 这种编码格式, 以上这条指令的二进制编码是: FF D0
下面我详细讲解一下是如何编译的:
x86 的指令格式是: prefix + opcode + Mod/RM + SIB + Disp + Imme
指令长度最长是 15 字节,最短是 1 字节。
以 CALL Ev 这种格式编码来讲解:
1、它的 opcode 是 0xff,这个是个特殊的 opcode 它需要配合 Mod/RM 字节。
2、Mod/RM 的格式如下:
00 000 000
--- ---- -----
Mod reg r/m
3、某些 x86 指令编码被分成几个组。 CALL Ev 被分配到 Group 5 里面去,在 Group 5 里的 CALL Ev 这种编码格式它的 Mod/RM中的 /reg 域被固定设为 2。
4、寄存器的编码顺序依次排列为 eax、ecx、edx、ebx、esp、ebp、esi、edi 。它们分别对应于 0、1、2、3、4、5、6、7 共8个编码。
5、根据 Mod/RM 编码表,eax 的编码为:
mod :11
reg: 未知
r/m: 000
6、而 CALL Ev 的 reg 已经固定为 2 ,所以整个操作数 eax 的 Mod/RM 字节编码为:
mod : 11
reg:010
r/m:000
因此,整个 Mod/RM 字节是: 11 010 000 也就是 D0
7、最后 call *%eax这条指令的编码是: FF D0
lz,所说的 call r32 这种格式估计就是 CALL Ev 这种格式, FF /2 中的 /2 是 call 指令被分配到 Group 5 中的第 3 列。注意,这里列是从 0 开始,也就是值 / 2 另外,LZ 可以看看我的 blog 里面有一篇文章是讲如何解析指令的。 讲的很详细啊,很有帮助,谢谢
页:
[1]