20

我试图了解x64编译器完成的程序集优化。

我在 Windows 8.1 上Release使用IDE编译了一个小型 C++ 项目。Visual Studio 2008 SP1

其中一行包含以下汇编代码:

B8 31 00 00 00   mov         eax,31h
0F 1F 44 00 00   nop         dword ptr [rax+rax]

这是一个屏幕截图:

在此处输入图像描述

据我所知nop,它本身是do nothing,但我从未见过这样的操作数。

有人可以解释它的作用吗?

4

3 回答 3

22

在本页其他地方的评论中, Michael Petch指向一个描述Intel x86多字节 NOP 操作码的网页。该页面有一个有用信息表,但不幸的是 HTML 被弄乱了,因此您无法阅读。以下是该页面中的一些信息,以及该表格提供了一种可读的形式:

多字节 NOP
http://www.felixcloutier.com/x86/NOP.html
单字节 NOP 指令是 XCHG (E)AX, (E)AX 指令的别名助记符。

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

指令的内存操作数形式允许软件创建一个“无操作”的字节序列作为一条指令。

对于需要多字节 NOP 的情况,推荐的操作(32 位模式和 64 位模式)是: [我的编辑:在 64 位模式下,写rax而不是eax. ]

长度组装字节序列
------- ---------------------------------------------- - -------------------------
1 字节 nop 90
2 字节 66 nop 66 90
3 字节 nop dword ptr [eax] 0F 1F 00
4 字节 nop dword ptr [eax + 00h] 0F 1F 40 00
5 字节 nop dword ptr [eax + eax*1 + 00h] 0F 1F 44 00 00
6 字节 66 nop 字 ptr [eax + eax*1 + 00h] 66 0F 1F 44 00 00
7 字节 nop dword ptr [eax + 00000000h] 0F 1F 80 00 00 00 00
8 字节 nop dword ptr [eax + eax*1 + 00000000h] 0F 1F 84 00 00 00 00 00
9 字节 66 nop 字 ptr [eax + eax*1 + 00000000h] 66 0F 1F 84 00 00 00 00 00


请注意,选择正确字节序列的技术——以及所需的总大小——可能会根据您使用的汇编程序而有所不同。

例如,从表中取出的以下两行组装表面上是相似的:

nop dword ptr [eax + 00h]
nop dword ptr [eax + 00000000h]

它们仅在前导零的数量上有所不同,并且某些汇编程序可能很难禁用始终编码尽可能短的字节序列的“有用”功能,这可能会使第二个表达式无法访问。

对于多字节 NOP 情况,您不需要这种“帮助”,因为您需要确保实际获得所需的字节数。所以问题是如何指定modr/m位的精确组合,最终得到所需的disp大小——但仅通过指令助记符。这个主题很复杂,当然超出了我的知识范围,但是Scaled IndexingMOD+R/MSIB可能是一个起点。

现在我知道你只是在想,如果你发现很难或不可能通过指令助记符强制你的汇编程序的合作,你总是可以诉诸db(“定义字节”)作为一个简单的简单的替代方案,嗯,保证工作。

于 2018-05-29T22:57:28.960 回答
9

正如评论中所指出的,当该指令是循环中的第一条指令时,它是一个多字节 NOP ,通常用于将后续指令与 16 字节边界对齐。

这种对齐有助于提高指令获取带宽,因为指令获取通常以 16 字节为单位进行,因此对齐循环顶部提供了解码发生而没有瓶颈的最大机会。

这种对齐的重要性可以说没有以前那么重要了,因为引入了对对齐不太敏感的循环缓冲区uop 缓存。在某些情况下,这种优化甚至可能是一种悲观化,尤其是当循环执行次数很少时。

于 2017-05-17T23:43:19.267 回答
1

当使用跳转指令执行从较大地址到较低地址(0EBh XX - jmp short)和(0E9h XX XX XX XX - jmp near)的跳转时,完成此代码对齐,其中 XX 在两种情况下都是带符号的负数。因此,编译器将需要执行跳转的代码块对齐到 10h 字节边界。这将提供优化和代码执行加速。

于 2020-03-01T08:29:02.420 回答