OS自作入門 3日目/30日(32ビットモードとC言語)
OS自作入門 3日目/30日(32ビットモードとC言語)
1.はじめに
3日目では、新たなアセンブラの命令やリンカの作成方法やデバッグの方法について解説を行う。3日目も作者オリジナルのプログラムが登場するが、オリジナルプログラムを使用せずに実行する。
<躓きどころ>
今までは、qemuを実行するのは下記命令でよかったが、
qemu-system-i386 helloos.img
フロッピーディスクから読み込むことを明示するため、-fdaを追加する。
qemu-system-i386 -fda helloos.img
2.新しく使用したアセンブラの命令
NASKの命令(30日本著者作成のアセンブラ) NASMの命令(今回使用のフリーのアセンブラ) において違いなし
命令 | 名前 | 内容 |
---|---|---|
JC | jump if carry | キャリーフラグが立っている場合、ジャンプする |
JNC | jump if not carry | キャリーフラグが立っていない場合、ジャンプする |
JBE | jump if below or equal | 比較した結果、それ以下の場合ジャンプする |
JB | jump if below | 比較した結果、それより小さい場合ジャンプする |
EQU | equal | 定数を宣言する際に使用 |
OUT | Output Data to I/O Port | データをレジスタ等に出力する |
NOP | No Operation | 何も実行しない |
CALL | call subroutine | サブルーチン(関数)を呼び出す |
LGDT | Load Descriptor Tables | global descriptor table registerにアドレスを読み込む |
AND | Bitwise AND | 論理積を計算する |
OR | Bitwise OR | 論理和を計算する |
JNZ | jumps only if the zero flag is not set | zero flagがセットされていない場合jumpする |
SHR | Bitwise Logical Shift Right | 右へ指定bitシフト演算する |
JZ | jumps only if the zero flag is set | zero flagがセットされている場合jumpする |
RET | Return from Procedure Call | 呼び出し元に戻る |
ALIGNB | Data Alignment | アライメントを行う |
3.harib00e,f,g
使用したMakefile(harib00e)
IMG=haribote.img IPL=ipl.bin IASM=ipl.asm HSYS=haribote.sys HASM=haribote.asm $(IMG): $(IPL) $(HSYS) mformat -f 1440 -C -B $(IPL) -i $(IMG) :: mcopy $(HSYS) -i $(IMG) :: $(IPL): $(IASM) nasm $(IASM) -o $(IPL) $(HSYS): $(HASM) nasm $(HASM) -o $(HSYS) img: make $(IMG) clean: rm -f $(IMG) $(IPL) $(HSYS)
今回、新たに使用する命令mcopy
の書式は下記の通り
mcopy システムファイル -i 出力イメージファイル ::
オプションの解説
オプション名 | 説明 |
---|---|
-i | マニュアルに記載なし。下記を参照 |
mcopyの引数である、システムファイル
と出力イメージファイル
をそれぞれテキストファイルにした場合は、出力イメージファイル
にシステムファイル
の中身を上書きするが、
sysファイル
とimgファイル
の組み合わせの場合、imgファイルにsysファイルが適切な場所に組み込まれる。
出力イメージファイルについても、元の容量から変化がない。いろいろ調べたが不明。
4.harib00i
書籍では、作者オリジナルのソフトが使用されており、下記の手順でイメージファイルが作成されている。
- cファイルからgasファイルを作成
- gasファイルからnasファイルを作成
- nasファイル(3個) からobjファイル(bootpack)とbinファイル(ipl,asmhead)を作成
- objファイルからbimファイルを作成
- bimファイルからhrbファイルを作成
- hrbファイルとbinファイルを結合し、sysファイルを作成
- sysファイルとbinファイルから、imgファイルを作成
今回もオリジナルのファイルは使わない方法で作成する。手順は下記の通り
- asmファイル(2個) からbinファイル(ipl,asmhead)を作成
- cファイルからhrbファイルを作成
- hrbファイルとbinファイルを結合し、sysファイルを作成
- sysファイルとbinファイルから、imgファイルを作成
躓きどころ
asmhead.asmについて下記のように修正する
行数 | 修正前 | 修正後 |
---|---|---|
58 | [INSTRSET "i486p"] | 削除 |
134,145 | ALIGNB 16 | ALIGN 16, DB 0 |
リンカ
cファイルからhrbファイルを作成する際にリンカが必要になるため作成する。
現時点で作成方法等がわからなかったため、下記サイトを参照した。
OUTPUT_FORMAT("binary"); OUTPUT_ARCH(i386) SECTIONS { .head 0x0 : { LONG(64 * 1024) /* 0 : stack+.data+heap の大きさ(4KBの倍数) */ LONG(0x69726148) /* 4 : シグネチャ "Hari" */ LONG(0) /* 8 : mmarea の大きさ(4KBの倍数) */ LONG(0x310000) /* 12 : スタック初期値&.data転送先 */ LONG(SIZEOF(.data)) /* 16 : .dataサイズ */ LONG(LOADADDR(.data)) /* 20 : .dataの初期値列のファイル位置 */ LONG(0xE9000000) /* 24 : 0xE9000000 */ LONG(HariMain - 0x20) /* 28 : エントリアドレス - 0x20 */ LONG(0) /* 32 : heap領域(malloc領域)開始アドレス */ } .text : { *(.text) } .data 0x310000 : AT ( ADDR(.text) + SIZEOF(.text) ) { *(.data) *(.rodata*) *(.bss) } /DISCARD/ : { *(.eh_frame) } }
Makefile
リンカが増えたことでMakefaileに変更を加えた。
hrbファイルを作成する際に、gcc
を使用する必要があるため、ubuntuにインストールする
sudo apt install gcc
以下に、Makefileの内容を記載する。
主な変更点として、gccによるコンパイルの行の追加とcatによるsysファイルの作成とdumpの追加の3点である。
3点目については必須項目ではなく、出力したimgファイルのバイナリを簡単に確認するためMakefile内に記載した。
IMG=haribote.img IPL=ipl.bin IASM=ipl.asm HD=asmhead.bin HASM=asmhead.asm BT=bootpack.c BHRB=bootpack.hrb LD=har.ld HSYS=haribote.sys $(IPL) : $(IASM) nasm $(IASM) -o $(IPL) $(HD) : $(HASM) nasm $(HASM) -o $(HD) $(BHRB) : $(BT) $(LD) gcc -march=i486 -m32 -fno-pic -nostdlib -T $(LD) $(BT) -o $(BHRB) $(HSYS) : $(HD) $(BHRB) cat $(HD) $(BHRB) > $(HSYS) $(IMG) : $(IPL) $(HSYS) mformat -f 1440 -C -B $(IPL) -i $(IMG) :: mcopy $(HSYS) -i $(IMG) :: img : make $(IMG) dump : hexdump -C $(IMG) clean : rm -f *.lst *.bin *.sys *.img *.hrb
gcc引数 | 説明 |
---|---|
-march=i486 | i486向けのコードを生成する |
-m32 | IA(Intel Architecture) 32向けにコードを生成するようコンパイラーに指示 |
-fno-pic | Generate position-independent code (PIC)を用いない。 |
-nostdlib | リンク時に標準システムスタートアップファイルや標準システムライブラリを使用しない |
-T | 後に続く引数をリンカスクリプトとして使用 |
-o | コンパイルを実行し、オブジェクトファイルを出力する |
degug
degug用に新たにバッチファイルを作成した。qemuで動作確認用のバッチファイルから新たに3つの引数を追加する。
追加引数 | 説明 |
---|---|
-gdb | gdbでデバックするための引数 |
tcp::22222 | デバックするために |
-S | qemu起動時点で動作を停止するため |
debug用batファイル
qemu-system-i386 -m 32 -fda haribote.img -gdb tcp::22222 -S
使い方は、imgファイルをmakeした後、debug用batファイルを使用する。qemuが起動したことを確認し、新たに別のプロンプトを立ち上げ下記コマンドを入力する。
>gdb GNU gdb (GDB) 7.8.1 (いろいろ出力されるが省略) (gdb) target remote localhost:22222 Remote debugging using localhost:22222 0x0000fff0 in ?? ()
上記で、新たに立ち上げたプロンプトからデバックを行うことができる。参考にいくつか実行例を下記に示す。
①ブレイクポイントの設定
iplの読み込み先頭アドレスにブレークポイントを設定
(gdb) b *0x7c00 Breakpoint 1 at 0x7c00
②ブレイクポイントまで実行
設定したブレイクポイントまで実行。0x7c00のブレイクポイントまで進んだことを確認できる。
(gdb) c Continuing. Breakpoint 1, 0x00007c00 in ??
③命令の確認
ブレイクポイントの命令内容を確認。jmp 0x7c50であることを確認できる。
(gdb) x/i $eip => 0x7c00: jmp 0x7c50
コマンドライン上でファイルをダンプ
書式 |
---|
hexdump [オプション] [ファイル名...] |
hexdump haribote.img 0000000 4eeb 4890 5241 4249 544f 0045 0102 0001 0000010 e002 4000 f00b 0009 0012 0002 0000 0000 0000020 0000 0000 0000 5d29 ab8c 4e03 204f 414e 0000030 454d 2020 2020 4146 3154 2032 2020 0000 0000040 0000 0000 0000 0000 0000 0000 0000 0000 0000050 00b8 8e00 bcd0 7c00 d88e 20b8 8e08 b5c0 (以下略)
5.harib00j
asmfunc.asmを新たに作成して、HLTを実装する。新たにアセンブリファイルが増えたので、Makefile等の修正を行う。
asmhead.asmについて下記のように修正する
行数 | 修正前 | 修正後 |
---|---|---|
4 | [FORMAT "WCOFF"] | 削除 |
5 | [BITS 32] | 削除 |
10 | [FILE "naskfunc.nas"] | 削除 |
17 | [SECTION .text] | 削除 |
asmhead.asm追加に伴いMakefileを修正する。
IMG=haribote.img IPL=ipl.bin IASM=ipl.asm HD=asmhed.bin HASM=asmhead.asm FASM=asmfunc.asm FOB=asmfunc.o BT=bootpack.c BHRB=bootpack.hrb LD=har.ld HSYS=haribote.sys $(IPL) : $(IASM) nasm $(IASM) -o $(IPL) $(HD) : $(HASM) nasm $(HASM) -o $(HD) $(FOB) : $(FASM) nasm -g -f elf $(FASM) -o $(FOB) $(BHRB) : $(BT) $(LD) $(FOB) gcc -march=i486 -m32 -fno-pic -nostdlib -T $(LD) -g $(BT) $(FOB) -o $(BHRB) $(HSYS) : $(HD) $(BHRB) cat $(HD) $(BHRB) > $(HSYS) $(IMG) : $(IPL) $(HSYS) mformat -f 1440 -C -B $(IPL) -i $(IMG) :: mcopy $(HSYS) -i $(IMG) :: img : make $(IMG) dump : hexdump -C $(IMG) clean : rm -f *.lst *.bin *.sys *.img *.hrb *.o
nasm引数 | 説明 |
---|---|
-g | Enabling Debug Information. デバッグ情報の出力を有効にする。 |
-f elf | 出力するデバックのファイル形式をelfに指定する |
gcc引数 | 説明 |
---|---|
-g | コンパイル時にデバッグ情報の生成を有効にする。 |
6.harib00iとharib00jの比較
horib00iとharib00jそれぞれのimgファイルを作成し、バイナリがどのように異なるかを確認する。
差異箇所 | harib00i | harib00j | 解説 |
---|---|---|---|
0x0027-0x002D | 49 B5 FD 36 | 5D 8C AB 03 | ブートローダ部 |
0x260E-0x260F | 86 08 | DD 06 | 分かったら追記予定 |
0x2616-0x2617 | 86 08 | DD 06 | 分かったら追記予定 |
0x261C | 59 | 72 | 分かったら追記予定 |
0x4344 | 29 | 42 | 分かったら追記予定 |
0x434C | 04 | 10 | 分かったら追記予定 |
0x4354-0x4358 | 55 89 E5 EB FE | ALL 00 | 分かったら追記予定 |
0x4360-0x4371 | ALL 00 | 55 89 E5 EB FE 66 90 66 90 66 90 66 90-66 90 90 F4 C3 | 分かったら追記予定 |