1. ホーム
  2. performance

[解決済み] EBPフレームポインタレジスタの目的は何ですか?

2023-01-05 11:52:08

質問

私はアセンブリ言語の初心者ですが、コンパイラが出力する x86 コードは通常、リリース/最適化モードであってもフレームポインタを保持し、その際に EBP レジスタを使用することができるのに、リリース/最適化モードでもフレーム ポインタを保持します。

フレームポインタがコードのデバッグを容易にすることは理解できますし、また、以下のような場合に必要かもしれません。 alloca() が関数内で呼び出される場合に必要かもしれません。 しかし、x86 には非常に少数のレジスタがあり、1 つのレジスタで十分なときにスタック フレームの位置を保持するために 2 つのレジスタを使用することは、私には意味がありません。 最適化/リリース ビルドにおいてさえ、フレーム ポインターを省略することが悪い考えであると考えられているのはなぜでしょうか?

どのように解決するのですか?

フレーム ポインターは、ローカル変数や引数がどこにあるかを 1 つの定数オフセットで知ることができる参照ポインターです。ESP の値は実行中に変化しますが、EBP は同じままなので、同じオフセットで同じ変数に到達することができます (たとえば、最初のパラメーターは常に EBP+8 になりますが、ESP オフセットはプッシュ/ポップするため大幅に変化する可能性があります)。

なぜコンパイラはフレームポインタを捨てないのでしょうか? なぜなら、フレーム ポインターを使用すると、ローカル変数と引数が EBP に対して一定のオフセットであることが保証されるため、デバッガーはシンボル テーブルを使用してどこにあるかを把握することができるからです。そうでなければ、ローカル変数がコード内の任意の時点でどこにあるかを把握する簡単な方法はありません。

グレッグが言及したように、EBP はスタック フレームの逆リンク リストを提供するので、デバッガーが関数のスタック フレームのサイズ (ローカル変数 + 引数) を把握できるようになり、デバッガーのスタック巻き戻しを助けることにもなります。

ほとんどのコンパイラーはフレームポインターを省略するオプションを提供していますが、それはデバッグを本当に難しくしてしまいます。このオプションは、たとえリリース コードであっても、決してグローバルに使用すべきではありません。ユーザーのクラッシュをデバッグする必要がいつ生じるかわからないからです。