3

以下の関数をコンパイルすると: gcc -S teste.c

void readInput() {
    int buf;
}

teste.S は次のようになります。

readInput:
     pushl   %ebp
     movl    %esp, %ebp
     subl    $16, %esp
     leave
     ret

私の疑問は次のとおりです。なぜ %esp が 16 バイトから差し引かれるのか、int の場合は 4 バイトではないのでしょうか? それはアライメントと関係がありますか?

これをコンパイルすると、同様のことが起こります。

void readInput() {
    char buf;
}

出力は上記と同じです。

4

3 に答える 3

0

キャッシュヒット率

いくつかのことが起こっています。

  1. 最適化せずにコンパイルすると、コード ジェネレーターの設計のアーティファクトが残ります。
  2. さらにコールまたは -g を使用しない場合、完全なスタック フレームはほとんど必要ありません。
  3. スペース割り当てられ、関数がリーフ ノードでない場合は、キャッシュ ライン境界または 1/2 nサブユニットに割り当てることが理にかなっている場合があります。将来の呼び出しはループになる可能性があり、新しいスタック フレームが 2 つのキャッシュ ラインまたはn + 1 キャッシュ ラインと重なる場合、スペースが無駄になり、ヒット率が低下するという考え方です。キャッシュ ヒット率は、しばらく前から非常に重要でした。同じ理由で、モジュールやより大きなデータ構造がオーバーアラインされていることがあります。もちろん、これは、キャッシュの効率を向上させるために、スタックの使用を小さく保つという合理的な目標とも矛盾します。
于 2012-04-16T16:45:05.827 に答える
0

基本的な問題は、最適化を使用していないため、割り当てるスペースや生成するコードを最小限に抑える努力をしていないことです。したがって、ここで何が起こっているかというと、必要になる可能性のあるもの (アンワインド ハンドラー、setjmp/longjmp/alloca の呼び出し、またはその他のコンパイラ組み込み関数) に割り当てられたスタック スペースがたくさんあるということですが、これはあなたのケースでは必要ありません。関数を呼び出したり、それらを必要とする機能を使用したりしないでください。

最適化を使用すると (たとえ-O1.

于 2012-04-16T16:25:21.963 に答える
0

スタックは、おそらく SSE2 用に 16 バイトにアラインされます。(128 ビット = 16*8) のレジスタ。64ビットの場合、これは私の知る限り必須です。

厳密に言えば、リーフ プロシージャを使用する非 SSE の場合、この要件は省略できます。

于 2012-04-17T09:52:24.703 に答える