21

nopwこのコンパイラ出力では、命令のマシンコードエンコーディングがどのように機能するかを理解しようとしています。

00000000004004d0 <main>:
  4004d0:       eb fe                   jmp    4004d0 <main>
  4004d2:       66 66 66 66 66 2e 0f    nopw   %cs:0x0(%rax,%rax,1)
  4004d9:       1f 84 00 00 00 00 00

http://john.freml.in/amd64-noplで、「nopw」に関するいくつかの議論があります。4004d2-4004e0の意味を誰かが説明できますか?オペコードリストを見ると、66 ..コードはマルチバイト拡張であるように見えます。数時間オペコードリストを調べようとしない限り、ここではおそらく私よりも良い答えを得ることができると思います。


そのasm出力は、Cの次の(非常識な)コードからのものであり、単純な無限ループに最適化されます。

long i = 0;

main() {
    recurse();
}

recurse() {
    i++;
    recurse();
}

でコンパイルするとgcc -O2、コンパイラは無限再帰を認識し、それを無限ループに変換します。main()実際、これは非常にうまく機能するため、関数を呼び出さずに実際にループしrecurse()ます。


編集者注:NOPを使用したパディング関数は、無限ループに固有のものではありません。これは、Godboltコンパイラエクスプローラーにある、さまざまな長さのNOPを持つ関数のセットです。

4

4 に答える 4

25

バイトは「0x66Operand-SizeOverride」プレフィックスです。これらを複数持つことは、1つ持つことと同じです。

これ0x2eは、64ビットモードでは「nullプレフィックス」です(それ以外の場合はCS:セグメントオーバーライドです。これが、アセンブリニーモニックに表示される理由です)。

0x0f 0x1fModRMバイトを使用するNOPの2バイトのオペコードです

0x84ModRMバイトであり、この場合、さらに5バイトを使用するアドレッシングモードをコード化します。

一部のCPUは、多くのプレフィックス(たとえば、3つ以上)を持つ命令のデコードに時間がかかるため、SIB + disp32を指定するModRMバイトは、5バイト以上のプレフィックスバイトを使用するよりもはるかに優れた方法です。

AgnerFogのmicroarchpdfのAMDK8デコーダー

各命令デコーダは、クロックサイクルごとに3つのプレフィックスを処理できます。これは、それぞれ3つのプレフィックスを持つ3つの命令を同じクロックサイクルでデコードできることを意味します。プレフィックスが4〜6の命令は、デコードするのに余分なクロックサイクルが必要です。


基本的に、これらのバイトは1つの長いNOP命令であり、とにかく実行されることはありません。コンパイラーが.p2align 4ディレクティブを発行したため、次の関数が16バイト境界に整列されるようにするために、そこにあります。そのため、アセンブラーにはNOPが埋め込まれます。 x86のgccのデフォルトはです
-falign-functions=16
。実行されるNOPの場合、long-NOPの最適な選択はマイクロアーキテクチャに依存します。IntelSilvermontやAMDK8など、多くのプレフィックスをチョークするマイクロアーキテクチャの場合、それぞれ3つのプレフィックスを持つ2つのNOPの方がデコードが高速である可能性があります。

質問にリンクされているブログ記事(http://john.freml.in/amd64-nopl)は、コンパイラが単一バイトの0x90NOP命令の束ではなく複雑な単一のNOP命令を使用する理由を説明しています。

命令エンコーディングの詳細については、AMDの技術参照ドキュメントを参照してください。

主に「AMD64アーキテクチャプログラマーズマニュアル第3巻:汎用およびシステムの説明」にあります。x64アーキテクチャに関するIntelのテクニカルリファレンスにも同じ情報が含まれていると確信しています(さらに理解しやすいかもしれません)。

于 2011-01-25T21:43:36.650 に答える
3

アセンブラ(コンパイラではない)は、次のアライメント境界までコードをパディングし、それに適合すると判断できる最長のNOP命令を使用します。これはあなたが見ているものです。

于 2011-01-25T23:23:28.737 に答える
0

これは単なる分岐遅延命令だと思います。

于 2011-01-25T20:20:51.207 に答える
-3

私はnopwががらくたであると信じています-私はあなたのプログラムで決して読まれないので、それを増やす必要はありません。

于 2011-01-25T21:28:37.483 に答える