自家製OSのロードについてもう少し-ブートローダーを書く

少し前に、 IA-32アーキテクチャをもう少しよく勉強することにしました。 そして、覚えておくべき最善のことは何ですか? もちろん、練習してください。 しかし、OSでプログラミングする場合、干渉なしにハードウェアへの最低レベルのアクセスを得ることはほとんどありません。 したがって、これらの目的のために、オペレーティングシステムの独自の類似性を記述します。 つまり、簡単に言えば、BIOSを読み込んだ直後にコードを実行します。

低レベルでプログラミングしたい人が遭遇する最初の問題は、コードをダウンロードする方法ですか?



エントリー



通常、BIOSには起動を試みるデバイスのリストがあり、順番に並べ替えられます。 このリストは通常​​、ドライブ、CDドライブ、ハードドライブで構成されます。 フロッピーディスクとCD-ROMからの起動はほぼ同じです。ディスクの起動領域の互換性のために、ディスクイメージが配置され、メモリにコピーされて仮想ドライブとして機能します。 そして以来 フロッピーディスクから起動するのが最も簡単で、これを使用します。

BIOSはすべてのデバイスを検出し、それ自体に必要なすべてを実行した後、ディスケットの最初のセクターをアドレス0000:7C00のメモリーにロードし、そこで制御を渡します。 ここで最初の問題が発生します-フロッピーディスク上のセクタのサイズは512バイトしかないため、このフレームワークに適合して残りのコードをダウンロードする必要があります。 それでもこれがあなたにとって多くのように思えるなら、私は互換性のために〜60人がサービス目的に費やされていると言います。 もちろん、それらを捨てることはできますが、システム上でディスケットが見えない可能性があり、そこにファイルをコピーすることは困難です。

簡単にするために、このデータを後で追加します。 上記のすべてのコードがFASM構文で提供されるように、すぐに予約してください。

