私はここでForthを学んでおり、リターンスタック操作に取り掛かっています。
したがって、Ubuntu 11.04 x64でコンソールを使用して、TOSをリターンスタックに入れようとしていますが、これは発生します。
1 2 3 4 5 ok
>r
:36: Invalid memory address
>R>>><<<
Backtrace:
私はここで何が間違っているのですか?
私はここでForthを学んでおり、リターンスタック操作に取り掛かっています。
したがって、Ubuntu 11.04 x64でコンソールを使用して、TOSをリターンスタックに入れようとしていますが、これは発生します。
1 2 3 4 5 ok
>r
:36: Invalid memory address
>R>>><<<
Backtrace:
私はここで何が間違っているのですか?
> rはそれ自体が単語であり、インタプリタに戻る必要があります。質問のように>rを実行すると、無効な新しいリターンアドレスが追加されます。
代わりに、(新しい)単語内で>rを使用してください。リターンスタックに追加されたアイテムは、そのワードが終了する前に削除する必要があることに注意してください。リターンスタックは、ワードの実行が開始されたときと同じ状態である必要があります。
ループは、実際にはワード内のリターンスタックのアプリケーションの例です(したがって、ワード内でバランスをとる必要があるのと同じように、リターンスタックの独自の使用もループ内でバランスをとる必要があります)。
あなたがやろうとしていることは、あまり意味がありません。4番目のマシンは一連のワードを実行します。実行される行の次のワードのアドレスは、NEXTと呼ばれる特殊レジスタに格納されます(CPUの命令ポインタのように考えてください)。
リターンスタックが必要なのは、それ自体がスレッド化されたワードリストであるワードが呼び出された場合、NEXTレジスタの元のアドレスをスクラブしてしまうためです。これを防ぐには、NEXTレジスタの現在の内容を使用します。リターンスタックにプッシュされます。
私が正しく理解していれば、 >rはデータの最上位要素をリターンスタックにプッシュします。この場合、アドレス「5」に命令がないため、「5」は無効です。
他の誰かが指摘しているように、新しい制御構造を実装しない限り、リターンスタックについて心配する必要はありません。
コマンドラインでGforthのリターンスタックを使用できます(これは非標準機能です)。ただし、1つの制限があります。1行内でバランスを取る必要があります。行の終わりで、ラインインタープリターが戻るため、リターンスタックには期待されるリターンアドレスが含まれている必要があります。
だから、次のようなものを試してください
1 2 3 4 5 >r + r> .s
それはあなたに与えるはずです
1 2 7 5