2012-06-24 1 views
8

メモリとスタックの仕組みを理解するために、gcc -Sで遊んでいます。これらの演劇の間、私はいくつかのことがわかりました。理由を理解するのを助けてくれますか?なぜアセンブラコードを作成するときにgccがそうするのですか?

  1. 呼び出す関数はそれがmovpush代わりespにを使用していますと呼ばれる1の引数を設定します。 pushを使用しない利点は何ですか?

  2. スタック位置の引数で動作する関数は、ebp + (N + offset)(Nはリターンアドレス用に予約されているサイズ)を指しています。私はより理解できるesp - offsetを見ることを期待する。 ebpをどこにでも使用する理由は何ですか?私はこれらの人が平等だが、とにかく知っていますか?

  3. mainの冒頭にこの魔法は何ですか?このようにしてespを初期化する必要があるのはなぜですか? 64ビット環境での引数はレジスタに渡されるため

    and esp,0xfffffff0 
    

おかげで、

+3

これは3つの別個の質問であり得る。とにかく、第3のポイントへの答えはスタックアライメントです。 – Mysticial

答えて

7

は、私はあなたが32ビット環境の下で作業していると仮定します。

質問1

ここで浮動小数点数の引数を渡している可能性があります。 32ビットランタイムのpush命令は一度に4バイトをプッシュしますので、値を分割する必要があるため、これらを直接プッシュすることはできません。 espから8を引くと、8バイトのクワッドワードを[esp]に移動する方が簡単な場合があります。

質問2

ebpはしばしばインデックスに32ビットコードのスタックフレームのパラメータと地元の人々が使用されています。これにより、スタックポインタが動いてもフレーム内のオフセットを固定することができます。あなただけespでスタックフレームの内容にアクセスした場合

void f(int x) { 
    int a; 
    g(x, 5); 
} 

今すぐ、そしてa[esp]である考慮するたとえば、リターンアドレスは[esp+8]になり[esp+4]xになります。次にgを呼び出すコードを生成しましょう。最初に5を押してからxを押す必要があります。しかし、5を押すと、xのオフセットがespから変更されました!このため、ebpが使用されます。通常、関数への入力時には、古い値ebpを保存してから、espebpにコピーします。今度はebpを使用してスタックフレームの内容にアクセスできます。私たちが引数を渡す途中に移動しません。

質問3

このand命令は16バイト境界に整列し、espの最後の4ビットをゼロに。スタックが下向きに成長するので、これは安全で安全です。

+1

Q3:最後の4ビットをゼロにします。 – hirschhornsalz

+0

ああ、ありがとう、@drhirsch。思考せずに入力する。恐ろしい。本当にありがとう!編集されました。 –

関連する問題