Virtualboxで、Hello World!! IPLプログラムを自作した。

Manjaro Linux上のVirtualBoxで、FD起動の単純なIPLプログラムを作ってみた。もう十五年くらい前に、CD起動でやろうとして、当時はVMwareやVirtualBoxのような仮想環境が手元になく、古いパソコンで試行錯誤したが、結局、何も動かずに諦めた。先日、VirtualBoxをいろいろ試していて、FDディスクイメージを作成したり、起動できることを知り、インターネットで調べたら、豊富に情報があり、定番のHello WorldをIPLプログラムで表示してみることにした。
アセンブラにIntel記法とAT&T記法があり、プログラムの記述にばらつきがあって混乱したが、Manjaro Linux標準のGNUアセンブラとリンカだけで、見事、VirtualBoxの実行画面に表示させることができた。参考にしたのは、以下の書籍。ロングセラーの定番らしい。

— 書籍 30日でできる! OS自作入門

ただし、この本では、naskとかいう独自アセンブラのIntel記法なので、Manjaro LinuxのGNUツールチェーンとは、かなり違っている。それで、GNUアセンブラのAT&T記法で自分で書き直しながら、インターネットのサンプルプログラムを盛り込んで、FDディスクイメージを作成した。

VirtualBoxの設定をして、恐る恐る起動したら、動作画面に”H”の文字が無限に表示されてしまった。プログラムを見直すと、ジャンプ判定が間違っていて、Intel記法のままだった。それを修正して、再度起動すると、見事に「Hello World!!」の文字が画面先頭に表示された。十五年前の挫折を克服した、という感慨と感動は、涙までは流しはしなかったが、言葉に言い表せない。それで気付いたのだが、私はRAM上のアドレスと、ディスクイメージ内のアドレスを混同していて、それが以前IPLプログラム作成に失敗した大きな理由だと分かった。上記の書籍でも、その区別を意識せずに読んでいると、いきなり「0xa000へ書き込む」とか書かれていて、あれ?メモリ上の0x8000へプログラムをロードするとか書いてなかったか?と意味不明に陥っていた。それは、インターネット上の情報でも同じで、書いた人は分かっているのだろうが、イメージ図をふんだんに使って、もっと明示的にどちらのアドレス指定なのか書いてくれないと、初めての人は混乱するのではないかと思った。

メッセージを表示して無限ループで停止するモニタープログラムを作って、フロッピーディスクイメージからロードさせることに挑戦した。
ディスクからセクターを読む指定には、CHS方式とLBA方式があるが、今回はフロッピーディスクのFAT12という前提で、それとブートセクターは512バイトしかないので複雑なプログラムを組めないこともあり、上記書籍を参考に、CHS方式をアセンブラでプログラミングして読み込こもうとしたが、プログラムを組んでいくうちに、それでは駄目だと思い始めた。
CHS方式はハードウェアとしてのドライブの構造に依存していて、シリンダーの数やヘッドやセクターの数を指定してBIOSで読み込むことになる。フロッピーでしか動かさないのであれば、それらの数を定数で決め打ちしてプログラムを作ることはできるが、それでも、ある程度大きなプログラムをロードしようとすると、ヘッダ番号やシリンダ番号を切り替えなければならない。(例:CHS方式では、先頭から19番目のセクターを読む時には、フロッピーディスクの片面のトラックにはセクターが18しかないので、ヘッダを切り替えて、シリンダー番号0-ヘッダ番号1のセクター1として指定する)ハードディスクドライブやSSDなどへ移植する場合は、またプログラムをそれぞれに合わせて書き換えることになり、それよりは、BIOSでドライブ情報(当該ドライブのシリンダー数、ヘッド数、セクター数)を取得して、アクセスしたいセクターを計算でCHS方式に変換する方が汎用性がある。また、LBA方式は論理的な順列のセクター番号なので、セクター番号0から順番に値を増やしていけるのでロジックの見通しがよい。ただディスクから読み込むときは、必ずCHS方式に変換し指定して、1セクターずつBIOSで読み出す必要がある。そこは複雑でもサブルーチンを作成するしかない。ディスクイメージの概念図では、記憶する領域がずっと一続きで連続しているようなイメージを持ちがちだが、実際はCHS方式のように、磁気ディスクの円盤の裏面へ移動したり、シリンダーを切り替えたりという物理的な形状の断絶があることをしっかり頭に叩き込まないと、なぜこんな複雑なプログラムを書かなければならないのか意味不明になって、理解が追い付かず、挫折するのではないかと思う。

