[解決済み] なぜGCCはNOPで関数を埋めるのですか?
質問
私はC言語をしばらく使っていましたが、ごく最近ASMを始めました。私がプログラムをコンパイルするとき
int main(void)
{
int a = 0;
a += 1;
return 0;
}
objdumpの逆アセンブルにはコードがありますが、retの後にnopsがあります。
...
08048394 <main>:
8048394: 55 push %ebp
8048395: 89 e5 mov %esp,%ebp
8048397: 83 ec 10 sub $0x10,%esp
804839a: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%ebp)
80483a1: 83 45 fc 01 addl $0x1,-0x4(%ebp)
80483a5: b8 00 00 00 00 mov $0x0,%eax
80483aa: c9 leave
80483ab: c3 ret
80483ac: 90 nop
80483ad: 90 nop
80483ae: 90 nop
80483af: 90 nop
...
私が学んだところでは、nopsは何もしませんし、retの後は実行されないので。
私の疑問は、なぜ悩むのか?ELF(linux-x86) は、任意のサイズの .text セクション (+main) で動作しないのでしょうか?
私はどんな助けでも感謝します、ちょうど学習しようとしています。
どのように解決するのですか?
まず最初に
gcc
は常にこれを行うわけではありません。パディングを制御するのは
-falign-functions
によって自動的にオンにされます。
-O2
と
-O3
:
-falign-functions
-falign-functions=n
関数の開始を次の2の累乗に揃える
n
までスキップしてn
をバイト単位でスキップします。例えば-falign-functions=32
は関数を次の32バイトの境界線に合わせますが-falign-functions=24
は次の32バイト境界に整列させますが は、23 バイト以下をスキップして行うことができる場合のみ、次の 32 バイト境界に整列します。
-fno-align-functions
とし-falign-functions=1
は等価であり、関数は整列されないことを意味します。アセンブラによっては、nが2のべき乗のときのみこのフラグをサポートします。 その場合、それは切り上げられます。
nが指定されないか、または0である場合、マシン依存のデフォルトを使用します。
レベル -O2, -O3 で有効になります。
これを行う理由は複数考えられますが、x86 での主なものはおそらくこれでしょう。
ほとんどのプロセッサは、アラインされた16バイトまたは32バイトのブロック単位で命令をフェッチします。これは クリティカルなループ エントリやサブルーチン エントリを 16 バイトでアラインすることは、コード内の 16 バイト境界を最小限にするために有利になります。 コード内の16バイト境界の数を最小限にするためです。または、クリティカル ループ エントリまたはサブルーチン エントリの後の最初の数命令で 16 バイト境界がないことを確認します。
(アセンブリ言語におけるサブルーチンの最適化 language" by Agner Fog.より引用)
を編集してください。 以下は、パディングを実演する例です。
// align.c
int f(void) { return 0; }
int g(void) { return 0; }
gcc 4.4.5 を使ってデフォルトの設定でコンパイルすると、こうなります。
align.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <f>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: b8 00 00 00 00 mov $0x0,%eax
9: c9 leaveq
a: c3 retq
000000000000000b <g>:
b: 55 push %rbp
c: 48 89 e5 mov %rsp,%rbp
f: b8 00 00 00 00 mov $0x0,%eax
14: c9 leaveq
15: c3 retq
指定する
-falign-functions
を与える。
align.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <f>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: b8 00 00 00 00 mov $0x0,%eax
9: c9 leaveq
a: c3 retq
b: eb 03 jmp 10 <g>
d: 90 nop
e: 90 nop
f: 90 nop
0000000000000010 <g>:
10: 55 push %rbp
11: 48 89 e5 mov %rsp,%rbp
14: b8 00 00 00 00 mov $0x0,%eax
19: c9 leaveq
1a: c3 retq
関連
-
構造体の配列--[エラー] '['トークンの前に一次式があることが予想される
-
[解決済み] mallocで文字列を確保する
-
[解決済み] mallocの結果はキャストするのですか?
-
[解決済み] なぜGCCはa*a*a*a*aを(a*a*a)*(a*a*a)に最適化しないのでしょうか?
-
[解決済み] 配列の場合、なぜ a[5] == 5[a] になるのでしょうか?
-
[解決済み] 配列のすべてのメンバーを同じ値で初期化するには?
-
[解決済み] Cプリプロセッサはなぜ "linux "という単語を定数 "1 "と解釈するのですか?
-
[解決済み] 難読化Cコードコンテスト2006。sykes2.cの解説をお願いします。
-
[解決済み] プログラム終了前にmallocの後にfreeをしないと本当に何が起こるのか?
-
[解決済み] .aファイル、.soファイルとは何ですか?
最新
-
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 実装 サイバーパンク風ボタン
おすすめ
-
関数 'malloc' の暗黙の宣言に対する解決策
-
警告:符号付き整数式と符号なし整数式の比較 [-Wsign-compare]
-
[解決済み] Linux Socket write() によるBad File Descriptor C
-
[解決済み] Linuxカーネルにおけるcontainer_ofマクロの理解
-
[解決済み] C - Setデータ構造を実装するには?
-
[解決済み] C言語でランダムなint型を生成するには?
-
[解決済み] printfは、フォーマット文字列の中に改行がないと、呼び出し後にフラッシュしないのはなぜですか?
-
[解決済み] なぜsizeof(x++)はxをインクリメントしないのですか?
-
[解決済み] なぜGCCは、速度の代わりにサイズに最適化すると、15-20%速いコードを生成するのですか?
-
[解決済み] ストラクチャーとユニオンの違い