それでは、最も簡単なことから始めましょう。コントロールを取得し、テキストを表示します。

  1. Use16 org 0x7C00 start : cli ; mov ax , cs ; mov ds , ax mov es , ax mov ss , ax mov sp , 0x7C00 ; .. , mov ax , 0xB800 mov gs , ax ; mov si , msg call k_puts hlt ; jmp $ ; k_puts : lodsb test al , al jz . end_str mov ah , 0x0E mov bl , 0x07 ; int 0x10 jmp k_puts . end_str ret msg db 'Hello world' , 0x0d , 0x0a , 0 times 510 - ( $ - $$ ) db 0 db 0x55 , 0xaa



  2. Use16 org 0x7C00 start : cli ; mov ax , cs ; mov ds , ax mov es , ax mov ss , ax mov sp , 0x7C00 ; .. , mov ax , 0xB800 mov gs , ax ; mov si , msg call k_puts hlt ; jmp $ ; k_puts : lodsb test al , al jz . end_str mov ah , 0x0E mov bl , 0x07 ; int 0x10 jmp k_puts . end_str ret msg db 'Hello world' , 0x0d , 0x0a , 0 times 510 - ( $ - $$ ) db 0 db 0x55 , 0xaa



  3. Use16 org 0x7C00 start : cli ; mov ax , cs ; mov ds , ax mov es , ax mov ss , ax mov sp , 0x7C00 ; .. , mov ax , 0xB800 mov gs , ax ; mov si , msg call k_puts hlt ; jmp $ ; k_puts : lodsb test al , al jz . end_str mov ah , 0x0E mov bl , 0x07 ; int 0x10 jmp k_puts . end_str ret msg db 'Hello world' , 0x0d , 0x0a , 0 times 510 - ( $ - $$ ) db 0 db 0x55 , 0xaa



  4. Use16 org 0x7C00 start : cli ; mov ax , cs ; mov ds , ax mov es , ax mov ss , ax mov sp , 0x7C00 ; .. , mov ax , 0xB800 mov gs , ax ; mov si , msg call k_puts hlt ; jmp $ ; k_puts : lodsb test al , al jz . end_str mov ah , 0x0E mov bl , 0x07 ; int 0x10 jmp k_puts . end_str ret msg db 'Hello world' , 0x0d , 0x0a , 0 times 510 - ( $ - $$ ) db 0 db 0x55 , 0xaa



  5. Use16 org 0x7C00 start : cli ; mov ax , cs ; mov ds , ax mov es , ax mov ss , ax mov sp , 0x7C00 ; .. , mov ax , 0xB800 mov gs , ax ; mov si , msg call k_puts hlt ; jmp $ ; k_puts : lodsb test al , al jz . end_str mov ah , 0x0E mov bl , 0x07 ; int 0x10 jmp k_puts . end_str ret msg db 'Hello world' , 0x0d , 0x0a , 0 times 510 - ( $ - $$ ) db 0 db 0x55 , 0xaa



  6. Use16 org 0x7C00 start : cli ; mov ax , cs ; mov ds , ax mov es , ax mov ss , ax mov sp , 0x7C00 ; .. , mov ax , 0xB800 mov gs , ax ; mov si , msg call k_puts hlt ; jmp $ ; k_puts : lodsb test al , al jz . end_str mov ah , 0x0E mov bl , 0x07 ; int 0x10 jmp k_puts . end_str ret msg db 'Hello world' , 0x0d , 0x0a , 0 times 510 - ( $ - $$ ) db 0 db 0x55 , 0xaa



  7. Use16 org 0x7C00 start : cli ; mov ax , cs ; mov ds , ax mov es , ax mov ss , ax mov sp , 0x7C00 ; .. , mov ax , 0xB800 mov gs , ax ; mov si , msg call k_puts hlt ; jmp $ ; k_puts : lodsb test al , al jz . end_str mov ah , 0x0E mov bl , 0x07 ; int 0x10 jmp k_puts . end_str ret msg db 'Hello world' , 0x0d , 0x0a , 0 times 510 - ( $ - $$ ) db 0 db 0x55 , 0xaa



  8. Use16 org 0x7C00 start : cli ; mov ax , cs ; mov ds , ax mov es , ax mov ss , ax mov sp , 0x7C00 ; .. , mov ax , 0xB800 mov gs , ax ; mov si , msg call k_puts hlt ; jmp $ ; k_puts : lodsb test al , al jz . end_str mov ah , 0x0E mov bl , 0x07 ; int 0x10 jmp k_puts . end_str ret msg db 'Hello world' , 0x0d , 0x0a , 0 times 510 - ( $ - $$ ) db 0 db 0x55 , 0xaa



  9. Use16 org 0x7C00 start : cli ; mov ax , cs ; mov ds , ax mov es , ax mov ss , ax mov sp , 0x7C00 ; .. , mov ax , 0xB800 mov gs , ax ; mov si , msg call k_puts hlt ; jmp $ ; k_puts : lodsb test al , al jz . end_str mov ah , 0x0E mov bl , 0x07 ; int 0x10 jmp k_puts . end_str ret msg db 'Hello world' , 0x0d , 0x0a , 0 times 510 - ( $ - $$ ) db 0 db 0x55 , 0xaa



  10. Use16 org 0x7C00 start : cli ; mov ax , cs ; mov ds , ax mov es , ax mov ss , ax mov sp , 0x7C00 ; .. , mov ax , 0xB800 mov gs , ax ; mov si , msg call k_puts hlt ; jmp $ ; k_puts : lodsb test al , al jz . end_str mov ah , 0x0E mov bl , 0x07 ; int 0x10 jmp k_puts . end_str ret msg db 'Hello world' , 0x0d , 0x0a , 0 times 510 - ( $ - $$ ) db 0 db 0x55 , 0xaa



  11. Use16 org 0x7C00 start : cli ; mov ax , cs ; mov ds , ax mov es , ax mov ss , ax mov sp , 0x7C00 ; .. , mov ax , 0xB800 mov gs , ax ; mov si , msg call k_puts hlt ; jmp $ ; k_puts : lodsb test al , al jz . end_str mov ah , 0x0E mov bl , 0x07 ; int 0x10 jmp k_puts . end_str ret msg db 'Hello world' , 0x0d , 0x0a , 0 times 510 - ( $ - $$ ) db 0 db 0x55 , 0xaa



  12. Use16 org 0x7C00 start : cli ; mov ax , cs ; mov ds , ax mov es , ax mov ss , ax mov sp , 0x7C00 ; .. , mov ax , 0xB800 mov gs , ax ; mov si , msg call k_puts hlt ; jmp $ ; k_puts : lodsb test al , al jz . end_str mov ah , 0x0E mov bl , 0x07 ; int 0x10 jmp k_puts . end_str ret msg db 'Hello world' , 0x0d , 0x0a , 0 times 510 - ( $ - $$ ) db 0 db 0x55 , 0xaa



  13. Use16 org 0x7C00 start : cli ; mov ax , cs ; mov ds , ax mov es , ax mov ss , ax mov sp , 0x7C00 ; .. , mov ax , 0xB800 mov gs , ax ; mov si , msg call k_puts hlt ; jmp $ ; k_puts : lodsb test al , al jz . end_str mov ah , 0x0E mov bl , 0x07 ; int 0x10 jmp k_puts . end_str ret msg db 'Hello world' , 0x0d , 0x0a , 0 times 510 - ( $ - $$ ) db 0 db 0x55 , 0xaa



  14. Use16 org 0x7C00 start : cli ; mov ax , cs ; mov ds , ax mov es , ax mov ss , ax mov sp , 0x7C00 ; .. , mov ax , 0xB800 mov gs , ax ; mov si , msg call k_puts hlt ; jmp $ ; k_puts : lodsb test al , al jz . end_str mov ah , 0x0E mov bl , 0x07 ; int 0x10 jmp k_puts . end_str ret msg db 'Hello world' , 0x0d , 0x0a , 0 times 510 - ( $ - $$ ) db 0 db 0x55 , 0xaa



  15. Use16 org 0x7C00 start : cli ; mov ax , cs ; mov ds , ax mov es , ax mov ss , ax mov sp , 0x7C00 ; .. , mov ax , 0xB800 mov gs , ax ; mov si , msg call k_puts hlt ; jmp $ ; k_puts : lodsb test al , al jz . end_str mov ah , 0x0E mov bl , 0x07 ; int 0x10 jmp k_puts . end_str ret msg db 'Hello world' , 0x0d , 0x0a , 0 times 510 - ( $ - $$ ) db 0 db 0x55 , 0xaa



  16. Use16 org 0x7C00 start : cli ; mov ax , cs ; mov ds , ax mov es , ax mov ss , ax mov sp , 0x7C00 ; .. , mov ax , 0xB800 mov gs , ax ; mov si , msg call k_puts hlt ; jmp $ ; k_puts : lodsb test al , al jz . end_str mov ah , 0x0E mov bl , 0x07 ; int 0x10 jmp k_puts . end_str ret msg db 'Hello world' , 0x0d , 0x0a , 0 times 510 - ( $ - $$ ) db 0 db 0x55 , 0xaa



  17. Use16 org 0x7C00 start : cli ; mov ax , cs ; mov ds , ax mov es , ax mov ss , ax mov sp , 0x7C00 ; .. , mov ax , 0xB800 mov gs , ax ; mov si , msg call k_puts hlt ; jmp $ ; k_puts : lodsb test al , al jz . end_str mov ah , 0x0E mov bl , 0x07 ; int 0x10 jmp k_puts . end_str ret msg db 'Hello world' , 0x0d , 0x0a , 0 times 510 - ( $ - $$ ) db 0 db 0x55 , 0xaa



  18. Use16 org 0x7C00 start : cli ; mov ax , cs ; mov ds , ax mov es , ax mov ss , ax mov sp , 0x7C00 ; .. , mov ax , 0xB800 mov gs , ax ; mov si , msg call k_puts hlt ; jmp $ ; k_puts : lodsb test al , al jz . end_str mov ah , 0x0E mov bl , 0x07 ; int 0x10 jmp k_puts . end_str ret msg db 'Hello world' , 0x0d , 0x0a , 0 times 510 - ( $ - $$ ) db 0 db 0x55 , 0xaa



  19. Use16 org 0x7C00 start : cli ; mov ax , cs ; mov ds , ax mov es , ax mov ss , ax mov sp , 0x7C00 ; .. , mov ax , 0xB800 mov gs , ax ; mov si , msg call k_puts hlt ; jmp $ ; k_puts : lodsb test al , al jz . end_str mov ah , 0x0E mov bl , 0x07 ; int 0x10 jmp k_puts . end_str ret msg db 'Hello world' , 0x0d , 0x0a , 0 times 510 - ( $ - $$ ) db 0 db 0x55 , 0xaa



  20. Use16 org 0x7C00 start : cli ; mov ax , cs ; mov ds , ax mov es , ax mov ss , ax mov sp , 0x7C00 ; .. , mov ax , 0xB800 mov gs , ax ; mov si , msg call k_puts hlt ; jmp $ ; k_puts : lodsb test al , al jz . end_str mov ah , 0x0E mov bl , 0x07 ; int 0x10 jmp k_puts . end_str ret msg db 'Hello world' , 0x0d , 0x0a , 0 times 510 - ( $ - $$ ) db 0 db 0x55 , 0xaa



  21. Use16 org 0x7C00 start : cli ; mov ax , cs ; mov ds , ax mov es , ax mov ss , ax mov sp , 0x7C00 ; .. , mov ax , 0xB800 mov gs , ax ; mov si , msg call k_puts hlt ; jmp $ ; k_puts : lodsb test al , al jz . end_str mov ah , 0x0E mov bl , 0x07 ; int 0x10 jmp k_puts . end_str ret msg db 'Hello world' , 0x0d , 0x0a , 0 times 510 - ( $ - $$ ) db 0 db 0x55 , 0xaa



  22. Use16 org 0x7C00 start : cli ; mov ax , cs ; mov ds , ax mov es , ax mov ss , ax mov sp , 0x7C00 ; .. , mov ax , 0xB800 mov gs , ax ; mov si , msg call k_puts hlt ; jmp $ ; k_puts : lodsb test al , al jz . end_str mov ah , 0x0E mov bl , 0x07 ; int 0x10 jmp k_puts . end_str ret msg db 'Hello world' , 0x0d , 0x0a , 0 times 510 - ( $ - $$ ) db 0 db 0x55 , 0xaa



  23. Use16 org 0x7C00 start : cli ; mov ax , cs ; mov ds , ax mov es , ax mov ss , ax mov sp , 0x7C00 ; .. , mov ax , 0xB800 mov gs , ax ; mov si , msg call k_puts hlt ; jmp $ ; k_puts : lodsb test al , al jz . end_str mov ah , 0x0E mov bl , 0x07 ; int 0x10 jmp k_puts . end_str ret msg db 'Hello world' , 0x0d , 0x0a , 0 times 510 - ( $ - $$ ) db 0 db 0x55 , 0xaa



  24. Use16 org 0x7C00 start : cli ; mov ax , cs ; mov ds , ax mov es , ax mov ss , ax mov sp , 0x7C00 ; .. , mov ax , 0xB800 mov gs , ax ; mov si , msg call k_puts hlt ; jmp $ ; k_puts : lodsb test al , al jz . end_str mov ah , 0x0E mov bl , 0x07 ; int 0x10 jmp k_puts . end_str ret msg db 'Hello world' , 0x0d , 0x0a , 0 times 510 - ( $ - $$ ) db 0 db 0x55 , 0xaa



  25. Use16 org 0x7C00 start : cli ; mov ax , cs ; mov ds , ax mov es , ax mov ss , ax mov sp , 0x7C00 ; .. , mov ax , 0xB800 mov gs , ax ; mov si , msg call k_puts hlt ; jmp $ ; k_puts : lodsb test al , al jz . end_str mov ah , 0x0E mov bl , 0x07 ; int 0x10 jmp k_puts . end_str ret msg db 'Hello world' , 0x0d , 0x0a , 0 times 510 - ( $ - $$ ) db 0 db 0x55 , 0xaa



  26. Use16 org 0x7C00 start : cli ; mov ax , cs ; mov ds , ax mov es , ax mov ss , ax mov sp , 0x7C00 ; .. , mov ax , 0xB800 mov gs , ax ; mov si , msg call k_puts hlt ; jmp $ ; k_puts : lodsb test al , al jz . end_str mov ah , 0x0E mov bl , 0x07 ; int 0x10 jmp k_puts . end_str ret msg db 'Hello world' , 0x0d , 0x0a , 0 times 510 - ( $ - $$ ) db 0 db 0x55 , 0xaa



  27. Use16 org 0x7C00 start : cli ; mov ax , cs ; mov ds , ax mov es , ax mov ss , ax mov sp , 0x7C00 ; .. , mov ax , 0xB800 mov gs , ax ; mov si , msg call k_puts hlt ; jmp $ ; k_puts : lodsb test al , al jz . end_str mov ah , 0x0E mov bl , 0x07 ; int 0x10 jmp k_puts . end_str ret msg db 'Hello world' , 0x0d , 0x0a , 0 times 510 - ( $ - $$ ) db 0 db 0x55 , 0xaa



  28. Use16 org 0x7C00 start : cli ; mov ax , cs ; mov ds , ax mov es , ax mov ss , ax mov sp , 0x7C00 ; .. , mov ax , 0xB800 mov gs , ax ; mov si , msg call k_puts hlt ; jmp $ ; k_puts : lodsb test al , al jz . end_str mov ah , 0x0E mov bl , 0x07 ; int 0x10 jmp k_puts . end_str ret msg db 'Hello world' , 0x0d , 0x0a , 0 times 510 - ( $ - $$ ) db 0 db 0x55 , 0xaa







