[解決済み] AMD64 -- nopw アセンブリ命令?
質問内容
このコンパイラの出力で、機械語コード化された
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
nopw"については、以下のサイトで議論されています。
http://john.freml.in/amd64-nopl
. 4004d2-4004e0 の意味を説明できる人はいますか?オペコードリストを見る限り、どうやら
66 ..
のコードはマルチバイト展開です。おそらく、私が数時間にわたってオペコードリストを理解しようとしない限り、ここでこれに対するより良い答えを得ることができるような気がします。
このasmの出力は、C言語の次の(非常識な)コードによるもので、単純な無限ループに最適化されています。
long i = 0;
main() {
recurse();
}
recurse() {
i++;
recurse();
}
でコンパイルした場合
gcc -O2
このため、コンパイラは無限再帰を認識し、無限ループに変換します。
main()
を呼び出すことなく
recurse()
関数を使用します。
編集部注:NOPsで関数を水増しするのは、無限ループに限ったことではありません。 以下は、NOPの長さの幅がある関数のセットです。 をGodboltコンパイラエクスプローラーに追加しました。
解決方法は?
その
0x66
バイトは "Operand-Size Override" の接頭辞です。これを複数個持つことは、1個持つことと同じです。
は、その
0x2e
は、64 ビットモードでは「ヌル接頭辞」です(それ以外の場合は CS: セグメントのオーバーライドであり、アセンブリ ニーモニックに表示されるのはそのためです)。
0x0f 0x1f
はModRMバイトを受け取るNOPの2バイトオペコードです
0x84
は
ModRMバイト
この場合、さらに5バイトを使用するアドレス指定モードを意味します。
CPUによっては、プレフィックスが多い(例えば3つ以上)命令のデコードが遅いので、SIB + disp32を指定するModRMバイトは、プレフィックスバイトを5つ増やすよりも、5バイト余分に使い切る方がはるかに良い方法です。
<ブロッククオートAgner FogのmicroarchにあるAMD K8デコーダーのpdf :
各命令デコーダは、1クロックあたり3つのプリフィックスを処理することができます。 サイクルです。つまり、3つのプリフィックスを持つ3つの命令が、それぞれ 同じクロックサイクルでデコードされます。4〜6個のプリフィックスを持つ命令 は、デコードに余分なクロックサイクルを必要とします。
基本的に、これらのバイトは1つの長いNOP命令であり、いずれにせよ実行されることはないでしょう。 これは、次の関数が16バイト境界にアラインされていることを確認するためのもので、コンパイラが
.p2align 4
ディレクティブがあるため、アセンブラはNOPで水増ししています。
gcc の x86 用のデフォルトは
-falign-functions=16
. 実行されるNOPの場合、long-NOPの最適な選択はマイクロアーキテクチャに依存します。 Intel Silvermont や AMD K8 のように、多くのプリフィックスで詰まるマイクロアーキテクチャの場合、3 つのプリフィックスを持つ 2 つの NOP の方が速くデコードできたかもしれません。
質問のリンク先のブログ記事( http://john.freml.in/amd64-nopl ) は、コンパイラが1バイトの0x90 NOP命令の束ではなく、複雑な1つのNOP命令を使用する理由を説明しています。
命令のエンコードに関する詳細は、AMDのtech refドキュメントに記載されています。
主に「"AMD64 Architecture Programmer's Manual Volume 3: General Purpose and System Instructions"」に記載されています。 Intelのx64アーキテクチャの技術資料にも同じ情報が載っているはずです(もっと分かりやすいかもしれません)。
関連
-
[解決済み] Connect: ソケット以外でのソケット操作
-
[解決済み】エラー:'for'ループの初期宣言はC99モードでしかできない【重複
-
[解決済み】スタックスマッシュを検出しました
-
[解決済み】int型配列へのポインタのスカラ・イニシャライザの過剰要素
-
[解決済み] Collatz予想の検証を行うC++のコードは、なぜ手書きのアセンブリよりも高速に動作するのでしょうか?
-
[解決済み】GCCを使用して読みやすいアセンブリを作成しますか?
-
[解決済み】マルチコアアセンブラとはどのようなものですか?
-
[解決済み】アセンブリコード vs マシンコード vs オブジェクトコード?
-
[解決済み】GDBで現在のアセンブリ命令を表示する
-
[解決済み] なぜGCCはほとんど同じCコードに対して根本的に異なるアセンブリを生成するのでしょうか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Valgrind が "Invalid write of size 8" で文句を言う。
-
[解決済み】単項演算子「*」の型が無効(「int」がある)C言語でのエラー
-
[解決済み】GCC Cコードで静的宣言が非静的宣言に続くことを解決するには?
-
[解決済み】Cygwin - Makefile-error: ターゲット `main.o' のレシピに失敗しました。
-
[解決済み】 switch case: error: case label does not reduce to an integer constant
-
[解決済み】EAGAINとはどういう意味ですか?
-
[解決済み】 「配列のイニシャライザーはイニシャライザーリストまたは文字列リテラルでなければなりません」と表示されるのですが?
-
[解決済み】fgetsによるセグメンテーションフォールト(コアダンプ) - と思う。
-
[解決済み】警告:引数「互換性のないポインタ型から」を渡す[デフォルトで有効]。
-
[解決済み】配列型char[]が代入できない [重複]。