NASM版 Hebo OS ソース

;-----------------------------------------------
; アセンブラ・プログラムのサンプル COM用
;
; 	2005.05.12   "OS.3as" -> "aOS.asm"
;
;	アセンブラを NASK → NASM に変更。
;
;	>nasm ファイル.asm -fbin -o ファイル.com
;	でCOMファイルができる。
;
;	ラベルで先頭が .(ピリオド)は、局所ラベル
;
;-----------------------------------------------
;
	BITS 16		;16ビットコードを生成せよ。

	org	100h	;ロードは100hから。
;//
;// NASMでは org100h としても リストファイルでは 0番地からの
;// 表示となってしまう。 不満あり。NASKではちゃんと100hからになる。
;//

section	.text
start: 
	;ここにコードを書く。

	JMP	_skip		;下の「DW 6」をパスする。
	DW	3072/512	;=6 これは何?
;//
;// NASMでは 下へのジャンプが 3バイトになってしまう。
;// NASKでは、2バイトで済む。コードサイズではNASKの方が優秀。
;//

_skip:	
	mov	AX,0013h	;AL=13h 320x200ドット モード
	int	10h		;(★ AH=00:ビデオモードの切り替え)
	;
	mov	AX,1010h	;AX=1010h:カラーパレット設定
	xor	BX,BX		;BX=0:黒のカラー番号(0--FFh)
	xor	DH,DH		;	DH=赤 (00-3Fhまで有効)
	xor	CX,CX		;	CH=緑  CL=青	
	int	10h		;(★ 黒の設定)
	;
	mov	AX,1010h	;
	mov	BX,15		;BX=15:白のカラー番号
	mov	DH,3Fh		; RGB すべて Full・・・白になる。
	mov	CX,3F3Fh	;
	;
;;	mov	DH,00h		; これだと       ・・・青になる。
;;	mov	CX,003Fh	;
	;
	int	10h		;(★ 白の設定)
	;
	CALL	cls		;●画面消去
	;
	mov	SI,_msg		;OS名(オープニング・メッセージ)
	CALL	putstr		;●文字列表示
	;
	push	DS
	 xor	AX,AX		;		;// 
	 mov	DS,AX		;DSをゼロクリア	;// INT 80h の割り込み
	 ;					;// ベクタテーブルのセット。
	 mov	WORD [ds:0x0200],_syscall	;// _syscallへ飛ぶように
	 mov	[ds:0202h],CS			;// セグメント:オフセットをセットする。
	pop	DS
	;
	CALL	loadDir		;● ディレクトリ情報を取得。
	;

;//---------------------------------------
;// ここから、コマンド入力。(メインループ)
;//---------------------------------------
;
_command:
	xor	AX,AX		;AX <- 0
	mov	BX,_cmdlin	;// コマンドラインバッファを
	mov	CX,40/2		;// 40文字ゼロクリア
.@Lcmd:	
	mov	[ds:BX],AX	;//
	add	BX,2		;//
	dec	CX		;//
	jne	.@Lcmd
	;
	mov	SI,_prompt	;コマンド待ち(>プロンプト)文字
	CALL	putstr		;●文字列表示
	mov	SI,_cursor	;カーソル文字(_)
	CALL	putstr		;●文字列表示
	;
.@Lkeyin:
	mov	AH,00h		;キーが押されるまで待つ。
	int	16h		;(★ キーボード入力)
	;			;文字コード->AL, 走査コード->AH
	xor	BX,BX

	mov	BL,BYTE [_curx]	;X座標 -> BL
	cmp	AL,20h		;キーコード:スペースより小さい
	jb	.@Pcmd1		; -> コントロールコード処理へ
	cmp	AL,7eH		;7Eh以上(アスキー文字でない)
	jae	.@Pcmd1		; -> 同上。
	;
	;// AL=アスキー文字だった場合。
	cmp	BL,39		;カーソルのX座標が、39文字
	jae	.@Pcmd1		; 以上(横いっぱいだった)-> 表示しない。
	;
	mov	SI,_char_cur	;入力文字コード
	mov	[ds:SI+1],AL	; 記憶

	mov	BYTE [BX-2+_cmdlin],AL		;文字列として記憶。

	CALL	putstr		;キー入力のエコー表示
	JMP	.@Lkeyin		;--> キー入力待ちループ。
