***本記事にはプロモーションが含まれています。***
読んだ。
この辺でつまずく人が多い気がする。bimとかhrbとか出てきて気になった。せっかく起動から追っかけてきたのにというのもあって、少し調べてみることにしました。
bimとhrbは、情報を見つけました。
omake/tolsrc/bim2hrb.cの引用。
******************************
[ .bimファイルの構造 ]
+ 0 : .textサイズ
+ 4 : ファイル中の.textスタートアドレス(0x24)
+ 8 : メモリロード時の.textスタートアドレス(0x24)
+12 : .dataサイズ
+16 : ファイル中の.dataスタートアドレス
+20 : メモリロード時の.dataスタートアドレス
+24 : エントリポイント
+28 : bss領域のバイト数
+36 : コード
[ .hrbファイルの構造 ]
+ 0 : stack+.data+heap の大きさ(4KBの倍数)
+ 4 : シグネチャ "Hari"
+ 8 : mmarea の大きさ(4KBの倍数)
+12 : スタック初期値&.data転送先
+16 : .dataのサイズ
+20 : .dataの初期値列がファイルのどこにあるか
+24 : 0xe9000000
+28 : エントリアドレス-0x20
+32 : heap領域(malloc領域)開始アドレス
*******************************
.bimファイルも、.hrbファイルも、上のような構造のヘッダーを持ったファイルになっています。WCOFFという形式は、調べてみたけどわからなかった。普通のCOFFと同じなのか。
Haribote.sysは、asmhead.binとbootpack.hrbを単純にくっつけたものになっているので、
asmhead.bin本体
bootpack.hrbのヘッダー
bootpack.hrbの本体
の三層構造になっています。これが、起動のときに重要な役割をします。
パソコンの電源を投入後、フロッピーが読み込まれて、IPLが実行され、asmhead.binに制御が移るところまではこれまで説明されているのでわかると思います。
その後、asmhead.nasでは、bootpack以下をBOTPAK(0x280000)に転送しています。bootpack:というラベルはasmhead.nasの最後にありますが、上に書いたようにasmhead.binの後ろにはbootpack.hrbがあるので、bootpack.hrbを0x280000に転送していることになります。また、最後にbootpackの起動のところで
JMP DWORD 2*8:0x0000001b
として2番目のデスクリプタの0x1bにジャンプすることで処理が終わっています。2番目のデスクリプタというのは、コピーされたbootpack.hrbがあるところなので、bootpack.hrbの0x1bに飛ぶことになるけど、0x1bというのが謎だった。
bootpack.hrbのヘッダーを見るとちょうど+24の0xe9000000の最後のバイトを指している。バイナリエディタで調べてみると、こんな風になっている。
+24: 0x00 0x00 0x00 0xe9 (0xe9000000)
+32: 0x09 0x00 0x00 0x00 (エントリーアドレス)
ここで、bootpack.hrbの0x1b番目(27番目)から並べてみると、エントリーアドレスはリトルエンディアンなので並べかえて、
0xe9 0x00000009
となって、これを逆アセンブルすると、
JMP _HariStartup
になります。つまり、0xe9というデータを実行可能なコードとみたてて、_HariStartupにジャンプするようになっていました。この_HariStartupというのは、obj2bimで、bootpack.bimにリンクされるライブラリの中にあります。ソースコードはomake/tolsrc/hrblib0a/startup.cにあって、内部でCのソースコードのHariMainを呼んでいます。そこでやっと、bootpack.cのHariMainが実行されます。
HariMainの起動までを要約すると、こんな感じです。
BIOSが、フロッピーのシリンダー0、ヘッド0、セクタ1の512バイト(IPL)を、0x7c00に読み込みます。
[ipl10.nas]
フロッピーのシリンダー10まで、0x8200を先頭に読み込み。Haribote.sysが読み込まれます。
Haribote.sysの先頭asmhead.bin(0xc200)にジャンプ。
[asmhead.nas]
Haribote.sys内のbootpack.hrbを0x280000を先頭にコピー。
コピーしたbootpack.hrbのヘッダー(0x280000 + 0x1b)にジャンプ。
[bootpack.hrbのヘッダー]
bootpack.hrb本体のHariStartupにジャンプ。
[startup.c]
HariMainを呼び出す。
[bootpack.c]
HariMain()を実行します。
フロッピーの内容を1度、メモリーにロードした後、コピーして実行しているところが複雑になっているのかな。