2014年9月13日土曜日

[OS作成]30日でできる!OS自作入門 1日目 (2)

数日経ったが、まだ1日目である。むぅぅぅ...

「30日でできる! OS自作入門」のサポートページにはLinux用のツールが公開されているが
筆者の独自ツールを使っているようだった。
あまり独自ツールは使いたくなかったので、いろいろと検索してみると、GASとGCCでも開発できるようだったので、
こちらを試してみた。
OS自作入門では、NASKというNASMベースのアセンブラを使っているが、GASとは構文が全く違うので、
書籍のコードを、いちいちGAS用に変換しなければならず、少し面倒だ。

NASM Intel構文
GAS AT&T構文

GASでは .intel_syntax ディレクティブを使うと、Intel構文にできるようであるが、とりあえずデフォルトのAT&T構文で開発を進めよう。
と言うことで、作成したのがこれ。
helloos1.s
.byte 0xEB, 0x4E, 0x90, 0x48, 0x45, 0x4C, 0x4C, 0x4F
.byte 0x49, 0x50, 0x4C, 0x00, 0x02, 0x01, 0x01, 0x00
.byte 0x02, 0xE0, 0x00, 0x40, 0x0B, 0xF0, 0x09, 0x00
.byte 0x12, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00
.byte 0x40, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x29, 0xFF
.byte 0xFF, 0xFF, 0xFF, 0x48, 0x45, 0x4C, 0x4C, 0x4F
.byte 0x2D, 0x4F, 0x53, 0x20, 0x20, 0x20, 0x46, 0x41
.byte 0x54, 0x31, 0x32, 0x20, 0x20, 0x20, 0x00, 0x00

.space 0x10

.byte 0xB8, 0x00, 0x00, 0x8E, 0xD0, 0xBC, 0x00, 0x7C
.byte 0x8E, 0xD8, 0x8E, 0xC0, 0xBE, 0x74, 0x7C, 0x8A
.byte 0x04, 0x83, 0xC6, 0x01, 0x3C, 0x00, 0x74, 0x09
.byte 0xB4, 0x0E, 0xBB, 0x0F, 0x00, 0xCD, 0x10, 0xEB
.byte 0xEE, 0xF4, 0xEB, 0xFD, 0x0A, 0x0A, 0x68, 0x65
.byte 0x6C, 0x6C, 0x6F, 0x2C, 0x20, 0x77, 0x6F, 0x72
.byte 0x6C, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00

.space 368

.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAA
.byte 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00

.space 4600

.byte 0xF0, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00

.space 1469432
参考にしたBlogでは .skipディレクティブを使っていたが、GASのマニュアルを参照すると、

.skip
.skip is recognized on the 680x0 platform as a synonym for .space.
.space
Syntax: .space size[, fill]
This directive emits size bytes, each of value fill. Both size and fill are absolute expressions. If the comma and fill are omitted, fill is assumed to be zero.

ということなので、RESBに対応するディレクティブは.skipではなく、.spaceを使用した。

$ as --32 -o helloos1 helloos1.s

--32 を付けて 32ビットコードを生成するようにした。

30日でできる!OS自作入門を Linux & GAS で行う (1日目) を参考に、同様にして、ELFヘッダのサイズを調べる。
$ readelf -h helloos1
ELF ヘッダ:
  マジック:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  クラス:                            ELF32
  データ:                            2 の補数、リトルエンディアン
  バージョン:                        1 (current)
  OS/ABI:                            UNIX - System V
  ABI バージョン:                    0
  型:                                REL (再配置可能ファイル)
  マシン:                            Intel 80386
  バージョン:                        0x1
  エントリポイントアドレス:               0x0
  プログラムの開始ヘッダ:          0 (バイト)
  セクションヘッダ始点:          1474664 (バイト)
  フラグ:                            0x0
  このヘッダのサイズ:                52 (バイト)  ← ◆これ
  プログラムヘッダサイズ:            0 (バイト)
  プログラムヘッダ数:                0
  セクションヘッダ:                  40 (バイト)
  セクションヘッダサイズ:            7
  セクションヘッダ文字列表索引:      4

ヘッダのサイズが52バイトなので、ddコマンドで52バイトスキップしてイメージを作成する。
$ dd if=helloos1 of=helloos1.img skip=52 ibs=1 count=1474560
1474560+0 レコード入力
2880+0 レコード出力
1474560 バイト (1.5 MB) コピーされました、 7.76736 秒、 190 kB/秒
最初に作った helloos0.imgと比較する。
$ cmp helloos0.img helloos1.img

qemuで動作確認。
$ qemu-system-i386 -m 32 -localtime -vga std -fda helloos1.img
違いが無いので、当然動く。問題無し。

GASやGCCでの開発方法をBlogで公開してくださった方々に感謝。

参考