他の数百の例のようにこれで終わると思うなら、私はあなたを失望させるか、多分あなたを喜ばせるでしょう-私たちのブートローダーはディスク上のファイルを探してそれをロードします。

まず、FAT12のフロッピーディスクのレイアウトについて説明します。

最初のセクターはサービスデータ用に予約されています-BIOSパラメーターブロック(BPB)とブートコード。



BIOSパラメータブロック



この場合のBPBは次のようになります。

 jmp start; 私たちのコードにジャンプ
	 db 0
	 BS_OEMName db 'MicLib'; 任意のテキスト
	 BPB_BytsPerSec dw 0x200; セクターのバイト
	 BPB_SecPerClus db 1; クラスター内のセクター
	 BPB_RsvdSecCnt dw 1; 予約済みセクターの数
	 BPB_NumFATs db 2;  FATテーブルの数
	 BPB_RootEntCnt dw 0x00E0; ルートツリーのエントリ数
	 BPB_TotSec16 dw 0x0B40
	 BPB_Media db 0xF0
	 BPB_FATSz16 dw 9; セクターのFATサイズ
	 BPB_SecPerTrk dw 0x12; トラック上のセクター
	 BPB_NumHeads dw 2; 読み取りヘッドの数
	 BPB_HiddSec dd 0
	 BPB_TotSec32 dd 0