;
.@Pcmd1:	;// コントロールコード処理
	cmp	AL,08H		;08h=BS(Back Space)
	jne	.@Pcmd2		;--> バックスペースでない。
	;
	;// タブキーが押された
	cmp	BL,3		;X座標が 3未満
	jb	.@Pcmd2		;--> 
	;
	mov	BYTE [BX-3+_cmdlin],0		;コマンド記憶を1文字削除
	;
	mov	SI,_backspace	;一つ文字を消して戻す。
	CALL	putstr		;●
	JMP	.@Lkeyin		;--> キー入力待ちループ。
;--------------------------------
;
.@Pcmd2:
	cmp	AL,0Dh		;0Dh=Enter
	je	.@Pcr		;--> エンターキーが押された。
	JMP	.@Lkeyin		;---> キー入力待ちループへもどる。
;
.@Pcr:	;// エンターが押されたので、コマンド判断へ。
	mov	SI,_delcur_lf	;まずは、カーソルを消して、
	CALL	putstr		;	改行。
	;
	mov	BX,_cmdlin	;コマンド・ラインから
	mov	AX,[ds:BX+0]	; 入力された文字を取り出し。
	mov	CX,[ds:BX+2]	; -> Max 6文字
	mov	DX,[ds:BX+4]	;
	;
	test	AX,AX		;Enterのみ(コマンド無し)
	je	_command	;---> 戻る。
	;
	cmp	AX,6c63H	;// ① 入力文字は "CLS" か?
	jne	.@Next1		;// 63h=C , 6Ch=L
	cmp	CX,0073H	;// 73h=S
	jne	.@Next1		;--> 次のコマンドチェックへ。
	;
	;// CLSコマンド処理
	CALL	cls		;画面を消す。
	JMP	_command
;
.@Next1:
	cmp	AX,6572h	;// ② 入力文字は "RESET" か?
	jne	.@Next2
	cmp	CX,6573h
	jne	.@Next2
	cmp	DX,0074h
	jne	.@Next2
	;
	int	19h		;(★ これでリセットがかかる)
	JMP	_command
;
.@Next2:
	cmp	AX,4142h	;// ③ 入力文字は "BASIC" か?
	jne	.@Next3		; 42h='B' 41h='A'
	cmp	CX,4953h	; 53h='S' 49h='I'
	jne	.@Next3		; 43h='C'
	cmp	DX,0043h
	jne	.@Next3
	;
	int	18h		;(★ ROM-BASIC起動??) これでリセットがかかる
	JMP	_command

.@Next3:
	cmp	AX,6964h	;// ④ 入力文字は "dir" か?
	jne	.@Next4		; 64h='d' 69h='i'
	cmp	CX,0072h	; 72h='r'
	jne	.@Next4
	;
	;-----------------------
	;● dir処理
	;-----------------------
	push	ES
	mov	AX,CS		;// CS+1000hを
	add	AX,1000h	;// -> ES にセット。
	mov	ES,AX		;// 〜512バイトx14=1C00h ディレクトリ情報
	; 
	xor	DI,DI		;ポインタ0クリア
.@Ldir:
	mov	AX,[es:DI]	;1文字づつ読み込み。(ファイル名)
	test	AL,AL		;  文字コード=ゼロなら、
	je	.@Qdir		;  ディレクトリ表示 終了。
	;
	cmp	AL,0E5H		;= データがかかれていない部分が見つかった。
	je	.@Pdir		; -> 次の ファイル・エントリの先頭へ。

	TEST	BYTE [ES:DI+11],18h	;11文字目=「ファイル属性」18h=通常のファイル?
	jne	.@Pdir			;-> 次の ファイル・エントリへ。
	;
	mov 	SI,_cmdlin
	mov	[ds:SI+0],AX	;// ファイル名8文字を
	mov	AX,[es:DI+2]	;// コマンドラインバッファへ
	mov	[ds:SI+2],AX	;// コピーする。
	mov	AX,[es:DI+4]	;//
	mov	[ds:SI+4],AX	;//
	mov	AX,[es:DI+6]	;//
	mov	[ds:SI+6],AX	;//
	;
	mov	AL,20h		;// ファイル名と拡張子の間に1つ空白を入れ、
	mov	AH,[es:DI+8]	;//
	mov	[ds:SI+8],AX	;// さらに、拡張子3文字
	mov	AL,[es:DI+9]	;// コピーする。
	mov	AH,[es:DI+10]	;//
	mov	[ds:SI+10],AX	;//
	
	mov	WORD [ds:SI+12],000Ah	;改行を付け足す。
	;
	CALL	putstr		;ファイル名+拡張子 表示。
	;
