私は自分のプログラムの逆アセンブルを調べていました (クラッシュしたため)。
xchg ax, ax
私はそれをグーグルで検索し、それが本質的にnopであることがわかりましたが、なぜビジュアルスタジオはnoopではなくxchgを行うのですか?
アプリケーションは、Visual Studio によってコンパイルされた C# .NET3.5 64 ビット アプリケーションです。
私は自分のプログラムの逆アセンブルを調べていました (クラッシュしたため)。
xchg ax, ax
私はそれをグーグルで検索し、それが本質的にnopであることがわかりましたが、なぜビジュアルスタジオはnoopではなくxchgを行うのですか?
アプリケーションは、Visual Studio によってコンパイルされた C# .NET3.5 64 ビット アプリケーションです。
x86 では、NOP
命令は次のとおりです。 XCHG AX, AX
2 つのニーモニック命令は、同じバイナリ オペコードにアセンブルされます。(実際、アセンブラはxchg
それ自体で任意のレジスタを使用できると思いますが、AX
私が知る限りEAX
、通常はレジスタに使用されます)。nop
xchg ax, ax
レジスタ値を変更せず、フラグを変更しないというプロパティがあります(ねえ-それはノーオペレーションです!)。
編集(アノンのコメントに応じて):
そうそう、命令にはいくつかのエンコーディングがあることを覚えていxchg
ます。ソースと宛先を指定する mod/r/m ビット セット (多くの Intel x86 アーキテクチャ命令と同様) を使用するものもあります。これらのエンコーディングには 1 バイト以上かかります。1 バイトを使用し、汎用レジスタを と交換する特別なエンコーディングもあります(E)AX
。指定されたレジスタも(E)AX
同じである場合は、1 バイトの NOP 命令があります。(E)AX
命令のより大きなバリアントを使用して、それ自体と交換するように指定することもできますxchg
。
MSVC は、操作なしで 1 バイト以上を処理したい場合に、xchg
withの複数バイト バージョンをソースおよび宛先として使用していると推測しています。逆アセンブリでは、結果が同じであっても、マルチバイトが としてデコードされていることはわかりません。(E)AX
xchg
xchg
NOP
具体的には、オペコードとしてエンコードするか、1 バイトxchg eax, eax
または2 バイトを使用するかどうかに応じてエンコードできます。Visual Studio 逆アセンブラー (およびおそらく他のもの) は、オペコードを命令としてデコードし、オペコードをとしてデコードします。nop
0x90
0x87 0xc0
0x90
NOP
0x87 0xc0
xchg eax, eax
詳細なアセンブリ言語の作業を行ってからしばらく経っているので、ここで少なくとも 1 つの点で間違っている可能性があります...
xchg ax,ax
これらは実際にnop
は同じ命令であり、同じオペコード (0x90 iirc) にマップされます。それは問題xchg ax,ax
ありません。No-Op です。何もしない命令で余分なオペコード エンコーディングを無駄にする必要があるのはなぜですか?
疑わしいのは、両方のニーモニックが表示される理由です。それはあなたの逆アセンブルの単なる欠陥だと思います。バイナリの違いはありません。
実際、xchg ax,ax
MSが「66 90」を分解する方法です。66 はオペランド サイズのオーバーライドであるため、ax
の代わりに動作すると思われますeax
。ただし、CPU はこれを nop として実行します。66 プレフィックスは、命令のサイズを 2 バイトにするためにここで使用されます。これは通常、アライメントの目的で行われます。
通常、MSVC は、デバッグ ビルド用にコンパイルされたコードに NOP を配置します。これにより、エディット コンティニュが機能します。