;-------------------------------------------------
;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なしで実行できるプログラム