プログラミング
Sectorforthは512バイトのブートセクタに収まる16ビットx86 Forth (2020)
Sectorforth is a 16-bit x86 Forth that fits in a 512-byte boot sector (2020) (github.com)
要約
Sectorforthは、わずか512バイトのブートセクタに収まる16ビットx86 Forth実装です。1996年のUsenetスレッドに触発されて開発され、最小限のプリミティブセットで分岐やコンパイルなどの機能をForth自身で記述できる柔軟性を持っています。NASMでコンパイル可能で、QEMUでのデバッグや実行もサポートしています。
全文翻訳
sectorforth sectorforthは、512バイトのブートセクタに収まる16ビットx86 Forthです。
Sectorforthを記述するインスピレーションは、1996年のUsenetスレッド(特に、そのスレッドのBernd Paysanによる最初の投稿)から得られました。
バッテリーは含まれていません
sectorforthには、上記のUsenet投稿で概説されている8つのプリミティブ、内部状態を操作するための5つの変数、および2つのI/Oプリミティブのみが含まれています。
この最小限のビルディングブロックセットで、分岐、コンパイル、リターンスタックの操作などのための単語はすべてForth自体で記述できます(例を参照してください!)。
コロンコンパイラ(:)が利用可能なので、新しい単語を簡単に定義できます(もちろん、;も利用可能です)。
多くのForth実装とは異なり、sectorforthは、利用可能なプリミティブを使用して数値を生成できるため、未知の単語を数値に変換しようとはしません。
含まれている2つのI/Oプリミティブは、より強力なインタプリタを記述するのに十分であり、数値の解析が可能です。
プリミティブ
プリミティブ スタック効果 説明
@ ( addr -- x ) addrのメモリ内容を取得します
! ( x addr -- ) xをaddrに格納します
sp@ ( -- sp ) データスタックのトップへのポインタを取得します
rp@ ( -- rp ) リターンスタックのトップへのポインタを取得します
0= ( x -- flag ) スタックのトップが0の場合-1、そうでなければ0
+ ( x y -- z ) スタックのトップにある2つの数値を合計します
nand ( x y -- z ) スタックのトップにある2つの数値をNANDします
exit ( r:addr -- ) リターンスタックをポップし、addrでの実行を再開します
key ( -- x ) キー入力をASCII文字として読み取ります
emit ( x -- ) xの下位バイトをASCII文字として出力します
変数
変数 説明
state 0:単語を実行します; 1:ディクショナリに単語アドレスをコンパイルします
tib ターミナル入力バッファ、ここで入力が解析されます
>in ターミナル入力バッファ内の現在の解析オフセット
here ディクショナリ内の次の空き位置へのポインタ
latest 最新のディクショナリエントリへのポインタ
コンパイル
sectorforthはNASM 2.15.01を使用して開発されました。
NASMの以前のバージョンでもコンパイルできる可能性が高いですが、テストされていません。
sectorforthをコンパイルするには、makeを実行するだけです。
$ make
これにより、コンパイルされたバイナリ(sectorforth.bin)と、そのブートセクタにバイナリを含むフロッピーディスクイメージ(sectorforth.img)が生成されます。
実行
Makefileには、QEMUでsectorforthを実行するための2つのターゲットが含まれています。
debug は、実行を一時停止した状態でQEMUをデバッグモードで起動します。
これにより、sectorforthの実行前にGDBでリモートターゲット(target remote localhost:1234)を設定し、任意のブレークポイントを設定できます。
run は、QEMUでsectorforthを単純に実行します。
使用法
1行あたり最大4KBの入力を入力できます。
リターンキーを押した後、インタプリタは一度に1つの単語を解析し、それを解釈します(つまり、state変数の現在の値に応じて、単語を実行またはコンパイルします)。
sectorforthは、Forthユーザーにはおなじみのokプロンプトを表示しません。
ただし、単語がディクショナリに見つからない場合、エラーメッセージ!!が赤色で表示され、エラーが発生したことがわかります。
単語がディクショナリに見つからない場合、インタプリタの状態はリセットされます。データスタックとリターンスタック、およびターミナル入力バッファがクリアされ、インタプリタは解釈モードに配置されます。
その他のエラー(例:単語定義で無効なアドレスをコンパイルし、それを実行しようとする)は、正常に処理されず、インタプリタがクラッシュします。
コード構造
コード全体にわたるコメントは、Forthとその一般的な実装方法に精通していることを前提としています。
Forthに慣れていない場合は、Leo BrodieのStarting Forthを読んでください。
x86でのForthの実装方法に慣れていない場合は、Richard W.M. Jonesのjonesforthのアセンブリコードを読んでください。
sectorforthはjonesforthから多くのインスピレーションを得ていますが、jonesforthはコメントで基本事項をより良く説明しています。
スレッドコード技術の優れた入門、およびさまざまなアーキテクチャでForthを実装する方法については、Brad RodriguezのMoving Forthを読んでください。