ARMでリンクレジスタとフレームポインタがどのように機能するかを理解しようとしています。私はいくつかのサイトに行ってきましたが、理解を確認したかったのです。
次のコードがあったとします:
int foo(void)
{
// ..
bar();
// (A)
// ..
}
int bar(void)
{
// (B)
int b1;
// ..
// (C)
baz();
// (D)
}
int baz(void)
{
// (E)
int a;
int b;
// (F)
}
foo()を呼び出します。リンクレジスタにはポイント(A)のコードのアドレスが含まれ、フレームポインターにはポイント(B)のコードのアドレスが含まれますか?そして、すべてのローカルが宣言された後、スタックポインターはbar()内のどこになりますか?
[編集]別の関数呼び出しbaz()を追加
免責事項:これはほぼ正しいと思います。必要に応じて修正してください。
このQ&Aの別の場所で示されているように、コンパイラはフレームポインターを使用する(ABI)コードを生成する必要がない場合があることに注意してください。多くの場合、コールスタック上のフレームには、役に立たない情報を配置する必要があります。
コンパイラオプションが「フレームなし」(擬似オプションフラグ)を呼び出す場合、コンパイラは呼び出しスタックデータを小さく保つ小さなコードを生成できます。呼び出し関数は、必要な呼び出し情報のみをスタックに保存するようにコンパイルされ、呼び出される関数は、必要な呼び出し情報のみをスタックからポップするようにコンパイルされます。
これにより、実行時間とスタックスペースが節約されますが、呼び出し元のコードで逆方向にトレースするのが非常に難しくなります(...
スタック上の呼び出し情報のサイズと形状に関する情報はコンパイラーのみが知っており、その情報はコンパイル後に破棄されました。