フロッピーディスクとファイルをさらに処理するために、いくつかの補助手順を作成します。

それらの最初は、絶対アドレスで1つのセクターを読み取ることです。 セクターは一連のパラメーターヘッド、クラスター、セクターではなく、1つの序数で設定されます。



  1. ;
  2. ; 絶対数によるディスクセクターの読み取り手順
  3. ;
  4. ; ログイン:
  5. ; dx-絶対セクター番号
  6. ; si-バッファアドレス
  7. ;
  8. k_read_sector
  9. ; S = N mod 18 + 1
  10. ; T = N / 18
  11. ; H = T mod 2
  12. ; C = T / 2
  13. プシャ
  14. mov ax dx
  15. mov cx [ BPB_SecPerTrk ]
  16. mov bx si
  17. xor dx dx ; ここから始めて、上記の式に従って再計算を行います
  18. div cx
  19. mov ch al
  20. shr ch 1
  21. mov cl dl
  22. inc cx
  23. mov dh al
  24. および dh 1
  25. mov axe 0x0201
  26. xor dl dl
  27. int 0x13
  28. jnc @f ; フラグCが設定されている場合、エラーが発生しています
  29. mov si msgErrorRead
  30. k_putsを呼び出します お知らせください
  31. @@
  32. ポパ
  33. ret




