为什么Visual Studio中使用XCHG斧,斧

问题描述 投票:28回答:6

我一直在寻找通过我的节目disassmbly(因为它崩溃),并发现大量的

xchg    ax, ax

我GOOGLE了它,发现它本质上是一个NOP,但为什么视觉工作室做的,而不是XCHG一个空操作的?

该应用程序是一个C#.NET3.5 64位应用程序,通过视觉工作室编译

assembly code-generation x86-64
6个回答
37
投票

在x86的NOP指令XCHG AX, AX

2个助记指令组装以相同的二进制运算码。 (其实,我想一个汇编程序可以使用寄存器的任何xchg与本身,而是AXEAX是什么通常用于nop据我所知)。

xchg ax, ax有没有改变寄存器值,并没有改变标志的特性(哎 - !这是一个无操作)。


编辑(响应于匿名评论。):

哦,对了 - 现在我还记得有几个编码为xchg指令。一些采取一个模/ R / M组比特(如许多Intel x86架构指令)指定的源和目的地。这些编码需要超过一个字节。还有使用单字节和交换通用寄存器与(E)AX一个特殊的编码。如果指定的寄存器也是(E)AX那么你有一个单字节NOP指令。你还可以指定(E)AX自身使用xchg指令的更大的变种进行交换。

我猜测,MSVC使用xchg的多字节版本(E)AX为源,当它要咀嚼超过一个字节为无操作的目的地 - 它需要的周期数相同的单字节xchg的,但会占用更多空间。在拆卸你不会看到解码为xchg多字节NOP,即使结果是一样的。

具体xchg eax, eaxnop可能取决于你是否希望它使用了1或2个字节编码为操作码0x900x87 0xc0。在Visual Studio反汇编器(也可能是其他人)将解码的操作码0x90作为NOP指令,将操作码解码0x87 0xc0作为xchg eax, eax

它已经有一段时间,因为我已经做了详细的汇编语言的工作,所以机会是我错了,就至少有一点是这里...


9
投票

xchg ax,axnop实际上是相同的指令,它们映射到相同的操作码(0×90这个)。这很好,xchg ax,ax是一个无操作。为什么要浪费额外的操作码的编码与不做什么指示?

质疑的是,为什么你看到印双方助记符。我想这只是在你的拆卸一大败笔,没有二元差异。


7
投票

其实,xchg ax,ax是MS多么拆解 “66 90”。 66是操作数尺寸替换,因此它理应上ax代替eax操作。然而,CPU仍然执行它作为一个NOP。 66前缀在这里用来使指令在大小两个字节,通常是为了对准目的。


4
投票

MSVC把NOP处于编译后的代码进行调试版本,一般。这使得编辑和继续工作。


2
投票

我不知道是否有什么做的问题,但许多Windows函数开始MOV EDI,EDI。这也是一个2字节NOP。两个字节NOP的是hotpatch代码很有用,因为你可以放心地使用短JMP替换它。

参考:http://blogs.msdn.com/b/oldnewthing/archive/2011/09/21/10214405.aspx


1
投票

这里真正的问题是;为什么反汇编器选择显示为xchg ax,ax而不是nop

我怀疑这是从32位或64位的代码和(假定拆装显示xchg ax,ax和不xchg eax,eax),其有用于使nop稍大的操作数大小覆盖前缀(达到一定量的填充用更少的指令);和前缀的存在混淆造成xchg ax,ax(而不是nopo16 nop)反汇编。

© www.soinside.com 2019 - 2024. All rights reserved.