.@Pdir:
	add	DI,32		;ポインタを1ディレクトリ分進める。
	JMP	.@Ldir		;ファイルがなくなるまで繰り返す。
.@Qdir:
	pop	ES
	JMP	_command
;	^^^^^^^^^^^^^^^^^^^^^^^^ ここまで DIR処理。
;
;
.@Next4:	;// 外部コマンド "hello"等 入力文字のチェック。
	;
	mov	CL,8		;MAX 8文字までチェックする。
.@Ldir2:
	mov	AL,[ds:BX]	;1文字づつ 確認。
	cmp	AL,00h
	jne	.@Pdir2		; コード=0なら
	 mov	AL,20h		;  → スペースに変更。
.@Pdir2:
	cmp	AL,61h		;小文字の"a"
	jb	.@Pdir3		; 未満なら → 
	cmp	AL,7Ah		;小文字の"z"
	ja	.@Pdir3		; より大きければ →
	;		小文字の"a"〜"z" だった。
	 sub	AL,20h		; 大文字"A"〜"Z"に変換。
.@Pdir3:
	mov	[ds:BX],AL	;キー入力バッファ格納し直す。
	inc	BX		; ポインタup
	dec	CL		; 文字数Down
	jne	.@Ldir2		; 8文字 繰り返す↑(8文字以下なら、残りは空白で埋める)
	;
	sub	BX,8		;ポインタを先頭に戻す。
	;
	push	ES
	mov	AX,CS		;// 
	add	AX,1000h	;// CS+1000h〜1C00h ディレクトリ情報
	mov	ES,AX		;//  → ESにセット。
	;
	xor	DI,DI		;ポインタゼロクリア
.@Bdir:
	mov	AX,[es:DI]	;Dirバッファの先頭から 文字比較。
	test	AL,AL		;  もし、先頭がNULLなら、リスト終わり
	je	.@Qcmd		;	→ コマンド確認 終了。
	
	TEST	BYTE [es:DI+11],18h	;11文字目=「ファイル属性」18h=通常のファイル?
	jne	.@Pdir5			;-> 次の ファイル・エントリへ。
	;
	cmp	WORD [es:DI+8],4F48H	;// 拡張子が 
	jne	.@Pdir5			;// 48h='H' 4Fh='O',41h='A' か?
	cmp	BYTE [es:DI+10],41H	;// そうでなければ、
	jne	.@Pdir5			;//   -> 次の ファイル・エントリへ。
	;
	cmp	AX,[ds:BX]	;// キー入力文字列と
	jne	.@Pdir5		;// ファイル名(8文字)を
	mov	AX,[es:DI+2]	;// 比較し、1文字でも
	cmp	AX,[ds:BX+2]	;// 違っていれば、
	jne	.@Pdir5		;//   -> 次の ファイル・エントリへ。
	mov	AX,[es:DI+4]	;//
	cmp	AX,[ds:BX+4]	;//
	jne	.@Pdir5		;//
	mov	AX,[es:DI+6]	;//
	cmp	AX,[ds:BX+6]	;//
	jne	.@Pdir5		;//
	;
	mov	AX,[es:DI+26]	;Dir情報 26バイト目=(次のクラスタ番号)
	sub	AX,2		;  2引いて、
	;			;  クラスタ/セクタ数 を かける。
	MUL	WORD [_SIZ_CLU]	;// (AX x [mem] → DX:AX)
	;			;これに、ユーザー・データのエントリ 先頭を加えると、
	add	AX,[_LBA_CLU2]	;  実際のデータが格納されている、クラスタ位置になる。

	mov	SI,AX		;SI=クラスタ番号
	mov	CL,1		;CL=読み込むクラスタ数(手抜きで1クラスタ=512バイトまで)
	mov	AX,CS		;//
	add	AX,2000h	;// ユーザプログラムを読み込むバッファ位置
	mov	ES,AX		;//  → ESに CS+2000h
	;
	mov	BX,0100h	;COMファイルを想定し、オフセット 100h〜
	CALL	readSec		;○ 1セクタ読み取り。
	jnc	.@Pdir4		; → エラーが無ければ、実行。
	;
	mov	SI,_diskerr	;FD読み込みエラー
	CALL	putstr		;○ エラーメッセージ表示
	JMP	_command

