12

関数呼び出しがプログラムによって行われた場合、呼び出された関数は呼び出し元に戻る方法を知っている必要があることを読みました。

私の質問は次のとおりです。呼び出された関数は、呼び出し元に戻る方法をどのように知っていますか? コンパイラを介して舞台裏で機能するメカニズムはありますか?

4

4 に答える 4

12

コンパイラは、対象の ABI の一部として定義された特定の「呼び出し規約」に従います。その呼び出し規則には、システムがどのアドレスに戻るべきかを知る方法が含まれます。呼び出し規約は、通常、プロシージャ呼び出しに対するハードウェアのサポートを利用します。たとえば、Intel では、戻りアドレスがスタックにプッシュされます。

...プロセッサーは、EIPレジスターの値 (命令に続く命令のオフセットを含むCALL) をスタックにプッシュします (後で戻り命令ポインターとして使用するため)。

関数から戻るには、次のret命令を使用します。

... プロセッサは、リターン命令ポインタ (オフセット) をスタックの一番上からEIPレジスタにポップし、新しい命令ポインタでプログラムの実行を開始します。

対照的に、ARM では、リターン アドレスはリンク レジスタに置かれます。

BLおよびBLX命令は、次の命令のアドレスを ( 、リンク レジスタ) にコピーしlrますr14

通常、リターンはmovs pc, lr、アドレスをリンク レジスタからプログラム カウンタ レジスタにコピーして戻すことによって行われます。

参考文献:

  1. インテル ソフトウェア開発者マニュアル
  2. ARMインフォメーションセンター
于 2013-07-07T18:06:55.923 に答える
4

呼び出し先と呼び出し元の協力が必要です。

呼び出し元は、呼び出し先が返すべきアドレスを (通常はスタックにプッシュするか、レジスタに渡すことによって) 呼び出し先に与えることに同意し、呼び出し先は実行が終了したときにそのアドレスに戻ることに同意します。

于 2013-07-07T19:08:57.607 に答える
4

これはスタックによって可能になります (特に Intel のようなシステムでは)。たとえば、ローカルに保持callerする を含むメソッドがあるとします。int

caller(そのintを呼び出すときはtarget(、保存する必要があります。これは、呼び出し元のアドレスとともにスタックに置かれます。target(ロジックを実行し、独自のローカル変数を作成し、他のメソッドを呼び出すことができます。そのローカル変数は、呼び出しのアドレスとともにスタックに配置されます。

終了するtarget(と、スタックは「展開」されます。target(のローカル変数を含むスタックの一番上が削除されます。

メソッドが再帰しすぎると、スタックが大きくなりすぎて、「スタック オーバーフロー」が発生する場合があります。

于 2013-07-07T18:06:56.180 に答える