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

この記事は2年以上前に書いたものです。
そのため情報が古い可能性があります。ご了承ください。m(_ _)m

がなかなか進まないのは、本が重いからだな。もしくは、重い本を置く場所が膝の上くらいしか無いから。我が家では。
広い机が欲しい。

三日目

ちゃんとしたIPL(*1)の作成、OS本体を書き始める、32ビットモード突入、C言語。

*1: ブートセクタ以外も読み込むIPLだとか

; ipl.nas
; haribote-ipl
; TAB=4

CYLS    EQU     10              ; どこまで読み込むか

        ORG     0x7c00          ; このプログラムがどこに読み込まれるのか

; 以下は標準的なFAT12フォーマットフロッピーディスクのための記述

        JMP     entry
        DB      0x90
        DB      "HARIBOTE"      ; ブートセクタの名前を自由に書いてよい(8バイト)
        DW      512             ; 1セクタの大きさ(512にしなければいけない)
        DB      1               ; クラスタの大きさ(1セクタにしなければいけない)
        DW      1               ; FATがどこから始まるか(普通は1セクタ目からにする)
        DB      2               ; FATの個数(2にしなければいけない)
        DW      224             ; ルートディレクトリ領域の大きさ(普通は224エントリにする)
        DW      2880            ; このドライブの大きさ(2880セクタにしなければいけない)
        DB      0xf0            ; メディアのタイプ(0xf0にしなければいけない)
        DW      9               ; FAT領域の長さ(9セクタにしなければいけない)
        DW      18              ; 1トラックにいくつのセクタがあるか(18にしなければいけない)
        DW      2               ; ヘッドの数(2にしなければいけない)
        DD      0               ; パーティションを使ってないのでここは必ず0
        DD      2880            ; このドライブ大きさをもう一度書く
        DB      0,0,0x29        ; よくわからないけどこの値にしておくといいらしい
        DD      0xffffffff      ; たぶんボリュームシリアル番号
        DB      "HARIBOTEOS "   ; ディスクの名前(11バイト)
        DB      "FAT12   "      ; フォーマットの名前(8バイト)
        RESB    18              ; とりあえず18バイトあけておく

; プログラム本体

entry:
        MOV     AX,0            ; レジスタ初期化
        MOV     SS,AX
        MOV     SP,0x7c00
        MOV     DS,AX

; ディスクを読む

        MOV     AX,0x0820
        MOV     ES,AX
        MOV     CH,0            ; シリンダ0
        MOV     DH,0            ; ヘッド0
        MOV     CL,2            ; セクタ2
readloop:
        MOV     SI,0            ; 失敗回数を数えるレジスタ
retry:
        MOV     AH,0x02         ; AH=0x02 : ディスク読み込み
        MOV     AL,1            ; 1セクタ
        MOV     BX,0
        MOV     DL,0x00         ; Aドライブ
        INT     0x13            ; ディスクBIOS呼び出し
        JNC     next            ; エラーがおきなければnextへ
        ADD     SI,1            ; SIに1を足す
        CMP     SI,5            ; SIと5を比較
        JAE     error           ; SI >= 5 だったらerrorへ
        MOV     AH,0x00
        MOV     DL,0x00         ; Aドライブ
        INT     0x13            ; ドライブのリセット
        JMP     retry
next:
        MOV     AX,ES           ; アドレスを0x200進める
        ADD     AX,0x0020
        MOV     ES,AX           ; ADD ES,0x020 という命令がないのでこうしている
        ADD     CL,1            ; CLに1を足す
        CMP     CL,18           ; CLと18を比較
        JBE     readloop        ; CL <= 18 だったらreadloopへ
        MOV     CL,1
        ADD     DH,1
        CMP     DH,2
        JB      readloop        ; DH < 2 だったらreadloopへ
        MOV     DH,0
        ADD     CH,1
        CMP     CH,CYLS
        JB      readloop        ; CH < CYLS だったらreadloopへ

; 読み終わったのでharibote.sysを実行だ!

        JMP     0xc200

error:
        MOV     AX,0
        MOV     ES,AX
        MOV     SI,msg
putloop:
        MOV     AL,[SI]
        ADD     SI,1            ; SIに1を足す
        CMP     AL,0
        JE      fin
        MOV     AH,0x0e         ; 一文字表示ファンクション
        MOV     BX,15           ; カラーコード
        INT     0x10            ; ビデオBIOS呼び出し
        JMP     putloop
fin:
        HLT                     ; 何かあるまでCPUを停止させる
        JMP     fin             ; 無限ループ
msg:
        DB      0x0a, 0x0a      ; 改行を2つ
        DB      "load error"
        DB      0x0a            ; 改行
        DB      0

        RESB    0x7dfe-$        ; 0x7dfeまでを0x00で埋める命令

        DB      0x55, 0xaa

↑のコードでは、読み込んだデータ(第2セクタ以降のデータ)を、0x08200~に入れていっている。

; ディスクを読む

        MOV     AX,0x0820
        MOV     ES,AX
        MOV     CH,0            ; シリンダ0
        MOV     DH,0            ; ヘッド0
        MOV     CL,2            ; セクタ2
readloop:
        MOV     SI,0            ; 失敗回数を数えるレジスタ
retry:
        MOV     AH,0x02         ; AH=0x02 : ディスク読み込み
        MOV     AL,1            ; 1セクタ
        MOV     BX,0
        MOV     DL,0x00         ; Aドライブ
        INT     0x13            ; ディスクBIOS呼び出し
・・・

0x08000~0x081ffには、後でブートセクタを入れるらしいので、
0x08000~ディスクを読み込んだデータが入る事になると。
FAT12の場合は(?)、ディスクイメージにファイルを保存すると、0x004200に保存されるらしく、
0x008000 + 0x004200 = 0xc200
だから、↓で0xc200にJMP。

; 読み終わったのでharibote.sysを実行だ!

        JMP     0xc200

そうすると、↓が実行される。

; haribote.nas
; haribote-os
; TAB=4

        ORG     0xc200          ; このプログラムがどこに読み込まれるのか
fin:
        HLT
        JMP     fin

そんな感じのイメージの作成は、↓の部分らしい。

# Makefile
・・・
haribote.img : ipl.bin haribote.sys Makefile
    $(EDIMG)   imgin:../z_tools/fdimg0at.tek \
        wbinimg src:ipl.bin len:512 from:0 to:0 \
        copy from:haribote.sys to:@: \
        imgout:haribote.img
・・・

tools/edimg – hrb-wikiによると、
copy from:xxx.xxx to:@:
は、ファイル(xxx.xxx)をディスクイメージにコピーする。

edimg.exeでコピーすると、
・ファイル名は、0x002600以降
・ファイルの中身は、0x004200以降
に入るとのこと。

The FAT File System
19~32セクタ(0x2600~0x41ff)が、Root Directory
33~2879セクタ(0x4200~0x167fff)が、File storage space
だとか。

32bitモードへ入るアセンブラの説明は後ほどとのこと。

OS自作入門でのC言語でのプログラミングは、
・cc1.exeでコンパイルし、gas(Gnu ASsembler)なファイルを作成する。
・gas2nask.exeを使って、gasなファイルをなファイルに変換する。
・nask.exeを使って、naskなファイルをアセンブルする。
・obj2bim.exe(リンカ)を使って、リンクする。(bimは、Binary IMageの略だとか)
・bim2hrb.exeを使って、ハリボテOS用の形式にする。
という一連の流れが必要らしい。

Makefileでやってるので、叩くコマンドは変わらず。

カテゴリー: ソフトウェア タグ: , パーマリンク

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です