FASMに慣れていない人のために、ジャンプのタグについて説明します。

@@は普遍的なラベルであり、コード内でいつでも使用できます。

@b-コードの最初のマーク@@にジャンプ(戻る);

@f-コードのさらに最初のマーク@@にジャンプします(前方)。





次の手順は、これに対するアドオンであり、一度に複数のセクターを連続して読み取ります。 不満を言うことはできますが、チェックはどこにありますか? スペースを節約するために、セクター番号の正確性をチェックしません。



  1. ;
  2. ; 順次セクター読み取り手順
  3. ;
  4. ; ログイン:
  5. ; dx-初期セクター
  6. ; cx-読み取るセクタの行数
  7. ; si-読み取るメモリアドレス
  8. ;
  9. k_read_sectors
  10. プッシュ dx
  11. cxを プッシュ
  12. @@
  13. k_read_sectorを呼び出す
  14. Inc dx
  15. siを 追加 [ BPB_BytsPerSec ]
  16. dec cx
  17. jnz @b ; まだ読んでいない0
  18. ポップ cx
  19. ポップ DX
  20. ret




ご覧のとおり、まだ複雑なものはありませんが、機能は追加されています。

次に、ファイルを読むために必要なものを説明します。 まず、メモリ内のFATテーブル全体とルートディレクトリを検討します。



FATテーブルとルートディレクトリ



FAT12テーブル全体は、12ビット(!)のレコードで構成され、それらは一緒にチェーンされています。 数字は、セクターの絶対アドレスを示します。 数値が0xFFFになるまで読み取ります。これがチェーンの終わりです。