.@Pdir4:		;--- 外部コマンド(ファイル)の実行。
	mov	AX,ES		;CS+1C00h〜1FFFh が 空いているので、
	mov	SS,AX		; ここをスタックエリアとして利用。
	mov	SP,0FFFEH	; オフセットは 安全をみて FFFEh。
	mov	DS,AX		;DSもCS,ESと同じ。
	push	AX

;@@	push	0100h
	mov	AX,0100h	;実行アドレスを、
	push	AX		; スタックにセット。
	RETF			;POPで 強制実行。
;
.@Pdir5:
	add	DI,32		; 1リストは、32バイト。
	JMP	.@Bdir		;次のファイルリストへ。
.@Qcmd:
	pop	ES
	mov	SI,_badcmd
	CALL	putstr
	JMP	_command
;
;
;-------------------------------
;	データ エリア
;-------------------------------
_msg:				;オープニング・メッセージ
		DB 'heboOS dayoon!',10
_lf:		DB	10,0
_prompt:	DB	'>',0		;コマンド待ち文字

_char_cur:	DB	8,0		;1文字戻す(BS)文字コード
_cursor:	DB      '_',0		;カーソル文字

_backspace:			;BS(バックスペース)
		DB	8,20h,8,8	; 左へ1つ戻し、スペースで文字を消し、
		DB 	'_',0		; プロンプト表示。
	;
_delcur_lf:			; 左へ1つ戻しカーソルを消した後、
		DB	8,20h,10,0	; 改行。

_badcmd:	DB	'Bad command or file name',10,0
_diskerr:	DB	'Disk error',10,0
	
	ALIGNB	2, db 0


_cmdlin:
;??	DB	40 dup (?) 
;	resb 	40		;コマンド文字のバッファ(40文字)
	times 40 db 0

;;main	endp
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


;-------------------------------
;● 画面の消去
cls:
	push	DS
	;
	 mov	AX,0A000h	;ビデオRAMの先頭アドレス
	 mov	DS,AX		; -> DSセグメントへ
	 xor	BX,BX
	 xor	AX,AX
.@Lcls:
	 mov	[ds:BX],AX	;全領域にゼロを書き込む。
	 add	BX,2		;ワード単位で
	 jne	.@Lcls		; BXがゼロになるまで、繰り返し。
	;
	pop	DS
	;
	mov	[_curx],AX	;カーソル位置XYともゼロクリア
	;
	RET
;;cls	endp

;-------------------------------
;● 文字列表示。
; in:	SI	...	文字列
;
putstr:	;	proc	near
	push	ES
	push	DI
	push	SI
	push	BX
	push	CX
	push	AX
	;
	mov	AX,0A000h	;V-RAMの先頭アドレス
	mov	ES,AX		;  -> ESセグメントへ
.@Bstr:
	xor	BX,BX
	mov	BL,[ds:SI]	;1文字取り出し、チェック。
	inc	SI		; ポインタを進める。
	;
	cmp	BL,0Ah		;改行か?
	je	.@Pnew		; -> 改行処理へ
	;
	cmp	BL,08h		;BSか?
	jne	.@Pbs

	;// BS(バックスペース処理)
	dec	BYTE [CS:_curx]
	JMP	.@Bstr

