;-------------------------------------------------
;FAT12 FDDディスクのinit.comという名前のファイルを実行します
;実行ファイルの最大サイズは63KBです
;-------------------------------------------------
[bits 16]
jmp init0
nop
;-----------------------------------------------------------------------------------
;Boot Parameter Block ;Offset byte数 内容
;-----------------------------------------------------------------------------------
OEMLabel db "test " ;03 8 OEM名/初期化を行ったOS.VER
BytePerSector dw 0x0200 ;0b 2 セクター当りのバイト数 通常512固定
SectorsPerCluser db 0x01 ;0d 1 クラスタ当りのセクター数
ReservedSectors dw 0x0001 ;0e 2 起動プログラムが使用するセクター数
NumberFATs db 0x02 ;10 1 FATの数(通常2)
MaxRootEntries dw 0x00E0 ;11 2 ルートディレクトリのエントリー数
NumberSectors dw 0x0b40 ;13 2 論理ディスク当りのセクタ数
MediaDescriptor db 0xf0 ;15 1 ディスクタイプ
SectorsPerFAT dw 0x0009 ;16 2 FAT当りのセクター数
SectorsPerTrack dw 0x0012 ;18 2 トラック当りのセクタ数
NumberHeads dw 0x0002 ;1a 2 ヘッド数
HiddenSectors dd 0x00000000 ;1c 4 隠しセクター数
LargeSectors dd 0x00000000 ;20 4 論理ディスク当りのセクタ数
DriveNumber db 0x00 ;24 1 物理ドライブ番号
Reserved1 db 0x00 ;25 1 予約
BootSignature db 0x29 ;26 1 拡張ブート識別コード
VolumeID dd 0x00000000 ;27 4 ボリュームS/N
VolumeLabel db " " ;2a 11 ボリューム名称
FileSystemLabel db "FAT12 " ;36 8 FATタイプ
;-----------------------------------------------------------------------------------
init0:
jmp 07C0h:init ;アドレス 07C0h にジャンプ。ロード・順次実行が行われる
init:
;初期化処理
cli ;割り込みを無効化
mov ax,07C0h ;セグメントの初期化
mov ds,ax
mov es,ax
mov ss,ax
mov sp,0h ;スタックポインタを0に設定
sti ;割り込みを有効に
start:
call diskSysReset
mov bx, 07E0h ;配置アドレス
mov es, bx
mov bx, 0 ;es:bx セグメント:オフセットの設定
mov ax,14h ;読み出し開始セクター番号
;FATのテーブルがある20セクタ目から14セクタを読み込み 14=MaxRootEntries*32/512
mov cx,14
ReetEntRead:
push cx
call diskRead
add ax,1h ;読み出し開始セクター番号
add bx,200h
pop cx
loop ReetEntRead
;ファイルの情報を全てみる
mov cx,word [MaxRootEntries]
mov bx,0h
FileNum:
push cx
;siの文字列の終端が0になるまで文字列比較
mov si,FileName
mov di,bx
;文字列比較
strcmp:
mov al,[si]
cmp al,0
je .equals
cmp al,[di]
jne .notequals
inc si
inc di
mov cx,[si]
jmp strcmp
.equals:
;ファイルが見つかった
call loadFile
jmp Exec
.notequals:
add bx,020h
pop cx
loop FileNum
mov si,ERRMSG1
call putstr
;----------------------------------------------------------
jmp end
end:
jmp end
;-----------------------------------------------------
;実行
;-----------------------------------------------------
Exec:
;初期化処理
cli ;割り込みを無効化
mov ax,07E0h ;セグメントの初期化
mov ds,ax
mov es,ax
mov ss,ax
mov sp,0h ;スタックポインタを0に設定
sti ;割り込みを有効に
jmp 07E0h:0
jmp end
;------------------------------------------
; ファイルの内容をメモリに展開
;------------------------------------------
lsize dw 0h
hsize dw 0h
rsecsize dw 0h
arsec dw 0h
loadFile:
;配置セクタを取得
mov al,byte [bx+26]
mov ah,byte [bx+27]
add ax,20h ;読み出し開始セクター番号を計算
mov [arsec],ax
;ファイルサイズを取得
mov al,byte [bx+28]
mov ah,byte [bx+29]
mov [lsize],ax
mov al,byte [bx+30]
mov ah,byte [bx+31]
mov [hsize],ax
;上の桁×128secter
push dx
mov ax,[hsize]
mov bx,128
mul bx
mov [rsecsize],ax
pop dx
;下の桁÷512+1
xor dx,dx
mov ax,[lsize]
mov cx,200h
div cx
add ax,1
;上の桁のセクタと下の桁のセクタを足すことによりセクタサイズがもとめられる
add [rsecsize],ax
mov bx, 07E0h ;配置アドレス
mov es, bx
mov bx, 0 ;es:bx セグメント:オフセットの設定
mov ax,[arsec]
mov cx,[rsecsize]
DataSecRead:
push cx
call diskRead
add ax,1h ;読み出し開始セクター番号
mov bx, es ;配置アドレス
add bx,20h
mov es, bx
mov bx, 0 ;es:bx セグメント:オフセットの設定
pop cx
loop DataSecRead
ret
;------------------------------------------
; ディスクシステムのリセット
;------------------------------------------
diskSysReset:
mov ax,0 ;AH = 00h
mov dl,0 ;drive (if bit 7 is set both hard disks and floppy disks reset)
int 13h ;Int 13/AH=00h RESET DISK SYSTEM
;clear if successful (returned AH=00h)
jc diskSysReset
ret
;------------------------------------------
; 1セクターのディスク読み出し
; mov ax,200h ;読み出しセクター番号
; mov bx, 9C0h ;配置アドレス
; mov es, bx
; mov bx, 0 ;es:bx セグメント:オフセットの設定
; call diskRead
;------------------------------------------
sector dw 01h
cylinder dw 00h
head dw 00h
pos dw 00h
pos2 dw 00h
diskRead:
mov [sector],ax
pusha
;$cylinder=int($sector/36);------------------------------
xor dx,dx
mov ax,[sector]
mov cx,36
div cx
mov [cylinder],ax
;$head=int(int($sector-$cylinder*36)/18);-----------------
; pos=$cylinder*36
push dx
mov ax,[cylinder]
mov bx,36
mul bx
mov [pos],ax
pop dx
; pos=$sector-pos
mov cx,[sector]
mov ax,[pos]
sub cx,ax
mov [pos],cx
; head=pos/18
xor dx,dx
mov ax,[pos]
mov cx,18
div cx
mov [head],ax
;$sector=$sector-($cylinder*36+$head*18);------------------
; pos=$head*18
push dx
mov ax,[head]
mov bx,18
mul bx
mov [pos],ax
pop dx
; pos2=$cylinder*36
push dx
mov ax,[cylinder]
mov bx,36
mul bx
mov [pos2],ax
pop dx
; pos=pos+pos2
mov cx,[pos]
mov ax,[pos2]
add cx,ax
mov [pos],cx
; sector=sector-pos
mov cx,[sector]
mov ax,[pos]
sub cx,ax
mov [sector],cx
;----------------------------------------------------------
popa
push ax
mov ch, [cylinder] ;low eight bits of cylinder number シリンダ =cylinder=(sector / 36)
mov dh, [head] ;head number =head=(sector-cylinder*36)/18
mov cl, [sector] ;sector number 1-63 (bits 0-5) 読み込み開始セクタ =sector-(cylinder*36+head*18)
mov ah, 02h ;AH=02h
mov al, 1 ;number of sectors to read 1 セクター読み出し
mov dl, 0 ;drive number (bit 7 set for hard disk)
int 13h ;Int 13/AH=02h DISK - READ SECTOR(S) INTO MEMORY
pop ax
jc diskRead
ret
;------------------------------------------
;al レジスタの数字から文字に
;------------------------------------------
itoa:
add al,48
ret
;------------------------------------------
; al レジスタの値を画面に出力
;------------------------------------------
putc:
push bx
mov ah, 0Eh
mov bx, 7
int 10h
pop bx
ret
;------------------------------------------
;文字列を画面に出力
;mov si,string
;call putstr
;string db "testTest"
;------------------------------------------
putstr:
pusha ;全レジスタのスタック待避
putstrloop:
lodsb
cmp al,0
je putstrend
call putc
jmp putstrloop
putstrend:
popa ;全レジスタのスタック復帰
ret
FileName db "INIT COM",0 ;11文字
ERRMSG1 db "The file is not found."
;MBRとして起動するために必要
times 510-($-$$) db 0 ;510バイトまで0で埋める
dw 0AA55h ;MBRをMBRたらしめるマジックナンバーを書き込む
▲トップページ
>
プログラミングの実験
>
OSなしで実行できるプログラム