1. ホーム
  2. c

[解決済み] なぜGCCはNOPで関数を埋めるのですか?

2023-06-03 14:56:54

質問

私は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