.@Pbs:
	shl	BX,4	;(文字コード)左へ <- 4ビットシフト[C1 E3 04]
	je	.@Qstr	;-> 表示 終了

	add	BX,-20h*16+charfont	;文字フォントデータの先頭計算。

	xor	AX,AX		;//
	mov	AL,[CS:_curx]	;// AX = カーソルX座標
	shl	AX,3		;それを8倍する。
	xor	CX,CX		;//
	;
	mov	CX,[CS:_cury]	;// DI = カーソルY座標
	;
	mov	DI,CX		;//
	shl	DI,2		;それを5倍する。
	add	DI,CX		;

	shl	DI,10		;[C1 E7 0A]
	add	DI,AX		; DI = Y*5125+X*8
	;
	mov	CH,16		;フォントデータ数
.@Lstr1:
	 mov	CL,8
	 mov	AL,[CS:BX]	;フォントデータ取り出し-> AL
	 inc	BX		; ポインタup
.@Lstr2:
	 add	AL,AL		;// 2倍する
	 SBB	AH,AH		;//??
	 and	AH,0Fh
	 mov	[es:DI],AH	;ビット書き込み。
	 inc	DI
	 dec	CL		;8回繰り返す。
	 jne	.@Lstr2		;
	;
	add	DI,320-8
	dec	CH
	jne	.@Lstr1
	;
	mov	AL,[CS:_curx]
	inc	AL

	mov	BYTE [CS:_curx],AL
	cmp	AL,40
	jne	.@Pstr1
	;
.@Pnew:
	mov	BYTE [CS:_curx],0
	;
	mov	AL,BYTE [CS:_cury]
	inc	AL
	mov	BYTE [CS:_cury],AL
	;
	cmp	AL,12
	jne	.@Pstr1
	;
	 CALL	scroll
.@Pstr1:
	JMP	.@Bstr
.@Qstr:
	pop	AX
	pop	BX
	pop	CX
	pop	SI
	pop	DI
	pop	ES
	RETN			;ret ??? 違いは??? コードは C3 で同じ。

;;putstr	endp

	ALIGNB	2, db 0		;これは有効 00 が1個入る。

;-------------------------------
;	データ エリア
;-------------------------------
_curx:	DB	0		;X側、カーソル座標
_cury:	DB	0		;Y側、カーソル座標


;-------------------------------
;● 画面表示をスクロールする。
scroll:		;	proc	near
;
	push	DS
	mov	AX,0A000h	;V-RAMの先頭アドレス
	mov	DS,AX		; -> DSセグメントへ
	;
	mov	SI,320*16	;画面の2行目の先頭?
	xor	DI,DI
.@Lscr:
	mov	AX,[ds:SI]	;2ドット分のデータを読み取り、
	add	SI,2		;
	mov	[ds:DI],AX	;  2行上にコピー。
	add	DI,2		;
	;
	cmp	SI,320*200	;画面の最後のドットまで、
	jb	.@Lscr		;  コピーを繰り返す。
	;
	xor	AX,AX		;ドット色データをゼロに。
.@Lscr2:	
	mov	[ds:DI],AX	;最後の1行分を、
	add	DI,2		;  クリアする。
	cmp	DI,320*200	;  (画面の最後のドットまで
	jb	.@Lscr2		;    繰り返す。)
	;
	pop	DS
	;
	dec	BYTE [CS:_cury]	;カーソルXの値を1減らす。
	RET
;
;;scroll	endp


;-------------------------------
;● FDのセクタ読み取り。
; in:	SI	...	FD読み取り位置(クラスタ番号?)
;	ES:BX	...	読み取りデータ格納先
;	CL	...	読み取りセクタ数
;
readSec:	;	proc	near

	mov	CH,3		;リトライ回数
