30日でできる!OS自作入門を Linux & GAS で行う (1日目)

gcc & as in Linux環境 で OS自作入門したい!と思ったので、そのために環境構築してみた。モチベーションとしては、

  1. Linuxコンパイルgcc で行われているから、gccで生成したバイナリをそのまま使えた方がlinuxも理解できるかも。
  2. ブートローダをGASで書けたらとても素敵だよね。

といったあたり。

しかし、OS自作本は Windows 向けに開発環境としてコンパイルされたバイナリのみが提供されているため、gasなどで試そうとしてもソースは違うわ、バイナリは違うわで動かない、やる気なくす、本は放置となってしまう。それじゃあもったいないということで、gas & as で OS自作入門を試してみようじゃないか、試すのだったら後でやる人がスムーズに同じことできるようにメモをとってったらいいんじゃないか、という趣旨。

教科書

いわずもがな、30日でできるOS自作入門。

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

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

加えて、Linux環境で「30日でできる!OS自作入門」を試していらっしゃる touch さんの まとめ blog。
http://www14.big.or.jp/~touch/blog/os/

環境

Ubuntu 8.04 LTS Desktop (Kernel 2.6.26.8)
基本的に Linux 環境で、かつ gcc と make のバージョン(後述)が合ってる環境ならいけるのではないかな?

代替品の用意

どの道具が何を行っているかを、以下にまとめる。

種類 ツール名
バイナリエディタ hexer (emacs 使いの方は emacs のバイナリ編集モードが良いかも)
Dosのディスクイメージ生成プログラム mformat
ビルド用ユーティリティ GNU make 3.81
コンパイラ gcc 4.2.4
アセンブラ GNU Assembler 2.18.0
リンカ GNU ld 2.18.0.20080103

早速、上記プログラムをインストールする。

 sudo aptitude install build-essential hexer mtools qemu

1日目をやってみる

バイナリエディタでイメージ作成

まず、viライクなバイナリエディタhexerを起動して、ディスクイメージを作成。
hexer helloos.img
これは打ち込むだけなので対した苦労はない。できたら、
qemu -fda ./helloos.img
として起動する。Hello, world が出力されていたら正常に読み込まれている証拠。

GASでデータを配置

さて、ここからが本番。GASでデータを配置していく。問題は大きくわけて2つあって、

  1. GASで記述する(nasmではDWなどでデータを保存していくところを、.wordなどGASの記法に置換しながらかき進める必要がある)
  2. 記述したテキストファイルをasに食わせると実行可能バイナリ(elf)形式として吐き出される

と言う問題がある。1.は、OS自作入門メモ (1日目)を参考にすればいけるはず。対応表は以下の通り;

nasm(nask) gas
DB .byte
DW .word
DD .int
ORG なし
fresb .org

ソースファイルの入力が終了したら、asでアセンブルする。

as gen_image.s -o tmp.img

2.については、書き込み時にelfヘッダをスキップして書き込むことで解決する。elfヘッダが何バイトか調べるには、バイナリエディタでイメージファイルを開いて数えても楽しいけれど、readelfコマンドを使うと大変便利。

readelf -h tmp.img 
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Size of this header:               52 (bytes)
  Size of program headers:           0 (bytes)
  Number of program headers:         0

先頭52バイトがelfヘッダで、その他にはヘッダは存在しないということがわかった。なので、これをスキップして別ファイルに書き込む。書き込みには、みなさんお馴染みddコマンドを使用する。

as gen_image.s -o tmp.img
dd if=tmp.img of=helloos.img skip=52 bytesize=1

最後に、helloos.imgを用いてqemuを起動する。

qemu -fda ./helloos.img

これで無事起動すれば、1日目は終了。

なお、私の書いたソースコードはこちら↓

  1   .byte   0xeb,0x4e,0x90
  2   .ascii  "HelloIpl"
  3   .word   512
  4   .byte   1
  5   .word   1
  6   .byte   2
  7   .word   224
  8   .word   2880
  9   .byte   0xf0
 10   .word   9
 11   .word   18
 12   .word   2
 13   .int    0
 14   .int    2880
 15   .byte   0,0,0x29
 16   .int    0xffffffff
 17   .ascii  "HELLO-OS   "
 18   .ascii  "FAT12   "
 19   .skip   18,0
 20 
 21 // Entry Point of this program!!
 22   .byte   0xb8, 0x00, 0x00, 0x8e, 0xd0, 0xbc, 0x00, 0x7c
 23   .byte   0x8e, 0xd8, 0x8e, 0xc0, 0xbe, 0x74, 0x7c, 0x8a
 24   .byte   0x04, 0x83, 0xc6, 0x01, 0x3c, 0x00, 0x74, 0x09
 25   .byte   0xb4, 0x0e, 0xbb, 0x0f, 0x00, 0xcd, 0x10, 0xeb
 26   .byte   0xee, 0xf4, 0xeb, 0xfd
 27 
 28 // Data for message.
 29   .byte   0x0a, 0x0a
 30   .ascii  "hello,world,yeahhh!"
 31   .byte   0x0a
 32   .byte   0
 33   .org    0x1fe,0
 34 
 35   .byte   0x55, 0xaa
 36 
 37   .byte   0xf0,0xff,0xff,0x00,0x00,0x00,0x00,0x00
 38   .skip   4600
 39   .byte   0xf0,0xff,0xff,0x00,0x00,0x00,0x00,0x00
 40   .skip   1469432
 41