我一直在寻找通过我的节目disassmbly(因为它崩溃),并发现大量的
xchg ax, ax
我GOOGLE了它,发现它本质上是一个NOP,但为什么视觉工作室做的,而不是XCHG一个空操作的?
该应用程序是一个C#.NET3.5 64位应用程序,通过视觉工作室编译
在x86的NOP
指令XCHG AX, AX
2个助记指令组装以相同的二进制运算码。
(其实,我想一个汇编程序可以使用寄存器的任何xchg
与本身,而是AX
或EAX
是什么通常用于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, eax
或nop
可能取决于你是否希望它使用了1或2个字节编码为操作码0x90
或0x87 0xc0
。在Visual Studio反汇编器(也可能是其他人)将解码的操作码0x90
作为NOP
指令,将操作码解码0x87 0xc0
作为xchg eax, eax
。
它已经有一段时间,因为我已经做了详细的汇编语言的工作,所以机会是我错了,就至少有一点是这里...
xchg ax,ax
和nop
实际上是相同的指令,它们映射到相同的操作码(0×90这个)。这很好,xchg ax,ax
是一个无操作。为什么要浪费额外的操作码的编码与不做什么指示?
质疑的是,为什么你看到印双方助记符。我想这只是在你的拆卸一大败笔,没有二元差异。
其实,xchg ax,ax
是MS多么拆解 “66 90”。 66是操作数尺寸替换,因此它理应上ax
代替eax
操作。然而,CPU仍然执行它作为一个NOP。 66前缀在这里用来使指令在大小两个字节,通常是为了对准目的。
MSVC把NOP处于编译后的代码进行调试版本,一般。这使得编辑和继续工作。
我不知道是否有什么做的问题,但许多Windows函数开始MOV EDI,EDI。这也是一个2字节NOP。两个字节NOP的是hotpatch代码很有用,因为你可以放心地使用短JMP替换它。
参考:http://blogs.msdn.com/b/oldnewthing/archive/2011/09/21/10214405.aspx
这里真正的问题是;为什么反汇编器选择显示为xchg ax,ax
而不是nop
?
我怀疑这是从32位或64位的代码和(假定拆装显示xchg ax,ax
和不xchg eax,eax
),其有用于使nop
稍大的操作数大小覆盖前缀(达到一定量的填充用更少的指令);和前缀的存在混淆造成xchg ax,ax
(而不是nop
或o16 nop
)反汇编。