楠木軒

操作系統學習 讓啓動鏡像支持Fat12文件格式

由 度方針 發佈於 科技

一、Fat12 文件格式1. 格式簡要説明
  • Fat12是DOS支持的軟盤格式。
  • FAT全稱是文件分配表(File Allocation Table),用來記錄存放文件名、起始扇區等文件信息。
  • 除了文件分配表,還有目錄表(File Directory Table)。
  • 軟盤有兩個磁頭,每個磁頭80個柱面(磁道),每個柱面有18個扇區,每個扇區512個字節空間

軟盤結構:

2. 引導扇區

簡寫格式

  • 面:C
  • 磁道:H
  • 扇區:S(每道18個扇區)

C0-H0-S1用來存放引導區,如果最後兩個字節是0x55,0xaa(DW 0xAA55),BIOS就把這512字節讀出來執行。

3. FAT
  • C0-H0-S2~C0-H0-S10(9個扇區) 存放 FAT表
  • C0-H0-S11~C1-H0-S1(9個扇區) 存放備用FAT表
  • C1-H0-S2~ C1-H0-S15(14個扇區)用於存放FDT(根目錄)
4. FAT結構
  • FAT12的每個文件分配表項佔12bit, 每個表項代表一個扇區。
  • 磁盤裏所有扇區被線性索引(LBA)
  • FAT12每個表項的值指出文件存放的下一個扇區號
5. 根目錄
  • 根目錄緊跟着FAT表,從19分區開始。
  • 根目錄由若干個目錄條目組成,最多有BPB_RootEntCnt個。
  • 根目錄中每個條目佔32字節:

名稱開始字節長度內容DIR_Name00xB文件名8字節,擴展名3字節DIR_Attr0xB1文件屬性保留位0xC10保留DIR_WrtTime0x162最後一次寫入的時間DIR_WrtDate0x182最後一次寫入的日期DIR_FstClus0x1A2此文件在數據區和FAT表中的開始簇號DIR_FileSize0x1C4文件大小

6. 數據區二、Fat12格式的引導區代碼:
;%define _BOOT_DEBUG_   ; 做Boot Sector時把這行註釋掉        ; 啓用這行就用nasm Boot.asm -o Boot.com生成.com文件用於調試%ifdef _BOOT_DEBUG_   org  0100h%else   org 07c00h%endifCYLS EQU 10; 把軟盤按Fat12格式填充   JMP init                ; 跳轉指令   DB      0x90            ; 空 DB,DD用來寫單字節   DB      "NotOneOS"      ; 廠商名,8字節,DB用來寫雙字節   DW      512             ; 每個扇區大小512字節,DW用來寫4字節   DB      1               ; 每個簇的扇區數   DW      1               ; Boot佔的扇區   DB      2               ; 有2個FAT表   DW      224             ; 根目錄大小224   DW      2880            ; 磁盤扇區總數 2880   DB      0xf0            ; 介質描述符,磁盤種類必須為0xf0   DW      9               ; 每個FAT扇區數   DW      18              ; 每個磁道18個扇區   DW      2               ; 2個磁頭   DD      0               ; 隱藏扇區數   DD      2880            ; 同上,磁盤大小   DB      0, 0, 0x29      ; 0x29 擴展引用標記   DD      0xffffffff      ; 無意義,固定這麼寫   DB      "NotOneOS   "   ; 磁盤名(卷標),11字節   DB      "FAT12   "      ; 磁盤格式名,8字節   RESB    18              ; 空18個字節,填充0x00init:   MOV AX,0   MOV SS,AX   MOV SP,0x7c00        ; 堆棧空間,從0x7c00向前   MOV DS,AX   MOV AX,0x0820        ; 把磁盤數據加載到內存0x0820處。0x8000~0x81ff的512字節給啓動區用的,所以從0x0820開始   MOV ES,AX            ; 初始化磁盤接口   MOV CH,0             ; 柱面 0   MOV DH,0             ; 磁頭 0   MOV CL,2             ; 扇區 2readloop:   MOV SI,0             ; 記錄失敗次數retry:   MOV    AH,0x02       ; 0x02 讀磁盤   MOV    AL,1          ; 讀1個扇區   MOV    BX,0   MOV    DL,0x00       ; A驅動器   INT    0x13          ; BIOS 讀磁盤功能   JNC    next          ; 成功跳轉   ADD    SI,1          ; 失敗加一次   CMP    SI,5          ; 到5次就跳到error   JAE    error   MOV    AH,0x00       ; 復位磁盤功能   MOV    DL,0x00   INT    0x13          ; 重置磁盤驅動器   JMP    retry         ; 重試   next:    MOV     AX,ES       ; 內存地址向後移動0x0020    ADD     AX,0x0020       MOV     ES,AX       ; 通過AX給ES加0x0020    ADD     CL,1        ; 扇區+1    CMP     CL,18       ; 有沒有到18個扇區    JBE     readloop    ; CL<=18,就跳到 readloop        MOV     CL,1    ADD     DH,1    CMP     DH,2    JB     readloop    ; 如果 DH < 2 ,則跳到readloop        MOV     DH,0    ADD     CH,1    CMP     CH,CYLS    JB     readloop    ; 如果CH
三、 文件讀寫

使用BIOS中斷 int 13h,參數:

知道扇區號的時候,要計算int 13h的參數:

設扇區號/每磁道扇區數(18) = 商 Q,餘數R ,則:

  • 柱面號= Q >> 1 (相當於 Q/2 無餘數)
  • 磁頭號=Q & 1
  • 起始扇區號=R+1
四、讀磁盤鏡像並寫入文件,查看文件格式

下面使用VirtualBox讀入磁盤鏡像,並寫入一個文件。(新建虛擬機並加虛擬磁盤的方法前面章節有提到。)

使用VsCode打開磁盤鏡像,可以看到存儲區域已經有了變化:

這裏使用的是笨方法保存文件,也可以使用edimg.exe程序來做。

  • 文件名保存到 0x002600處
  • 文件的內容存在 0x40200處

後面章節來看如何讓程序加載NotOneOS.sys裏的代碼。

本章代碼與編譯運行方法已放到gitee:gitee.com/xundh/learn-os