0

私は、 Richard BlumによるProfessional Assembly Languageを読んでいます。コールを入力するときは、レジスタの値を にコピーする必要があります。また、彼は次のテンプレートも提供しています。ESPEBP

function_label:
    pushl %ebp
    movl %esp, %ebp
    < normal function code goes here>
    movl %ebp, %esp
    popl %ebp
    ret

なぜこれが必要なのかわかりません。関数内に何かをプッシュすると、明らかにそれを元に戻そうとするため、ESP元の値に戻ります。

では、なぜこのテンプレートがあるのでしょうか。とにかく、レジスタ
の使用は何ですか?EBP

明らかに何かが欠けていますが、それは何ですか?

4

1 に答える 1

2

関数内に何かをプッシュするときは、明らかにそれをポップバックするつもりです

これは、スタックを使用する理由の一部にすぎません。はるかに一般的な使用法は、ローカル変数を格納するスニペットにないものです。EBP をセットアップした後に表示される次の一般的なコードは、ESP での減算であり、ローカル変数ストレージに必要なスペースの量に相当します。もちろん、関数のエピローグで同じ量を追加するだけで、バランスをとるのも簡単です。コードで C99 の可変長配列や、標準ではないが一般的に利用可能な _alloca() 関数なども使用している場合は、さらに困難になります。EBP から ESP を復元できると、これが簡単になります。

さらに言えば、このようにスタック フレームをセットアップする必要はありません。ほとんどの x86 コンパイラは、「フレーム ポインターの省略」と呼ばれる最適化オプションをサポートしています。GCC の -fomit-frame-pointer、MSVC の /Oy でオンにします。これにより、EBP レジスタが一般的な用途に利用できるようになります。これは、CPU レジスタが不足している x86 で非常に役立ちます。

ただし、その最適化には非常に重大な欠点があります。EBP レジスタがスタック フレームの先頭を指していないと、スタック ウォークを実行するのが非常に困難になります。これは、コードをデバッグする必要がある場合に重要です。スタック トレースは、コードがどのようにクラッシュしたかを調べるために非常に重要な場合があります。顧客からクラッシュの「コア ダンプ」を取得した場合は非常に貴重です。非常に貴重なため、Microsoft はWindows バイナリの最適化をオフにして、顧客がクラッシュを診断できるようにすることに同意しました。

于 2013-04-07T14:57:07.277 に答える