0

そのため、インターウェブを何週間も検索しましたが、質問に対する答えが見つかりません。

gcc によって追加された開始記号が最初の 2 つの引数 (int argc、char *argv[]) を設定していることがわかります。私は 3 番目の環境引数を信じていますが、これについていくつか質問があります。main() 関数が引数を持たないように定義されている場合、なぜこれらすべてを追加するのでしょうか? 引数なしで _main を呼び出すと、スペース (および技術的に処理時間) を節約できませんか? 次に $0x0 のプッシュは何をしますか? 私はテストを行いましたが、デフォルトの開始シンボルのようにコマンドライン引数を反復しようとすると、最初に $0x0 をプッシュする必要があります。そうしないと、次のようなことをするとスタック エラーが発生します。

push $0x00
call _main
mov %eax, %edi
call _exit

また、私の調査では、crt1.10.6.o にリンクすると、リンカーによって開始記号が追加されることがわかりました。

説明やドキュメントをいただければ幸いです

4

1 に答える 1

1

あなたが見つけたように、のコードは、または同様_startの名前のオブジェクトファイルから来ています。crt1.oそのオブジェクト ファイルは通常、C ライブラリの一部であるソース コードから取得されます。関数の宣言方法を無視してコンパイルされるため、3 つの潜在的な引数mainすべてを使用する必要があると想定する必要があります。引数を使用しない場合でも、引数を設定しても害はありません(あなたが言及したように、わずかな量のスペースと時間を除いて)。main

これは x86-64 ELF ABI であると推測できます。mov %eax,%ediつまり、フレーム ポインターがないため、ご想像のとおり、push $0x00実際にはスタックを 16 バイト境界に揃えておくだけです。(x86-32 ELF ABI では、フレーム ポインターのリンク リストのターミネーターとしても機能していました。)

于 2012-06-17T22:45:01.487 に答える