.@Lrsec:
	push	ES
	push	SI
	push	BX
	push	DX
	push	CX
	push	AX
	;
	mov	AX,SI		;// SIのポインタを18で割り、
	mov	CL,18		;//   → CHに入れる。CLにはあまりを。
	DIV	CL		;// (AX ÷ CL → 答 AL あまりAH)
	mov	CH,AL		;//
	mov	CL,AH		;SIを18で割ったあまり+1 -> セクタ番号
	;
	mov	DH,AL
	shr	CH,1		;SIを18で割った答えをさらに÷2->トラック番号
	and	DH,01h		;SIを18で割った答えのビット0 ->ヘッド番号
	inc	CL
	;			;ES:BX= 読み取り先バッファアドレス。
	;			;DH=0,1 ヘッドNo.
	;			;CH=トラック番号,    CL=セクタ番号
	mov	AX,0201h	;AH=2 セクタ読み取り AL=セクタ数
	xor	DL,DL		;DL=ドライブNo. 0=A:
	int	13h		;(★ FDのセクタ読み取り)
	;			;  →AL=実際に読まれたセクタ数。
	;			;  →AH=FDの状態。
	pop	AX
	pop	CX
	pop	DX
	pop	BX
	pop	SI
	pop	ES
	jnc	.@Prsec		;NCなら読み取りエラー無し。
	;
	dec	CH		;3回リトライでもエラーなら
	je	.@Qrsec		; エラー終了。
	;
	push	ES		;↓以下、エラーリトライ
	push	SI
	push	BX
	push	DX
	push	CX
	push	AX
	;
	mov	AH,11h		;AH=2 ヘッドの位置合わせ
	xor	DL,DL		;DL=ドライブ番号 0=A:
	int	13h		;(★ ヘッドの位置合わせ)
	;
	pop	AX
	pop	CX
	pop	DX
	pop	BX
	pop	SI
	pop	ES
	JMP	.@Lrsec		;↑もう一回やり直し。
;
.@Prsec:	
	add	BX,512		;データ格納先を 512バイト 進める。
	inc	SI		;読み取りクラスタ番号を1つ進める。
	clc
	dec	CL		;読み取り回数(セクタ数)を1つ減らす。
	jne	.@Lrsec
.@Qrsec:
	RET
;;readSec	endp

;+----------------------------------------------------------+
;| 解説:   FDのファイルシステムについて。       |
;|                             |
;|ファイルシステム名称: FAT12            |
;|1セクタあたり、512バイト、1クラスタ=1セクタ        |
;|                             |
;| FDの先頭から1クラスタを使って、MBR(ブートプログラム) |
;| 次に  FAT領域       9クラスタ分     No. 1〜    |
;| さらにFAT2領域       9クラスタ分     No. 10〜   |
;| その次にディレクトリ領域 14クラスタ分     No. 33〜   |
;| これ以降がユーザが自由にファイルを格納できる領域      |
;|                             |
;|ディレクトリ領域:                       |
;| 1区画は32バイト、ファイル名8文字、拡張子名3文字、属性1バイト   |
;|                             |
;+----------------------------------------------------------+

