スタックは、ボトムアップで積み上げるものです。
したがって、スタックが空になりプログラムが終了するまで各関数が終了するため、関数が呼び出されたときにスタックから新しいアイテムが追加され、呼び出しスタックはスタックに新しいアイテムを追加します。
上記が正しい場合、なぜ人々はコールスタックを「上に」移動するコントロールを参照するのですか?確実に、制御は呼び出しスタックを下に移動します。
スタックは、ボトムアップで積み上げるものです。
したがって、スタックが空になりプログラムが終了するまで各関数が終了するため、関数が呼び出されたときにスタックから新しいアイテムが追加され、呼び出しスタックはスタックに新しいアイテムを追加します。
上記が正しい場合、なぜ人々はコールスタックを「上に」移動するコントロールを参照するのですか?確実に、制御は呼び出しスタックを下に移動します。
回答:
この使用には2つの理由が考えられます。
例外のコンテキストでは、コントロールは呼び出し元の関数/メソッドに移動します。この呼び出し階層は、通常、メインメソッドを上に、メソッド呼び出しを下に階層化して抽象化のレベルを下げて視覚化されます。この階層では、例外が上に移動します。
通常のx86アプリケーションの実際のプログラムスタックは反転します。つまり、下向きに成長します。PUSH / PUSHW / PUSHDマシンコード命令は、スタックポインターを減らします。他のアーキテクチャがこのモデルを共有する場合があります。
それはすべて単語の定義に依存します。この文脈での「上」と「下」という言葉、およびオペレーティングシステムまたはコンピュータアーキテクチャの実装について、正確にはどういう意味ですか。
Commodore 64でプログラミングをしていた昔のことを覚えています。アドレス$ 0800(2048)と$ 9FFF(40959)の間のメモリは、BASICプログラム用に予約されていました。BASICプログラムのコードは、下位アドレス($ 0800、そこから上方向に増加)から保存されました。変数とサブルーチンの戻りアドレスを格納するためのスタックは、その範囲の先頭($ 9FFF)から始まり、下位アドレスに向かって増加しました。したがって、このコンテキストでは、スタックが下向きに成長しているのを見ることが論理的でした。サブルーチンから戻ると、サブルーチンのスタックフレームはスタックポインタをインクリメントして破棄されたため、「スタックを上に移動している」と言えるでしょう。サブルーチンから戻る。
WindowsやIntel x86プロセッサなどの最新バージョンでどのように機能するかはわかりません。スタックは逆に機能する可能性があります。つまり、スタックは低いアドレスから高いアドレスへと成長します。その場合は、おそらく「上」、「下」、「上」、「下」という言葉をまったく逆に使用します。
foo(6、x + 1)などの関数を呼び出すには...
- 呼び出し元のコンテキストで、x + 1などの実際のパラメーター式を評価します。
- この目的専用のランタイム「コールスタック」にメモリの適切な「ローカルブロック」をプッシュすることにより、foo()のローカルにメモリを割り当てます。ローカル変数ではなくパラメーターの場合、ステップ(1)の値をfoo()のローカルブロックの適切なスロットに格納します。
- 呼び出し元の現在の実行アドレス(「戻りアドレス」)を格納し、実行をfoo()に切り替えます。
- foo()は、呼び出しスタックの最後で便利に使用できるローカルブロックで実行されます。
- foo()が終了すると、スタックからローカルをポップして終了し、以前に格納された戻りアドレスを使用して呼び出し元に「戻り」ます。これで、呼び出し元のローカルはスタックの最後にあり、実行を再開できます。
参照:
http://cslibrary.stanford.edu/102/PointersAndMemory.pdf(p15)
スタックをボトムアップのものとして概念化する場合、通常の重力現実下でテニスボールが中にあるシリンダーのように、コントロールは関数が呼び出されるとスタックを上に移動します。関数が完了すると、コントロールはスタックを下に移動します。
テニスボールの同じシリンダーのように、重力が逆転しているように、スタックをトップダウンの概念として概念化すると、関数が呼び出されるとコントロールがスタックを下に移動し、関数が完了するとスタックが上に移動します。
これらはどちらも頭の中の単なるモデルであり、本質的に完全に任意です。必要に応じて、サイドバイサイドのものとして概念化することもできますが、人とのコミュニケーションに問題が生じる可能性があります。私は個人的に、AがBを呼び出し、BがCを呼び出す場合、Cはスタックの最下部(重力の反転現実)であり、Cで例外が発生した場合、その例外をAまで「バブル」にしたいと考えます。これは、 Cが深く、Aがトップであるという感覚のため、より一般的な言語の使用法。最初の関数はより直感的に私にとって一番上にあり、関数は各呼び出しでより深くなります。