いものやま。

雑多な知識の寄せ集め

『OS自作入門』を読んでみた。(その1)

前回、『30日でできる! OS自作入門』を読んでいることをちょこっと書いた。

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

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

この本では、小さなプログラムから始めて、少しずつOSっぽい機能をつけていき、最終的にはOSが出来上がるようにしている。
最初からしっかりと全体を設計して作っていくというわけではなく(もちろん、筆者の中ではやってるのかもしれないけど)、少しずつ継ぎ足し継ぎ足しでプログラムを成長させていくのが面白い。

そんな本なので、実際に手を動かしながら、自分でも動くものを作っていくのが面白いかな、と。

最初のOS?

ということで、最初のOSっぽいプログラム。
まぁ、ブートして文字列を出力するだけのプログラムなんだけどw
しかも、それをアセンブラで書くというわけではなく、イメージをバイナリエディタで作るというw

本ではBzというバイナリエディタを使っているんだけど、自分はMacなので、これは使えず。
そこで、RubyVimを使って同じバイナリイメージを作ってみた。

空データのファイルの作成

フロッピーディスクのディスクイメージを作るんだけど、そのサイズは1440KBで、しかもそのほとんどは空のデータ(0x00)。
これを全部手打ちするのは無駄なので、まずは全部0x00で埋まった1440KBのファイルを作ることにした。
そして、あとで必要な部分を修正していく。

全部0x00で埋まった1440KBのファイルは、Rubyを使ったワンライナーでサクッと。

$ ruby -e 'print "\x0" * 1440 * 1024' > hello-os.img

出来たファイルの中身を見てみると、次のような感じ:

$ hexdump -C hello-os.img
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00168000

1440Kは1474560(=1440x1024)で、これを16進数にすると0x168000なので、これでOK。

Vimを使ったバイナリファイルの編集

空データのファイルは出来たので、あとはこれをVimで編集していく。

Vimでバイナリファイルを編集する場合、-bオプションをつけて起動する:

$ vi -b hello-os.img

起動すると、こんな感じ:

f:id:yamaimo0625:20170422161403p:plain

^@(=0x00)がたくさん並んでいるのが分かると思う。

このままではさすがに編集できないので、編集しやすいようにする。
そのとき使うのが、xxdというコマンド。
このコマンドは、バイナリデータを見やすい16進数表示のテキストに変換してくれたり、逆に、16進数表示のテキストをバイナリデータに変換してくれたりする。

exモードで、以下を実行:

:%!xxd -c 16 -g 1

すると、こんな表示になる:

f:id:yamaimo0625:20170422162012p:plain

ちなみに、-c 16 -g 1はオプションで、なくてもOK。
-cは1行に何バイトずつ表示させるかを指定するオプションで、-gは1列に何バイトずつ表示するのかを指定するオプションになっている。
デフォルトだと1列に2バイトずつ表示され、リトルエンディアンなのかビッグエンディアンなのか分からず戸惑ったので、1列には1バイトずつ表示するようにしている。
(ちなみに、デフォルトだとビッグエンディアンなので、例えば0102 0304 ...と表示されていたら、メモリ上も0x01 0x02 0x03 0x04 ...とデータは並んでいる)

この状態で、バイト列の16進数を本に書かれた通りに修正していく。
これは、テキストファイルを修正しているだけなので、普通に編集すればいい。
すると、以下のような感じ:

f:id:yamaimo0625:20170422162910p:plain

あとは、このテキストファイルをバイナリデータとして書き戻してやるだけ。
それには、xxdコマンドに-rオプションをつけて実行すればいい。

ということで、exモードで以下を実行:

:%!xxd -r -c 16 -g 1

すると、こんな感じ:

f:id:yamaimo0625:20170422163401p:plain

データが書き換わっているのが分かると思う。

保存して中身を確認してみると、次のようになっている:

$ hexdump -C hello-os.img
00000000  eb 4e 90 48 45 4c 4c 4f  49 50 4c 00 02 01 01 00  |.N.HELLOIPL.....|
00000010  02 e0 00 40 0b f0 09 00  12 00 02 00 00 00 00 00  |...@............|
00000020  40 0b 00 00 00 00 29 ff  ff ff ff 48 45 4c 4c 4f  |@.....)....HELLO|
00000030  2d 4f 53 20 20 20 46 41  54 31 32 20 20 20 00 00  |-OS   FAT12   ..|
00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000050  b8 00 00 8e d0 bc 00 7c  8e d8 8e c0 be 74 7c 8a  |.......|.....t|.|
00000060  04 83 c6 01 3c 00 74 09  b4 0e bb 0f 00 cd 10 eb  |....<.t.........|
00000070  ee f4 eb fd 0a 0a 68 65  6c 6c 6f 2c 20 77 6f 72  |......hello, wor|
00000080  6c 64 0a 00 00 00 00 00  00 00 00 00 00 00 00 00  |ld..............|
00000090  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 aa  |..............U.|
00000200  f0 ff ff 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000210  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00001400  f0 ff ff 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00001410  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00168000

これでイメージは完成。

動作確認

イメージが完成したので、さっそく動作確認。
前回QEMUをビルドしてあるので、そのQEMUを使って起動してみた。

$ qemu-system-i386 -fda hello-os.img 

なお、hello-os.imgはフロッピーディスクのイメージなので、-fdaオプションを指定している。

起動すると、以下のような感じ:

f:id:yamaimo0625:20170422164442p:plain

OS?が起動して、"hello, world"が表示されているのが分かると思う。

今日はここまで!

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

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