そのため情報が古い可能性があります。ご了承ください。m(_ _)m
os自作入門がなかなか進まないのは、本が重いからだな。もしくは、重い本を置く場所が膝の上くらいしか無いから。我が家では。
広い机が欲しい。
三日目
ちゃんとしたIPL(*1)の作成、OS本体を書き始める、32ビットモード突入、C言語。
*1: ブートセクタ以外も読み込むIPLだとか
; 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。
JMP 0xc200
そうすると、↓が実行される。
; haribote-os
; TAB=4
ORG 0xc200 ; このプログラムがどこに読み込まれるのか
fin:
HLT
JMP fin
そんな感じのイメージの作成は、↓の部分らしい。
・・・
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なファイルに変換する。
・nask.exeを使って、naskなファイルをアセンブルする。
・obj2bim.exe(リンカ)を使って、リンクする。(bimは、Binary IMageの略だとか)
・bim2hrb.exeを使って、ハリボテOS用の形式にする。
という一連の流れが必要らしい。
Makefileでやってるので、叩くコマンドは変わらず。