LBAからCHSへの変換ルーチンの作成は時間がかかりそうなので、1セクタ分だけCHS[0,0,2](LBA方式ではLBA[1])から、メッセージ表示するだけのモニタープログラムを読み込んで、モニタープログラムへジャンプするようにした。これも何度目かのトライで、無事「Welcome to Monitor !!」が画面に表示された。
これから暇を見て、少しずつ拡張し、FreeDOS(?)のような、どこかの出来合いのフリーOSを移植しようと思っている。

(2022/11/3 追記) ブートセクターのIPLプログラムを作成する時、高級言語でやっていたように、エラーチェックとエラー処理、どんなエラーが発生したのか、すぐ分かるようにプログラミングしていたが、何と、いつの間にか512バイトをオーバーしてしまい、ブートセクターの中に納まらなくなっていた。プログラムの最後はエラー発生時のメッセージのアスキーコードなので、今まで気づかなかったが、本当にエラーが発生していたらプログラムが暴走していただろう。『30日でできる! OS自作入門』の中のプログラムが決め打ちで、プログラムを簡便化していた理由が分かった。IPLは本当にディスクからRAMへのロードだけしかできないのだ。
IPLプログラム全体を見直し、メッセージは長々とした英文ではなく、簡潔な単語だけに縮小し、先頭のFAT12の情報の後、18バイト領域を空けていたのを2バイトにし、サブルーチンの数を減らすために、BIOSのエラーコードの数値を文字に変換して出力するのを止め、LBAからCHSへの変換ルーチンもbpレジスタやdiレジスタ、siレジスタを作業用に使用するように改造し、push,popする回数を最小限に抑えた。何とかブートセクター内に収めたが、それでも40バイト程度しか空きがなく、もしハードディスクへインストールする場合、パーティション情報をブートセクターへ完全には格納するにはまだ足りない。メッセージの文字列をもっと省略して、「error 1」とかだけにすれば、ぎりぎり何とかなりそうだが、その時にまた考え直そうと思う。

(2022/11/7 追記) IPLプログラムのFDディスクイメージのセクター2以降へ、FAT12のフォーマット時のFAT情報を設定するように改造して、モニタープログラムをファイルとして書き込み、FD内の実際にファイル内容が書き込まれたセクターからRAMへ書き込むようにした。ファイルシステムなしで、ブートとロード専用で直接セクターへの読み書きすることもできるが、三十年以上前のパソコンとMS-DOSはフロッピーだけで動作していて、そんな感じに利用することを取り敢えずの目標とし、また、Manjaro Linuxのファイル操作機能を利用して開発の利便性を向上させることも考えた。
この時、ちょっとドツボに嵌った。Makefile内でターゲットのイメージを作成する時、vfat形式を指定して/mnt/へマウントし、cpコマンドでファイルを書き込んだ後、すぐアンマウントさせるだけの手順なのだが、mount、umount、cpコマンドはスーパーユーザーでのログインが必要だった。ネットで調べると、.bashrcへ環境変数を設定して、「sudo -S」で実行すれば自動でログインしてくれることが分かったが、パスワードを直に書いてしまうことになり、セキュリティ上問題がある。SSH暗号化を使用する方法もあったが、面倒臭いし、個人の遊びのシステムなので、.bashrcへ直に書くことで我慢した。
Makefileを書き直して問題なくイメージファイルが作成できたのだが、モニタープログラムが想定とは違うセクターへ書き込まれていた。FATのデータ領域は、LBA[33]から始まるのだが、初期化直後の状態でFAT管理情報を作成しているのにも関わらず、LBA[34]から書き込まれている。散々調べたが、その理由は分からなかった。データ領域の先頭クラスターは予約領域なのか、ボリューム情報か何かにでも使用しているのかもしれない。とにかく、IPLのロード開始位置を修正して、無事、モニタープログラムのロードと「Welcome Monitor!!」の表示が正常に行えた。
これからは、32bitプロテクトモードへの切り替えと、画面への文字表示をやっていこうと思っている。

(2022/12/10 追記) Windows10のVMware Player 17でも、仮想マシンにフロッピーディスクドライブのデバイス機能を追加して、起動時に読み込むとFDイメージを読み込むように設定したら、Virtualboxと同様に起動して、画面表示を行えた。

カテゴリー: Linux, VirtualBox, VMware, 自作OS パーマリンク

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です