Yabu.log

ITなどの雑記

30日OS自作本3日目

なんかすごく低レイヤー臭が強まったdayでした。

フロッピーの容量は次のように決まる

  • 1セクタ=512バイト
  • 1シリンダ=18セクタ
  • 1面あたりのシリンダ数=80シリンダ
  • ヘッドの数(つまり面の数):2面(両面)

512バイト × 18セクタ × 80シリンダ × 2 = 1474560B ≒ 1.440KB

トラックとシリンダの意味で混乱したのでteratailで聞いて見ました。

teratail.com

記憶装置のトラックとかシリンダとかは情報処理試験を受けるたびに理解せずに暗記して忘れるということを繰り返しましたが、今度はしっかり覚えれた気がします。

ESとBXレジスタを使ったバッファアドレスの決まり方

  • BX = 16ビット = 2^16-1 = 65,535
  • EBX = 32ビット = 2^32-1 = 4,294,967,295

16bitのBXレジスタだけだと64KBしか表せないが、EBXレジスタは4GBまで表せる。が、EBXレジスタが導入されるのは、BXだけじゃ足らん!となってからもっと後のこと。ではBXで足りなくなってからどうやって凌いだかというと。。。16bitのセグメントレジスタであるES(エクストラセグメント)とBXの合わせ技で解決した。

ES * 16 + BXレジスタで番地を指定する。

これで((2^16-1) * 16) + 2^16-1 =1,114,095バイト(およそ1MB)まで指定できるようになった。

セグメントレジスタはBX以外のレジスタを使うときも考慮されるらしくどのセグメントレジスタを使うか指定する必要がある。省略するとDSが選ばれるらしい。だからDSは基本的に0で初期化しないと16の倍数分ブーストされた思わぬアドレスに遭難する恐れがある。

BIOSとのお別れ

32ビットモードを使う以上、16ビットで動いているBIOSとはお別れ。 なおC言語を導入することでnaskを使ってアセンブラ(nas) -> バイナリ(img)で済ませていた手順から大きく変更が入る。

手順 使うツール やること
1 cc1.exe .c -> .gas
2 gas2nask .gas -> .nas
3 nask .nas -> .obj
4 obj2bim .obj -> bim
5 bim2hrb .bim -> hrb
6 cat .bon + hrb でバイナリをくっつける

実際にmakeした時のコマンドにコメントを入れて対応関係を見てみる。 今までは手順3だけでよかったのに途端にやることが増える*1

$ make run
make -r img
make -r haribote.img
../../z_tools/nask ipl10.nas ipl10.bin ipl10.lst
../../z_tools/nask asmhead.nas asmhead.bin asmhead.lst
../../z_tools/gocc1 -I../../z_tools/haribote/ -Os -Wall -quiet -o bootpack.gas bootpack.c #⚠️1
../../z_tools/gas2nask -a bootpack.gas bootpack.nas #⚠️2
../../z_tools/nask bootpack.nas bootpack.obj bootpack.lst #⚠️3
../../z_tools/obj2bim @../../z_tools/haribote/haribote.rul out:bootpack.bim stack:3136k map:bootpack.map \
        bootpack.obj #⚠️4
../../z_tools/bim2hrb bootpack.bim bootpack.hrb 0 #⚠️5
cat asmhead.bin bootpack.hrb > haribote.sys #⚠️6
../../z_tools/edimg   imgin:../../z_tools/fdimg0at.tek \
        wbinimg src:ipl10.bin len:512 from:0 to:0 \
        copy from:haribote.sys to:@: \
        imgout:haribote.img
cp haribote.img ../../z_tools/qemu/fdimage0.bin
make -r -C ../../z_tools/qemu
qemu-system-i386 -L . -m 32 -localtime -vga std -fda fdimage0.bin
WARNING: Image format was not specified for 'fdimage0.bin' and probing guessed raw.
         Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
         Specify the 'raw' format explicitly to remove the restrictions.

個人的には手順6が結構衝撃的。naskで作ったバイナリ(asmhead)にbim2hrbで作ったバイナリをくっ付けてるだけ。 ファイルサイズを確認したけど304+52=356で確かに一致する。

$ls -l
total 3072
-rw-r--r--  1  staff      304  5  5 11:52 asmhead.bin
-rw-r--r--  1  staff       52  5  5 11:52 bootpack.hrb
-rw-r--r--  1  staff      356  5  5 11:52 haribote.sys

手順3で普通にnask使ってるけどここでアセンブルされたobjファイルと手順4,5を通して出来た.hrbファイルの質的な違いがいまいちわからない。

う〜ん。まぁとりあえず進めましょう。

新しく知ったこと

gccはgasというアセンブリ用のソースを出力する

GDBを使ったC言語デバッグは昔こちらの本でちょっとだけやったことがあったのですが、

Hacking: 美しき策謀 第2版 ―脆弱性攻撃の理論と実際

Hacking: 美しき策謀 第2版 ―脆弱性攻撃の理論と実際

gccというコンパイラはgasという名称のアセンブラを前提にしているので、gas用のソースプログラムを出力してしまうのです。

普通にgccってx86とかが実行できる機械語のコードを作ると思っていたのですが、gasというのは初見。*2

c -> x86の命令コード

くらいに思っていたのですが、この矢印の間にgasとか、まだ他にも何かが何個か入るのかもしれません。

objファイルのobjectは目的、の意味

オブジェクトというのは「object」、つまり目的のことです。私たちは機械語を得るためにC言語プログラムを書いているわけで、これを目的ファイルと呼ぶのはそこに由来しています。

へぇ〜そうだったのかobjectって普通に物体とかモノとかそういう感じの意味でつけてるのだと思ってました。

30日でできる! OS自作入門

30日でできる! OS自作入門

*1:まあ動かすだけならmakeコマンドを叩くだけでいいんですが。

*2:デバッグしてた時に見えてたインテル用のオプションで機械語を表示するとかはなんだったんだろう?