"nop dword ptr [rax + rax]"x64汇编指令有什么作用?

c00*_*0fd 10 assembly x86-64 cpu-architecture visual-studio nop

我正在尝试理解x64编译器完成的程序集优化.

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

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

B8 31 00 00 00   mov         eax,31h
0F 1F 44 00 00   nop         dword ptr [rax+rax]
Run Code Online (Sandbox Code Playgroud)

这是一个截图:

在此输入图像描述

据我所知nop本身是do nothing,但我从来没有用那种操作见过它.

有人可以解释它是做什么的吗?

Gle*_*den 10

在本页其他地方的评论中,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.]

Length    Assembly                                     Byte Sequence
-------   ------------------------------------------   --------------------------
1 byte    nop                                          90
2 bytes   66 nop                                       66 90
3 bytes   nop dword ptr [eax]                          0F 1F 00
4 bytes   nop dword ptr [eax + 00h]                    0F 1F 40 00
5 bytes   nop dword ptr [eax + eax*1 + 00h]            0F 1F 44 00 00
6 bytes   66 nop word ptr [eax + eax*1 + 00h]          66 0F 1F 44 00 00
7 bytes   nop dword ptr [eax + 00000000h]              0F 1F 80 00 00 00 00
8 bytes   nop dword ptr [eax + eax*1 + 00000000h]      0F 1F 84 00 00 00 00 00
9 bytes   66 nop word ptr [eax + eax*1 + 00000000h]    66 0F 1F 84 00 00 00 00 00


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

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

nop dword ptr [eax + 00h]
nop dword ptr [eax + 00000000h]
Run Code Online (Sandbox Code Playgroud)

这些仅在前导零的数量上有所不同,并且一些汇编器可能使得难以禁用它们总是编码最短可能字节序列的有用特征,这可能使第二表达式不可访问.

对于多字节NOP情况,您不需要此"帮助",因为您需要确保实际获得所需的字节数.所以问题是如何指定modr/m位的确切组合,以便最终得到所需的disp大小 - 但仅通过指令助记符.这个话题很复杂; 有关详细信息,请参见缩放索引,MOD + R/MSIB.

当然,如果你发现很难或不可能通过指令助记符强制你的汇编程序的合作,你总是可以求助db("定义字节")作为一个简单而安全的替代方案,保证工作.


Bee*_*ope 6

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

这种对齐方式可以帮助提高指令提取带宽,因为指令提取通常以16个字节为单位进行,因此对齐循环的顶部可以最大程度地进行解码而不会出现瓶颈。

可以说,这种对齐的重要性已不如从前重要,因为引入了对对齐不太敏感的循环缓冲区uop缓存。在某些情况下,此优化甚至可能是悲观的,尤其是在循环执行很少的时候。