34

私は自分のプログラムの逆アセンブルを調べていました (クラッシュしたため)。

xchg    ax, ax

私はそれをグーグルで検索し、それが本質的にnopであることがわかりましたが、なぜビジュアルスタジオはnoopではなくxchgを行うのですか?

アプリケーションは、Visual Studio によってコンパイルされた C# .NET3.5 64 ビット アプリケーションです。

4

6 に答える 6

42

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 バイト以上を処理したい場合に、xchgwithの複数バイト バージョンをソースおよび宛先として使用していると推測しています。逆アセンブリでは、結果が同じであっても、マルチバイトが としてデコードされていることはわかりません。(E)AXxchgxchgNOP

具体的には、オペコードとしてエンコードするか、1 バイトxchg eax, eaxまたは2 バイトを使用するかどうかに応じてエンコードできます。Visual Studio 逆アセンブラー (およびおそらく他のもの) は、オペコードを命令としてデコードし、オペコードをとしてデコードします。nop0x900x87 0xc00x90NOP0x87 0xc0xchg eax, eax

詳細なアセンブリ言語の作業を行ってからしばらく経っているので、ここで少なくとも 1 つの点で間違っている可能性があります...

于 2010-01-25T22:13:49.653 に答える
10

xchg ax,axこれらは実際にnopは同じ命令であり、同じオペコード (0x90 iirc) にマップされます。それは問題xchg ax,ax ありません。No-Op です。何もしない命令で余分なオペコード エンコーディングを無駄にする必要があるのはなぜですか?

疑わしいのは、両方のニーモニックが表示される理由です。それはあなたの逆アセンブルの単なる欠陥だと思います。バイナリの違いはありません。

于 2010-01-25T22:14:09.320 に答える
7

実際、xchg ax,axMSが「66 90」を分解する方法です。66 はオペランド サイズのオーバーライドであるため、axの代わりに動作すると思われますeax。ただし、CPU はこれを nop として実行します。66 プレフィックスは、命令のサイズを 2 バイトにするためにここで使用されます。これは通常、アライメントの目的で行われます。

于 2012-01-09T12:13:07.077 に答える
4

通常、MSVC は、デバッグ ビルド用にコンパイルされたコードに NOP を配置します。これにより、エディット コンティニュが機能します。

于 2010-01-26T02:58:24.443 に答える