在 x86_64 中带参数的 nop

逆向工程 x86
2021-06-23 05:22:29

我正在调查的一个程序有以下代码(由 IDA 反汇编,我进行了一些轻微的审查):

__text:....B9                 call    <redacted>
__text:....BE                 nop
__text:....BF                 nop     dword ptr [rax+00h]

我有两个问题。首先,为什么编译器会插入这些nops?它们似乎不用于任何对齐目的。

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

顺便说一下,下一条指令开始于....C3并且是一个真正的/生产性指令(即,不是 anop或任何道德上等同于 a 的东西nop)。

2个回答

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

描述

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

NOP 的多字节形式可用于具有模型编码的处理器:

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

手术

一字节的 NOP 指令是 XCHG (E)AX, (E)AX 指令的别名助记符。

多字节 NOP 指令对支持的处理器不执行任何操作,并在不支持多字节 NOP 指令的处理器上产生未定义的操作码异常。

指令的内存操作数形式允许软件创建一个“无操作”的字节序列作为一条指令。对于需要多字节 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]                  |                              |
+---------+--------------------------------+------------------------------+

关于你的第一个问题,NOP当编译器有兴趣对齐它后面的代码时,它会发出 s ,通常是因为该代码是跳转的目标(例如在循环中)并且它与段落对齐是有益的(16 -byte 边界)或缓存行(32 字节边界)。

换句话说,它这样做是为了提高性能。