;-------------------------------
;● ディレクトリ情報を取得。
;
; out:	(CS+2000h)	...	〜512バイト  BPB(BIOSパラメータ情報)
; 	(CS+1000h)	...	〜512バイトx14=1C00h ディレクトリ情報
;
loadDir:	;	proc	near
	push	ES
	mov	AX,CS		;//
	add	AX,1000h	;// CS+2000hを
	mov	ES,AX		;//  → ESにセット。
	
	mov	BYTE [es:0],00h	;先頭をゼロクリア
	
	mov	AX,CS		;//
	add	AX,2000h	;// CS+2000hを
	mov	ES,AX		;//  → ESにセット。
	;
	xor	BX,BX		;読み込み先をオフセット=0に。
	xor	SI,SI		;読み込みクラスタ番号を0
	mov	CL,1		; 1セクタだけ読む。
	CALL	readSec		;そこへ1セクタ分 FDから読み込み。
	jc	.@Err		;	→ 読み取りエラーなら終了。
	;
	mov	AL,[es:000Dh]	;+13バイト目が、
	mov	[_SIZ_CLU],AL	; 1クラスタのセクタ数? 1セクタ=1クラスタ

	mov	AX,[es:000Eh]	;FATの入っているクラスタ番号先頭 (=0001)
	mov	[_LBA_FAT],AX	;  ->LBA_FATへセット。

	mov	CX,[es:0016h]	;1つのFAT領域の大きさ。(=9)
	add	AX,CX		; これを加えると、
	mov	[_LBA_FAT2],AX	; -> FAT2 の先頭、LBA_FAT2へセット
	add	AX,CX		; さらに加えると、
	mov	[_LBA_DIR],AX	;ルート・ディレクトリ・エントリの先頭クラスタ番号
	;
	mov	CX,[es:0011h]	;ルート・ディレクトリ・エントリのサイズ
	mov	[_SIZ_DIR],CX	; クラスタ数で 00E0h=224個分。

	shl	CX,5		;CXを32倍 -> 1C00h
	add	CX,511		; + (512-1) 512はセクタサイズ -> 1DFFh
	shr	CX,9		;÷1024 -> 7
	;
	add	AX,CX
	mov	[_LBA_CLU2],AX	;ユーザー・データのエントリ 先頭クラスタ番号
	;
	mov	AX,CS		;//
	add	AX,1000h	;// CS+1000hを
	mov	ES,AX		;//  → ESにセット。
	;
	xor	BX,BX		;読み込みデータ格納先オフセット
	mov	SI,[_LBA_DIR]	;ルート・ディレクトリ・エントリの先頭クラスタ番号
	;			CLは??
	CALL	readSec		;ディレクトリの内容よ読み込む。
	
	mov	BX,[_SIZ_DIR]	;// 1ディレクトリは32バイト
	dec	BX		;//
	shl	BX,5		;//  BXを32倍
	;
	mov	BYTE [es:BX],00h	;そこをゼロクリア
.@Err:
	pop	ES
	RET
;
	ALIGNB	2, db 0

_LBA_FAT:	DW	1	;1つ目のFATの先頭クラスタ番号
_LBA_FAT2:	DW	10	;2つ目のFATの先頭クラスタ番号
_LBA_DIR:	DW	19	;ディレクトリ・エントリの先頭クラスタ番号
_LBA_CLU2:	DW	33	;ユーザーデータ・エントリの先頭クラスタ番号
_SIZ_DIR:	DW	00E0h	;ディレクトリの情報に使っている クラスタ数。
_SIZ_CLU:	DW	1	;1クラスタのセクタ数
;
;;loadDir	endp	

;-------------------------------
;● システムコール。
;解説:
; ユーザープログラムから int 80h で呼び出される
; システムコールの処理部分。AXに機能番号を入れて機能を指示。
; ただし、現時点では、
;  AX=0: セグメントの初期化
;  AX=1: 文字列の表示
;  AX=2: 画面のクリア
; しか、機能実装されていない。
_syscall:	;	proc
	push	DI
	push	SI
	push	BP
	push	BX
	push	DX
	push	CX
	push	AX
	;
	mov	BP,SP
	test	AX,AX
	jne	.@Psys1
	;
	;// AX=0 の時の処理。【初期化?】
	mov	AX,CS
	mov	SS,AX
	mov	SP,0FFFEh
	mov	DS,AX
	mov	ES,AX
	JMP	_command

.@Psys1:
	cmp	AX,1
	jne	.@Psys2
	;
	;//  AX=1 の時の処理。【文字列表示】
	CALL	putstr
	JMP	.@Psys3
	;
.@Psys2:
	cmp	AX,2
	jne	.@Psys3
	;
	;//  AX=2 の時の処理。【画面のクリア】
	CALL	cls
	JMP	.@Psys4
.@Psys3:
	or	BYTE [ss:BP+18],01h
	JMP	.@Qsys
.@Psys4:
	and	BYTE [ss:BP+18],0FEh
	;
.@Qsys:	
	pop	AX
	pop	CX
	pop	DX
	pop	BX
	pop	BP
	pop	SI
	pop	DI
	IRET
;
;;_syscall	endp


;-------------------------------
;● ここから下に 文字フォントデータをつなげる。
charfont:
	;
	;よって、データはこのファイルでは無し。
	;
;//	incbin "charfont.bin"	;←これで、直接リンクできる。

	end			;プログラム終了。