つまり ファイルが513バイトを占有する場合、2つのセクターが割り当てられますが、2番目のセクターは1バイトのみで占有されます。

さて、メインディレクトリのテーブルについては-ファイルに関するすべてのデータを含む32バイトのレコードで構成されています。

そのフォーマットは次のとおりです。



 +0 11「IIIIIIIIRRR」形式のファイル名
		長さが8文字のファイル名は、短い場合はスペースで埋められます。 区切り点はありません。
		 3バイト拡張
 + 0Bh 1ファイル属性: 
			 01h-読み取り専用 
			 02h-非表示 
			 04h-システム 
			 08h-ボリュームラベル 
			 10h-ディレクトリ 
			 20h-アーカイブ 
 + 0Ch 10予約済み 
 + 16時間2ファイル時間形式での作成または変更時間 
 + 18h 2ファイル時間形式の作成日または変更日 
 + 1Ah 2 FATの最初のチェーンエントリの番号
 + 1Ch 4サイズ


1つの機能-ファイルを削除すると、レコード自体は削除されませんが、名前の最初のバイトのみが文字0xE5に置き換えられます。

長さがゼロのファイルを-にすることはできません したがって、フォルダが指定され、オフセット+ 1Ahで、ディレクトリにネストされたファイルの最初のレコードの番号が記録されます。

最初の2つは。 および..は、それぞれ現在のディレクトリの最初のレコードと親を指します。



さらに2つの非常に小さなプロシージャを作成します。これは、メモリ内の両方のテーブルを読み取ります。



  1. ;
  2. ; プロシージャは、FATテーブルをメモリに読み込みます
  3. ;
  4. k_read_fat
  5. mov dx 1 ; ブートセクタのすぐ後ろに配置
  6. mov cx [ BPB_FATSz16 ] ; 9セクター
  7. mov si FAT
  8. k_read_sectorsを呼び出す
  9. ret
  10. ;
  11. ; プロシージャは、ルートディレクトリをメモリに読み取ります。
  12. ;
  13. k_read_root_dir
  14. mov dx 19 ; 1 + 9 * 2
  15. mov cx 15
  16. mov si ROOT
  17. k_read_sectorsを呼び出す
  18. ret




ファイルを読む



さて、ファイルのメモリを読み込むために、私たちが書いたすべてを収集すること、つまり ルートディレクトリでそのレコードを見つけ、FATのセクター番号を使用してメモリに読み込みます。

実際、この操作には最も時間とコードがかかりました。



  1. ;
  2. ; この手順では、フロッピーディスクからメモリにファイルを読み取ります。
  3. ;
  4. ; ログイン:
  5. ; di-バッファアドレス
  6. ; si-NNNNNNNNEEE形式の厳密なファイル名
  7. ; 出力:
  8. ; ax-ファイルが見つからない場合は0、見つかった場合は1-
  9. ;
  10. k_read_file
  11. プッシュ ディ
  12. mov di ROOT
  13. mov cx 0xE0 ; BPB_RootEntCnt
  14. next_item
  15. mov al バイト [ di ]
  16. cmp al 0xE5 ;リモートファイルラベル
  17. je space_item
  18. cmp al 0 ;空白のエントリ
  19. je space_item
  20. プッシュ ディ
  21. プッシュ si
  22. cxを プッシュ
  23. mov cx 11 ; 8 + 3
  24. repe cmpsb ;ファイル名と検索を比較します
  25. cmp cx 0
  26. ポップ cx
  27. ポップシ
  28. ポップディ
  29. je read_file ;ブレーク
  30. space_item
  31. diを 追加 32 、レコード長
  32. ループ next_item
  33. xor ax ax
  34. ; jmp .end_of_file
  35. ret
  36. read_file
  37. ポップシ
  38. mov bp word [ di + 0x1A ] ; FAT開始セル番号
  39. mov bx word [ di + 0x1C ] ;ファイルサイズ
  40. read_next_claster
  41. プシャ
  42. mov dx bp
  43. サブ DX 3
  44. dx 0x22を 追加
  45. k_read_sectorを呼び出す
  46. ポパ
  47. cmp di 0xFFF
  48. je end_of_file
  49. mov di bp
  50. mov axe bp ; パリティのために保存
  51. mov bx bp ; 0xFFFがある場合に保存
  52. imul di </ f



All Articles