OS自作入門 + アルファ part1
OS自作入門 + アルファ part1
ブートセクタ (テスト)
%define FAT_ADDR 0x7E00
%define ROOT_ADDR 0xA200
%define BOOT_FILE_ADDR 0x0500[BITS 16]
ORG 0x7C00;
; IPLへジャンプ
;
JMP entry
DB 0x90 ; Windows 8 では必須;
; OEM name string (ブートセクタの名前)
;
BS_OEMName DB "EatIce ";
; BIOS Parameter Block
;
BPB_BytsPerSec DW 512 ; セクターあたりのバイト数
BPB_SecPerClus DB 1 ; クラスターあたりのセクター数
BPB_RsvdSecCnt DW 1 ; FAT場所 (起動プログラムのセクター数)
BPB_NumFATs DB 2 ; FAT個数
BPB_RootEntCnt DW 224 ; ルートディレクトリの最大ファイル数 (エントリー数)
BPB_TotSec16 DW 2880 ; ドライブのセクター数 (12bit/16bit用)
BPB_Media DB 0xf0 ; メディアのタイプ
BPB_FATSz16 DW 9 ; FATあたりのセクター数
BPB_SecPerTrk DW 18 ; トラックあたりのセクター数
BPB_NumHeads DW 2 ; ヘッド数
BPB_HiddSec DD 0 ; パーティション前の隠しパーティションのセクター数
BPB_TotSec32 DD 0 ; ドライブのセクター数 (32bit用);
; 拡張 BIOS Parameter Block
;
BS_DrvNum DB 0x00 ; 物理ドライブ番号
BS_Reserved1 DB 0x00 ; 予約
BS_BootSig DB 0x29 ; シグネチャ
BS_VolID DD 0x20131023 ; シリアル番号
BS_VolLab DB "EatIceOS " ; ボリューム名
BS_FilSysType DB "FAT12 " ; FATの種類;
; Initial Program Loader
;
entry:
; レジスタ初期化
XOR AX, AX
XOR BX, BX
XOR CX, CX
XOR DX, DX
; セグメント初期化
MOV DS, AX
MOV ES, AX
MOV FS, AX
MOV GS, AX
; スタック関連初期化
MOV SS, AX
MOV SP, 0xFFFC; ディスクリセット
CALL DiskReset; FAT読み込み
CALL FATLoad; ルートディレクトリ読み込み
CALL RootLoad; ファイル読み込み
MOV SI, BootFileName
MOV BX, BOOT_FILE_ADDR
CALL FileRead; ファイル読み込み確認テスト (テキトウ)
MOV SI, BOOT_FILE_ADDR
CALL MsgDraw; 成功
MOV SI, MSG_OK
CALL MsgDrawfin:
HLT
JMP fin; 失敗
error:
MOV SI, MSG_ERR
CALL MsgDraw
JMP fin; -------------------------------- ;
; 高度なサブルーチン
; -------------------------------- ;;
; FAT読み込み
;
FATLoad:
XOR AX, AX
MOV AL, BYTE [BPB_NumFATs] ; FAT数
MUL WORD [BPB_FATSz16] ; ×FATあたりサイズ
MOV CX, AX ; FATサイズ (ループ回数)
MOV AX, WORD [BPB_RsvdSecCnt] ; FAT場所
;
ADD WORD [CurSecter], AX
ADD WORD [CurSecter], CX
; FAT読み込みメモリアドレス
MOV BX, FAT_ADDR
; 読み込み
CALL DiskRead
RET;
; ルートディレクトリ読み込み
;
RootLoad:
MOV AX, 32 ; エントリサイズ
MUL WORD [BPB_RootEntCnt] ; ×エントリ数
; 四捨五入割り算
ADD AX, WORD [BPB_BytsPerSec]
DEC AX
DIV WORD [BPB_BytsPerSec]
MOV CX, AX ; ルートサイズ (ループ回数)
; XOR AX, AX
; MOV AL, BYTE [BPB_NumFATs] ; FAT数
; MUL WORD [BPB_FATSz16] ; ×FATあたりサイズ
; ADD AX, WORD [BPB_RsvdSecCnt] ; +FAT場所 =ルート場所
MOV AX, WORD [CurSecter] ; ルート場所
;
ADD WORD [CurSecter], CX
; ルート読み込みメモリアドレス
MOV BX, ROOT_ADDR
; 読み込み
CALL DiskRead
RET;
; ファイル読み込み
;
; DS:SI == 文字列メモリアドレス, ES:BX == 読み込み先メモリアドレス
;
FileRead:
PUSH BX
CALL GetFstClusByFileName
POP BX
CALL FileReadByFstClus
RET; -------------------------------- ;
; 中位なサブルーチン
; -------------------------------- ;;
; ファイル名から開始クラスタ取得
;
; DS:SI == 文字列メモリアドレス
;
; AX = 開始クラスタ
;
GetFstClusByFileName:
MOV BX, ROOT_ADDR
MOV CX, WORD [BPB_RootEntCnt] ; エントリ数 (ループ回数)
GetFstClusByFileNameLp:
MOV DI, BX
PUSH CX
; 異なる文字数カウント
MOV CX, 11
PUSH DI
PUSH SI
REPE CMPSB
POP SI
POP DI
JCXZ GetFstClusByFileNameFin
; 次のエントリ
POP CX
ADD BX, 32
LOOP GetFstClusByFileNameLp
; 1件もヒットしなかった
JMP error
GetFstClusByFileNameFin:
POP CX
MOV AX, WORD [BX+26]
RET;
; 開始クラスタからファイル読み込み
;
; AX == 開始クラスタ, ES:BX == 読み込み先メモリアドレス
;
FileReadByFstClus:
FileReadByFstClusNext:
PUSH AX
SUB AX, 2
XOR CX, CX
MOV CL, BYTE [BPB_SecPerClus]
MUL CX
ADD AX, WORD [CurSecter] ; データエリア場所
MOV CX, 1
CALL DiskRead
POP AX
PUSH BX
; クラスタの場所
MOV BX, AX
SHR BX, 1
ADD BX, AX
; クラスタのメモリアドレス
ADD BX, FAT_ADDR
MOV DX, WORD [BX]
; 偶数番目 (奇数番号) なら右へ半byteシフト
TEST AX, 1
JZ FileReadByFstClusElse
SHR DX, 0x0004
FileReadByFstClusElse:
AND DX, 0x0FFF
; 次のクラスタ
MOV AX, DX
CMP DX, 0x0FF0
;
POP BX
JB FileReadByFstClusNext
; 読み込み終了
RET; -------------------------------- ;
; 簡単なサブルーチン
; -------------------------------- ;;
; DiskReset
;
DiskReset:
MOV AH, 0x00 ; ドライブ初期化
MOV DL, BYTE [BS_DrvNum] ; ドライブ番号
INT 0x13
JC error ; 失敗時
RET;
; DiskRead
;
; AX == LBA, ES:BX == 読み込み先メモリアドレス, CX == セクター数
;
DiskRead:
DiskReadNext:
MOV DI, 5 ; エラーカウンタ
DiskReadRetry:
PUSH AX
PUSH BX
PUSH CX
; LBAチェック
CMP AX, WORD [BPB_TotSec16]
JAE error
; LBA2CHS
XOR DX, DX
DIV WORD [BPB_SecPerTrk]
INC DL
MOV CL, DL ; セクター
XOR DX, DX
DIV WORD [BPB_NumHeads]
MOV DH, DL ; ヘッド
MOV CH, AL ; シリンダー
; 読み込み実行
MOV AH, 0x02 ; ドライブ読み込み
MOV AL, 0x01 ; セクター数
MOV DL, BYTE [BS_DrvNum] ; ドライブ番号
INT 0x13
JNC DiskReadFin ; 成功時
; 失敗時
CALL DiskReset
POP CX
POP BX
POP AX
DEC DI
JNZ DiskReadRetry ; やり直す
JMP error
DiskReadFin:
POP CX
POP BX
POP AX
; 次のセクター読み込み準備
ADD BX, WORD [BPB_BytsPerSec]
INC AX
LOOP DiskReadNext
RET;
; 文字列表示
;
; DS:SI == 文字列メモリアドレス
;
MsgDraw:
PUSH SI
MsgDrawLp:
LODSB
OR AL, AL
JZ MsgDrawFin
MOV AH, 0x0E ; 一文字表示
MOV BH, 0x00 ; 0
MOV BL, 0x07 ; カラーコード
INT 0x10
JMP MsgDrawLp
MsgDrawFin:
POP SI
RET; -------------------------------- ;
; その他
; -------------------------------- ;;
; 変数, データ
;
MSG_OK DB 0x0A, "OK", 0x0A, 0x00
MSG_ERR DB 0x0A, "ERROR", 0x0A, 0x00
BootFileName DB "TEST TXT", 0x00
CurSecter DW 0;
; 残りを 0 で埋める
;
TIMES 510 - ($ - $$) DB 0x00;
; Boot Signature
;
DB 0x55, 0xaa
おお、これは見事なアセンブリ・・・
本格的になってきましたね。
ありがとうございます!!
アセンブリ初心者だったのですが、なんとかここまでできました…