Ale*_*der 4 x86 assembly encoding intel machine-code
我在VS2017中调试了以下代码(请注意下面的断点):
接下来,您会发现上面提到的断点的反汇编:
如上图所示,编译器为该指令生成的机器代码call dword ptr [fp]是FF 55 F8,其中FF是调用指令的操作码,55是ModeR/M字节的值,F8是值为-8的8位位移,将在下面解释。
现在,如果您查看下面的“表2-2:具有ModeR / M的32位寻址形式”字节,该字节是从英特尔的“ 64 IA-32体系结构软件开发人员手册”第2A卷获得的,上面提到的55号对应于一个有效地址[EBP]+disp8。也就是说,CALL汇编器中的指令将跳转到其地址是从寄存器EBP中的地址加上上述值-8的8位位移获得的指令。这个地址是正确的。它对应于一条JMP指令的地址,该地址最终将代码传递给函数f。
因此,一切看起来都很好。但是我缺少一个重要的点:我应该已经ModeR/M使用英特尔手册中的CALL指令参考以及上面的表2.2 获取了该字节。但是我仍然不知道该怎么做。任何提示都会受到高度赞赏,因为我已经为此工作了几天,而我对此一无所知。
您所缺少的是操作码的一部分被编码为ModR / M字节。通常,ModR / M字节编码两个操作数。第一个操作数是表左侧行标签中给出的寄存器或内存操作数,而第二个操作数是由表顶部列标题给出的寄存器。对于只有一个操作数的指令(例如CALL指令),第二个操作数将用于提供其他操作码位。
如果查看CALL指令的文档,您会发现“调用r / m32中给出的绝对,间接间接地址”指令的操作码列为FF /2。该/2指示在MODR / M字节的附加操作码位在这指令值2。然后,如果您查看“(以十进制表示)/ digit(操作码)”列标题,则会看到数字2出现在该列的开头。如果您向下看该列,您会55在标有“ [EBP] + disp8”的行上看到。
指令摘要表(无VEX前缀的指令)中的“英特尔软件开发人员手册第二卷”的第3.1.1.1节“操作码”列中对此进行了说明:
- / digit — 0到7之间的数字表示指令的ModR / M字节仅使用r / m(寄存器或存储器)操作数。reg字段包含提供指令操作码扩展名的数字。
您唯一缺少的另一件事是call dword ptr [fp]反汇编程序生成的文本。它从未组装过,如何组装取决于如何fp定义。反汇编程序从调试信息中知道编译器生成了局部变量fp在堆栈中的位置,并知道[ebp - 8]可用于访问它。之所以显示它fp,是[ebp - 8]因为前者在大多数情况下会更有意义。取消选中“显示符号名称”,以后应该可以看到。
请注意,该call std::operator<<std:char_traits<char> >行不能不管如何组装std,operator等被定义的,因此表明,你看是不是实际上意味着拆卸组装。反汇编程序通常是这种情况。输出的目的是提供信息,比查看十六进制字节序列更好。这并不是一个可逆的过程。
| 归档时间: |
|
| 查看次数: |
74 次 |
| 最近记录: |