5

次の簡単なデモ関数をコンパイルしています。

int add(int a, int b) {
    return a + b;
}

当然、この関数はインライン化されますが、動的にリンクされているか、他の理由でインライン化されていないと仮定しましょう。最適化を無効にすると、コンパイラは予想されるコードを生成します。

00000000 <add>:
   0:   55                      push   ebp
   1:   89 e5                   mov    ebp,esp
   3:   8b 45 0c                mov    eax,DWORD PTR [ebp+0xc]
   6:   03 45 08                add    eax,DWORD PTR [ebp+0x8]
   9:   5d                      pop    ebp
   a:   c3                      ret

この関数内には関数呼び出しがないため、0、1、および 9 の命令は目的がないように見えます。最適化が無効になっているため、これは許容されます。

ただし、 でサイズを最適化しながらコンパイルすると-Os -s、まったく同じコードが生成されます。これらのオプションで関数のサイズを 66% 増やすのはかなり無駄に思えます。

コードが次のように最適化されていないのはなぜですか?

00000000 <add>:
   0:   8b 45 0c                mov    eax,DWORD PTR [esp+0x8]
   3:   03 45 08                add    eax,DWORD PTR [esp+0x4]
   6:   c3                      ret

コンパイラはこれを最適化する価値があるとは考えていませんか、それとも関数のアライメントなどの他の詳細に関連していますか?

4

2 に答える 2

0

関数に入るときの EBP の値は不明です。コードでレジスタを使用することはできますがmov eax,dword ptr [esp+8]、気にする必要はありませんBPが、多くのデバッグ ツールは、各ローカル変数が何らかのレジスタに対して固定されたオフセットにあると想定しています。コンパイラがスタックにプッシュされたものを追跡し、インデックス オフセットを適切に調整できたとしても、デバッガはおそらくそうできません。

于 2013-07-02T20:49:35.577 に答える