まだコンピュータアーキテクチャの用語に慣れていないので、ご容赦ください。フォンノイマンアーキテクチャはハーバードアーキテクチャよりも堅牢(「ユニバーサルチューリングマシン」)であることを理解しているようですが、詳細についてはまだあまり詳しくありません。
コールスタック を調べて過去数泊を過ごした後も、私は 混乱 のままです。 コールスタックなしのプログラミング、およびその他、仮想マシンを定義するためのシステム/アーキテクチャがコールスタックなしであるかどうかが不思議に思われます。どうなるかはよくわかりませんが、チェックすべきことがあるかもしれません。 simpleマシンについては話していない。1960年代以前のマシンのように、再帰がなかったため、コールスタックが不要だったと思う。私は、コールスタック以外の何かを使用する、完全に堅牢で完全なコンピュータアーキテクチャについて話しています。
...コールスタックなしで仮想マシンを定義するためのシステム/アーキテクチャがあるかどうか疑問に思う
継続渡しスタイル は、すべての関数呼び出しに対して 末尾呼び出しの最適化 を有効にします—したがって、スタックは必要ありません。ただし、ヒープメモリは、ローカル変数への参照をキャプチャするクロージャを保持するために最もよく使用されます。
CPSは、一部のコンパイラで中間形式(仮想命令セットなど)として使用され、特に例外や例外処理で発生する制御の明示的なフローを表します。
スタックは非常に効率的なデータ構造です。スタックの最上部はほぼ確実にデータキャッシュ内にあり、割り当てと割り当て解除は非常に高速です(つまり、1つの命令)。スタックはCプログラムに必要な部分であるため、スタックを明示的にサポートせずに最新のコンピューターが作成されることはほとんどありません。
ただし、明確にするために、MIPSとRISC Vには、個別のハードウェア専用のスタックポインターやプッシュ/ポップ命令はありません。ソフトウェアは、多くの汎用レジスターの1つをそのまま使用します。
ここでは堅牢性は問題ではないと思います。機能性とは、最も文字通りの意味です。
実装の詳細を一瞬忘れて、実際にコールスタックとは何かを検討します。これにより、サブプログラム(関数)を呼び出してサブプログラム(関数)から戻り、中断したところから続行できます。つまり、問題を小さなパーツに分割して、機能的なビルディングブロックを作成する可能性を提供します。
これは、汎用の問題解決マシンの基本的な機能であり、これがないと、想像するのが難しいでしょう。複雑なものを作成する方法がないので、それは役に立たないでしょう。
「堅牢」とは、好みの問題です。
スタックは便利ですが、アーキテクチャで直接定義する必要はありません。
必要に応じて、プログラムはいつでも独自のスタックを作成できます。
何かのハードウェアサポートがあると、処理は速くなりますが、柔軟性が低下します。
呼び出しスタックを備えたアーキテクチャでは、関数呼び出しが高速になりますが、通常は引数の転送に関連する作業があるため、veryは高速ではありません。
一方、関数の呼び出しと戻りのために、後入れ先出しの世界に閉じ込められます。 coroutinesを使用したい場合、スタックは役に立ちません。
私たちが持っているハードウェアは、私たちが書くプログラムに影響を与えます。そして私たちが書くプログラムは私たちが望むハードウェアに影響を与えます。結局のところ、私たちが持っているものは、それが多くの選択肢の1つにすぎない場合でも、「必要」であると思われます。
プログラミング言語レベルでもハードウェアレベルでも、必ずしもstacksを呼び出す必要はありません。
コンピュータアーキテクチャの観点から見ると、半任意の言語を実装するために、祝福されたスタック(たとえば、特別なスタックポインタレジスタ、このスタックに関連する値をロードおよび格納するための命令など)に対するハードウェアサポートは必要ありません。 CやSchemeのような関数呼び出しのネスト。レジスタ、レジスタオフセットアドレッシング、および「スタックポインタ」を指定したレジスタを手動でインクリメントおよびデクリメントして、独自のレジスタを実装できます。マシンコードをコンパクトにするために、命令セットの呼び出しスタックのサポートがあります。
プログラミング言語の観点から見ると、スタックは実装の詳細にすぎません。 C標準はそれをスタックとは呼ばず、スタック変数を「自動」と呼びます(定義されたスコープを離れると、ストレージは自動的に割り当て解除されるため)。一般的なオペレーティングシステムでの標準の呼び出し規約は、スタックを使用することです。そのため、人々はそうする必要があると想定しています。
ファーストクラスの継続を持つ言語は、概念的にはスタックのように動作しません。 Forthの実装は通常、2つのスタックを使用します。 CPSdコードは概念的にスタックを使用しません。継続とコルーチンを実装するために使用されるヒープに割り当てられた分岐 "スタック"から、標準のCまで、さまざまな方法があります。