非情報系インフラエンジニアの情報系お勉強

OS自作、ネットワーク、セキュリティの備忘録

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ファイルが適切な場所に組み込まれる。 出力イメージファイルについても、元の容量から変化がない。いろいろ調べたが不明。

qiita.com

4.harib00i

書籍では、作者オリジナルのソフトが使用されており、下記の手順でイメージファイルが作成されている。

  1. cファイルからgasファイルを作成
  2. gasファイルからnasファイルを作成
  3. nasファイル(3個) からobjファイル(bootpack)とbinファイル(ipl,asmhead)を作成
  4. objファイルからbimファイルを作成
  5. bimファイルからhrbファイルを作成
  6. hrbファイルとbinファイルを結合し、sysファイルを作成
  7. sysファイルとbinファイルから、imgファイルを作成

今回もオリジナルのファイルは使わない方法で作成する。手順は下記の通り

  1. asmファイル(2個) からbinファイル(ipl,asmhead)を作成
  2. cファイルからhrbファイルを作成
  3. hrbファイルとbinファイルを結合し、sysファイルを作成
  4. sysファイルとbinファイルから、imgファイルを作成

躓きどころ

asmhead.asmについて下記のように修正する

行数 修正前 修正後
58 [INSTRSET "i486p"] 削除
134,145 ALIGNB 16 ALIGN 16, DB 0

www.nasm.us

hrb.osask.jp

リンカ

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) }

}

vanya.jp.net

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 コンパイルを実行し、オブジェクトファイルを出力する

bttb.s1.valueserver.jp

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

bttb.s1.valueserver.jp

qiita.com

コマンドライン上でファイルをダンプ

書式
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] 削除

hrb.osask.jp

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に指定する

ja.wikipedia.org

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 分かったら追記予定