2014年9月15日月曜日

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

今度はプログラム部分を分かり易く置き換えていく。

helloos3.s

/*
 helloos3.s
*/
 .code16
 jmp entry
 .byte 0x90
 .ascii "HELLOIPL" # ブートセクタの名前
 .word 512  # 1セクタのバイト数
 .byte 1  # クラスタの数
 .word 1  # FAT開始セクタ
 .byte 2  # FATの個数
 .word 224  # ルートディレクトリ領域のエントリ数
 .word 2880  # ドライブのセクタ数
 .byte   0xF0  # メディアタイプ
 .word 9  # FAT領域のセクタ数
 .word 18  # 1トラックのセクタ数
 .word 2  # ヘッド数
 .int 0  # ?
 .int 2880  # ドライブのセクタ数
 .byte 0, 0, 0x29 # ?
 .int 0xFFFFFFFF # ボリュームシリアル番号
 .ascii "HELLO-OS   " # ディスクの名前
 .ascii "FAT12   " # フォーマットの名前
 .space 18

// プログラム
entry:
 movw $0, %ax
 movw %ax, %ss
 movw $0x7C00, %sp
 movw %ax, %ds
 movw %ax, %es

 movw $msg, %si
putloop:
 movb (%si), %al
 add $1, %si
 cmp $0, %al
 je fin  # メッセージの後ろの0x00で終了する
 movb $0x0E, %ah # Write Character in TTY Mode
 movw $15, %bx # カラーコード
 int $0x10  # BIOS interrupt call
 jmp putloop
fin:
 hlt
 jmp fin

// メッセージ 
msg: 
 .string "\n\nhello, world\n"

 .org 0x1FE
 .byte 0x55, 0xAA # 55AAでブートセクタ

// ブートセクタ以降
 
 .byte 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00
 .space 4600
 .byte 0xF0, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00
 .space 1469432
起動時はリアルモードなので、.code16で、16bitコードを生成するように指定する。

ELFヘッダをスキップしたイメージを作るには、リンカスクリプトを使えば良いことが分かった。
NASMのORGに相当するものはGASには無いので、ORGで指定するアドレスはリンカスクリプトで設定する。

lnk.ls

OUTPUT_FORMAT("binary");

IPL_BASE = 0x7C00;

SECTIONS {
  . = IPL_BASE;
}
今までは、asコマンドとddコマンドでイメージを作成していたが、これからは、gccコマンドでイメージを作成できる。
$ gcc -nostdlib -o helloos3.img -Tlnk.ls helloos3.s
今まで通り、qemuで確認してOK。
$ qemu-system-i386 -m 32 -localtime -vga std -fda helloos3.img
ここを参考にすると、リンカスクリプトを
OUTPUT_FORMAT("binary");
IPLBASE = 0x7c00;

SECTIONS {
        . = IPLBASE;
        .text        : {*(.text)}
        .data        : {*(.data)}
        . = IPLBASE + 510;
        .sign        : {SHORT(0xaa55)}
}
のように書くと 0x1FEからの0xAA,0x55も定義できるようだけど、試していない。
今のところ、.text, .dataの設定は不要だった。
そのうち必要になるのかな?

Z80のアセンブラには慣れているせいか、GASの標準であるAT&T構文ではsourceとdestinationが逆なのは、ちょっと気持ち悪く感じる。

参考