2

次のコード行が int main (int argc, char *argv[]) である理由を誰か説明してもらえますか

{
int i=17;
int output=0

.....

}

次の x64 アセンブリ コードに変換されます。

pushq %rbp
movq %rsp, %rbp
subq $32, %rsp
movl %edi, -20(%rbp)
movq %rsi,-32(%rbp)
movl $17, -8(%rbp)
movl $0, -4(%rbp)
...

SP が 32 減った理由がわかりません。レジスタ %edi、%rsi は、メイン コードで使用されていない argc と *argv[] に対応しているようです。[%esp, %rbp] の間のスペースは、ローカル変数のみに割り当てられ、関数の引数には割り当てられないと思いました。したがって、上記のコードでは、サイズは 8 だけにする必要があります。つまり、rsp を 32 ではなく 8 だけ減らす必要があります。説明をお願いします。

4

1 に答える 1

0

... の部分を知っていると役に立ちます。

gcc は ... の部分にレジスタが必要だと判断したため、変数をスタックにプッシュしたと思います。

スタックは、任意のローカル変数または関数引数に使用できます。SysV x64 ABI による唯一の要件は、最初のいくつかの関数引数がレジスタで始まることです。

次に、関数は引数をスタックに移動し、必要に応じてローカル変数をレジスタに入れることができます。それはコンパイラ次第です!

ローカル変数がスタックに置かれる保証はありません! また、args がレジスターに残ることもありません。

そのため、argc と argv をプッシュし、次に i をプッシュして出力することにしました。これは 24 バイトのスペースです。しかし、関数呼び出しが次にある場合、スタックは 16 バイトに揃える必要があるため、32 になります。

-O3 を試して、コードが変わるかどうかを確認してください。

別の言い方をすれば:

引数は次のようになります: %rdi %rsi %rdx %rcx %rbx %r8 %r9 (スタック上の余分な引数) (レッド ゾーン)

関数の開始です。その後、関数はスタックで必要なことを何でも行うことができます。はい、何でも!取得した状態でスタックを返す限り。

(注、これはシステム V (Windows 以外のすべてで使用される) 用であり、Windows は異なります)

于 2013-02-23T20:55:42.897 に答える