我正在研究的程序具有以下代码(由IDA分解,并由我进行了一些轻率的审查):

首先,为什么编译器会插入这些nop?它们似乎没有任何对齐目的。

其次,带有相对寻址参数的nop是什么?其十六进制为0F 1F 40 00。查看http://ref.x86asm.net/,这似乎是一条称为“ hintable NOP”的指令,但是我很难找到有关它的相关信息。

下一条指令从....C3开始,并且是真实/有效的指令(即不是nop或任何道德上与nop等效的东西)。

#1 楼

这些是多字节nop指令。
来自http://www.felixcloutier.com/x86/NOP.html


说明

该指令不执行任何操作。它是一个单字节或多字节的
NOP,它占用指令流中的空间,但不影响机器上下文,除了EIP寄存器。

字节格式的NOP在具有以下模型编码的处理器上可用:

多字节NOP指令不会更改
寄存器的内容,并且不会发出内存操作。在非64位模式和64位模式下,指令的
操作相同。

操作

一字节NOP指令是别名助记符。对于XCHG(E)AX,
(E)AX指令。
不支持多字节NOP指令。

该指令的内存操作数形式允许软件创建一个“ no operation”字节序列作为一条指令。对于需要多字节NOP的情况,建议的操作
(32位模式和64位模式)为:

+---------+--------------------------------+------------------------------+
| LENGTH  |           ASSEMBLY             |         BYTE SEQUENCE        |
+---------+--------------------------------+------------------------------+
|         |                                |                              |
| 2 bytes |  66 NOP                        |  66 90H                      |
|         |                                |                              |
| 3 bytes |  NOP DWORD ptr [EAX]           |  0F 1F 00H                   |
|         |                                |                              |
| 4 bytes |  NOP DWORD ptr [EAX + 00H]     |  0F 1F 40 00H                |
|         |                                |                              |
| 5 bytes |  NOP DWORD ptr [EAX + EAX*1 +  |  0F 1F 44 00 00H             |
|         | 00H]                           |                              |
|         |                                |                              |
| 6 bytes |  66 NOP DWORD ptr [EAX + EAX*1 |  66 0F 1F 44 00 00H          |
|         |  + 00H]                        |                              |
|         |                                |                              |
| 7 bytes |  NOP DWORD ptr [EAX + 00000000 |  0F 1F 80 00 00 00 00H       |
|         | H]                             |                              |
|         |                                |                              |
| 8 bytes |  NOP DWORD ptr [EAX + EAX*1 +  |  0F 1F 84 00 00 00 00 00H    |
|         | 00000000H]                     |                              |
|         |                                |                              |
| 9 bytes |  66 NOP DWORD ptr [EAX + EAX*1 |  66 0F 1F 84 00 00 00 00 00H |
|         |  + 00000000H]                  |                              |
+---------+--------------------------------+------------------------------+



评论


Nitpick:该表出现在Intel的官方参考资料中(除非我的记忆欺骗了我,否则描述非常相似)。也许最好将OP指向该点。

–杂件
16年2月9日在9:28

@Jongware:链接的站点是从英特尔文档生成的

–伊戈尔·斯科钦斯基♦
16年2月9日,12:53

#2 楼

关于第一个问题,当编译器有兴趣对齐其后的代码时,NOP是由编译器发出的,通常是因为该代码是跳转的目标(如循环),并且将其与段落对齐是有益的( 16字节边界)或缓存行(32字节边界)。换句话说,这样做是为了提高性能。