今回は、機械語ローダについてです。機械語ローダとは、紙テープに打たれたプログラムをメモリに書き込むプログラムです。古いコンピュータは、搭載メモリが少ないため、OSなしのベアメタルで運用されていました。有名なところでは、 世界で最初のプログラム内蔵式コンピュータであるEDSACのイニシャル・プログラム・ローダや、東大のパラメトロん計算機のPC1の和田英一さんのプログラムなどがあります。
木村泉先生追悼文集 別冊 3 の最後尾のセクションは、小さなローダについてです。作者は、当時、木村先生の研究室に在籍した久野靖氏と思います、この文集には、久野さんが2名関係しているので、確定できません)
こんな感じでOHPが3枚掲載されています。
このプログラムは、前回紹介したローダ語で書かれているので、これをメモリに格納するには、メモリの中にローダ語をロードするローダ必要と堂々巡りが起こります。(ブートストラップ問題の一例)
ブートストラップ問題 (Bootstrap problem) は、コンパイラをコンパイル対象のプログラミング言語で作成した際に、そのコンパイラの最初のコンパイルをどうするかといった場合を典型的な例とする、いわゆる「鶏と卵」の形をしたセルフホスティング環境の問題を指す。これを解決するための方式をブートストラップ方式といい、この問題を何とかして最初の完備した環境を作ることをブートストラッピングという[1]。 (Wikipedia から)
今回は、ちょっとずるいですけれど、ローダ語を解読しながら、 PDP-11 のアッセブラに入力して、絶対ローダ形式に変換しました。お正月休みに入力していたら、大問題発生、冊子には、3枚のOHPが掲載されていましたが、本来、4枚目があったようで、名前表の検索をするサブルーチンと名前表のチェックをするサブルーチンが、失われてしまっていました。幸い名前表の構造は、名前の登録サブルーチンから判明したので、Balconが勝手に、足らないサブルーチンと紙テープ入力サブルーチンをつけ足して、完成させました。
全体で、 0.7 kByte 程度のサイズで、ごく小さなローダです。仕様は次のとおりです。
プログラムは紙テープで入力します。simhで、紙テープを作る方法は、普通の編集ソフトで、普通に入力して、ASCIIファイルを保存すれば、紙テープ・イメージとして使えます。ただし、Unix系の編集ソフトは改行がラインフィード( LF)なのですが、テレタイプの改行キャリージ・ラインフィード (CRLF)なので、紙テープ入力サブルーチンでCRを加えて、読み込んでいます。
機械語は、カンマ(、)または、セミコロン(;)で区切ります。1語、16ビットの8進数で、6桁で入力しますが、先頭から続く0は省略可能です。
名前は、$に続く8進数で定義して、最後にコロン(:)をおきます。名前が、出現した番地を名前で置き換えることが可能になります。
分岐命令にカンマなしで スラッシュ(/)名前で、名前の番地のオフセットを計算して、分岐命令を完成させて、メモリに格納します。
$記号なしの8進数がコロン(:)で終わると、メモリの開始番地指定になり、機械語はその番地から格納されます。 開始番地が、指定されていない場合は、60000番地からの格納になります。
エラーチェックはありません。
以上が、オリジナルのローダの仕様です。
このコードはローダの仕組みを説明するのは、ちょうどいいのですが、実際に使ってみると、あったら良いなという点があります。Balconはオリジナルにいくつか、拡張をして、
mld-obj.ptap という絶対ローダで読み込める紙テープ・イメージをつくりました。
下のリンクからダウンロードできます。
Balconの拡張点は、三つです。
エラーメッセージ:
未登録の名前
名前の多重定義
分岐命令の誤り
エラーを検出すると、検出した行を表示しますが、これは、エラーが判明した場所で、必ずしもエラーある場所ではないので、表示された行にエラーがないときはその前の行をチェックしてください。
実行番地指定:
8進数の後にピリオード記号があると、その8進数を実行を開始する番地として、読み込みにエラーがなければ、その番地に飛びます。
文字列;
“…“で囲まれた範囲は、文字列として1バイトづつ格納されます。最後の番地に000が格納されますが、その番地が、偶数であれば、さらに000を追加して、次の命令が、偶数番地になるように自動的に追加が行われます。これによって、文字列を扱うときに、0をチェックすれば、終端がわかるようになります。
文字列中に、 \(バックスラッシュ)はエスケープ文字として、認識されます。\の後に3桁の8進数字があれば、その数字を1バイトとして扱います。「\」自体を入力する場合は、\\と2回バックするラッシュを打ちます。また、「“」を入力するには、\“で、可能です。\e はエスケープ記号として認識します。
メインプログラムは 150000番地から実行します。
140000から147776番地までは、プログラムのデータ領域として使用します。スタックは140000番地から、小さい方に使っています。
機械語ローダの使い方
snails-mld.ptapの内容を機械語としてロードする場合を説明します。
go 150000(絶対ローダで、機械語ローダを読み込むと、自動で機械語ローダが立ち上がるので、 入力は不要)
で起動します。すぐに一時停止しますから、
attatch ptr snails-mld.ptap
で、紙テープ・イメージを高速テープリーダに取り付けます。
次に、c↩️でプログラムを続行すると、紙テープ・イメージの内容が、メモリに格納されます。
155000番地には、隠しコマンドがあります。 これは、メモリーの内容を紙テープに出力するコマンドで、前もって、紙テープパンチに空のファイルをattachしておくと、メモリの任意の範囲を絶対ローダ形式で打ち出します。隠しコマンドは、エラーチェックなど一切しないので、注意して使ってください。入力ミスがあったら、コントロール eで simh を止めて、最初から、スタートしてください。
始める前に、空のファイルを高速紙テープパンチ装置に、取り付けます。
例えば、 ml-obj.ptapが空のファイルとします。下のコマンドを打つと、もし、同じ名前が、存在しなければ、自動的に、新しいファイルが作られます。
attach ptp ml-obj.ptap
以下コマンドで、ml-boj.ptap に絶対ローダでロードできる2進データを作ることができます。
go 155000で実行すると、隠しコマンドが開始します。
B、E、Sの三つのパラメータ入れます。8進数で入れてください。Bは開始番地、Eは終了番地、Sは、実行番地、絶対ローダでロードすると、Sで指定した番地から、プログラムを開始します。隠しコマンドなので、エラー処理はありません。打ち間違えをしたら、コントロール e で一旦止めて、も一度最初から 、go 155000 で始めてください。
実行を自動的に開始したくなければ、Sに0を入れると、絶対ローダは、データをメモリにロードした後、停止します。
プログラムが終了したら、
detach ptp
で、紙テープ装置から、イメージを外します。
これで、絶対ローダでロードし、自動実行する(しない)テープ・イメージが、 ml-obj.ptapに書き込まれます。