Forthにはスタックとリターンスタックがあります。Forthのような言語を1つのスタックで実装できますか?
私が理解する限り、リターンスタックのポイントは、プログラムカウンタの以前の値を格納することです。
Cプログラムは、プログラムカウンタの前の値をスタックに置き、戻りスタックを使用しません。
Forthは結果をスタックに返すためreturn-stackだけが必要なので、プログラムカウンタの前の値を埋め込むことができますか?
Forthにはスタックとリターンスタックがあります。Forthのような言語を1つのスタックで実装できますか?
私が理解する限り、リターンスタックのポイントは、プログラムカウンタの以前の値を格納することです。
Cプログラムは、プログラムカウンタの前の値をスタックに置き、戻りスタックを使用しません。
Forthは結果をスタックに返すためreturn-stackだけが必要なので、プログラムカウンタの前の値を埋め込むことができますか?
「ポータブルアセンブリ言語」は近いはずです。これは、標準/従来のForthとほぼ同じ言語用のコンパイラのコンセプトです。どのような種類のプログラムを書くことができるかにはいくつかの制限があります。ほとんどの場合、スタックの深さを静的に決定できない状況を避けなければなりません。
この言語は、1つのスタックしか必要としない方法でコンパイルできます。
http://www.complang.tuwien.ac.at/anton/euroforth/ef13/papers/ertl-paf.pdf
はじめに:私はめちゃめちゃコールスタックを持ついくつかの問題を追跡するために、ハードウェアデバッガ用の拡張機能を書いたので、私は実際C
スタックの一部進ダンプを見てきました。
C
スタックは、リターンアドレス、ローカル変数、および関数パラメータが混在しています。各関数について、どの値を期待しているのかを知ることができますが、この知識は関数の範囲で停止します。
forth
でもこのようにすることができますが、これは巨大なオーバーヘッドを意味します。スタックにパラメータを配置して、同じスタックの上に戻りアドレスを配置することができます。問題はありません:各コマンドは、オペランドがスタック上で2番目以降であることを認識します。しかし、コマンドはこれらの値を持つ別のコマンドを呼び出す必要があります。これは、コールされたコマンドがスタックに埋め込まれている場所を知ることができないため、値を上に戻すためにスタックの順序を変更する必要があります。書きました。
コンパイラは、より複雑なforth
コンパイラは、各コマンドがどのくらいの数の値を取ってきて、各コマンド呼び出しの前にスタックをソートすることができます。しかし、どのようなコストで!
もちろん、C
プログラムにもこのオーバーヘッドがあります。インラインアセンブリで非インライン関数呼び出しが表示される場合、常にレジスタ交換のオーバーヘッドがあります。しかし、良いforth
プログラムは小さな関数で構成されているので、より多くの関数呼び出しとより多くのオーバーヘッドがあります。
最新のコンピュータアーキテクチャのように、各レジスタはスタックポインタとして使用できるため、問題なくスタックをいくつか持つことができます。
最後に、あなたの質問に対する答えは:はい、forth
という1つのスタックの派生物を実装できますが、それは無益です。
私は専門家ではありませんが、パラメータのサイズ(リターンアドレスに到達するために必要なデータ)がコンパイル時に分かります。静的です。戻り値のサイズも同じです。第4に、これらはどちらも知られていません。 – unwind
Cでは、通常、リターンスタックと引数スタックは同じです。引数と戻りアドレスは、マシンスタック上(通常、これは必須ではありません)です。しかし、Cはレジスタ内で引数を渡すだけでよく、通常はレジスタ内で引数を返します。そのため、CはForthのようなスタックベースの言語ではありません。Forthでは、スタックは言語に不可欠です。 –
Forthでは、リターンスタックはしばしば一時的なストレージとしても使用されます。データスタックから値を取得するので、値の「下」の値はより簡単にアクセスできます。一般的に例外処理の役割を果たします。これは単に返品先住所を覚えているだけではありません。実際には、そのような戻り値がそこに格納されていることは必須ではありません。 –