FromNandの日記

自分的備忘録

main関数の「return 0;」について逆アセンブルして考察してみた

main関数の「return 0;」は、OSにプログラムが安全に終了したことを伝えるという意味合いを持つ。
しかし実際には、main関数の「return 0;」を書いていない人もしばしば見かける。
ということで、今回は「return 0;」を書くのと書かないのとではどのような違いが生じるのかをアセンブラで調べてみる。


まず、こちらは「return 0;」を書いた場合のソースコード

int main(void){
    return 0;
}


このソースを次のコマンドでコンパイルして

gcc -m32 main.c -o main


次のコマンドで逆アセンブルすると

objdump -d main


main関数の部分は次のようなアセンブリになっている。

000004ed <main>:
 4ed:   55                      push   %ebp
 4ee:   89 e5                   mov    %esp,%ebp
 4f0:   e8 0c 00 00 00          call   501 <__x86.get_pc_thunk.ax>
 4f5:   05 e7 1a 00 00          add    $0x1ae7,%eax
 4fa:   b8 00 00 00 00          mov    $0x0,%eax
 4ff:   5d                      pop    %ebp
 500:   c3                      ret


このアセンブリのミソは「mov $0x0, %eax」の部分で、これが「return 0;」に対応している。


さて、次は「return 0;」を書かなかった場合について調べてみる。
先程と同様に次のソースコードコンパイルする。

int main(void){
}


すると、次のようなアセンブラが生成された。

000004ed <main>:
 4ed:   55                      push   %ebp
 4ee:   89 e5                   mov    %esp,%ebp
 4f0:   e8 0c 00 00 00          call   501 <__x86.get_pc_thunk.ax>
 4f5:   05 e7 1a 00 00          add    $0x1ae7,%eax
 4fa:   b8 00 00 00 00          mov    $0x0,%eax
 4ff:   5d                      pop    %ebp
 500:   c3                      ret


こちらのコードにも「mov $0x0, %eax」の記述がある。
つまり、僕の環境では、賢いコンパイラが「return 0;」を書き忘れたプログラマに変わってコードを挿入してくれたらしい。
結果としては、main関数の中に「return 0;」を書いても書かなくても、「return 0;」は自動的に挿入されることになるらしい。
しかし、環境によっては「return 0;」を書かない場合は「mov $0x0, %eax」がないままになる環境もあるらしいので、「return 0;」は書くべきだと言えるだろう。