2007年10月9日 星期二

OrzMicrokernel boot.asm 磁碟內容參數的詳細註解

Standard
這是 OrzMicrokernel 裡 boot.asm 磁碟內容參數的部分,這部份比較直觀且不涉及硬體裝置的操作和定義,只要了解磁碟的資料配置結構,很容易就能了解其中的運作。

程式碼包括詳細註解:
;-----------------------------------------------
; 計算各項磁碟內容參數
;
; 計算磁區位置:
; 1. FAT表磁區
; 2. 根目錄磁區
; 3. 資料磁區
;
; 計算 FAT 檔案系統資訊:
; 1. FBD 所佔磁區數量
;-----------------------------------------------
;
; 磁碟資料結構:[開機記錄磁區][隱藏磁區][FAT表磁區][根目錄磁區][資料磁區]
; [FAT表磁區] 是由許多 FAT 表所構成
; [根目錄磁區] 是由許多 FBD 所構成
; FBD(檔案描述區塊):大小為 32Bytes
; 每個檔案都有自己的 FBD,記錄檔案名稱、建檔日期、檔案大小等資料

; 計算 FAT 的開始位置
; 方法:跳過隱藏磁區和開機磁區
; hiddenSectors = [高位元 2Bytes][低位元 2Bytes]
mov si,[hiddenSectors] ; 低位元給 SI
mov di,[hiddenSectors+2] ; 高位元給 DI
add si,[resSectors] ; 跳過隱藏磁區加開機記錄所佔用的磁區數
adc di,0 ; DI:SI = 第一個 FAT 表的開始位置
mov [fatStart],si ; 用 fatStart 保存 FAT 的開始位置
mov [fatStart+2],di

; 計算根目錄磁區的開始位置
; 方法:跳過 FAT 表磁區
; FAT 表的總數 x 每個表的磁區數 = 所有 FAT 表的磁區總數
mov al,[fatCopies] ; AL = FAT 表總數
xor ah,ah ; AX 暫存器中我們只用到其中的 AL,故要將 AH 歸零
mul WORD [sectPerFat] ; AL 乘以每個表的磁區數:DX:AX = 所有 FAT 表所
; 佔的磁區總數

add si,ax ; 跳過 FAT 表的磁區總數
adc di,dx ; DI:SI = 根目錄磁區的開始位置
mov [rootStart],si ; 用 rootStart 保存根目錄磁區的開始位置
mov [rootStart+2],di


; 計算全部 FBD 所佔磁區數
; 方法:根目錄最大檔案數 x 單一FBD大小(32Bytes) = 根目錄全部 FBD 所佔空間
mov ax,[rootEntCnt] ; 取得根目錄的最大檔案數
mov cl,5 ; TODO: reminding yet?
shl ax,5 ; 將 AX 向左平移 5 bit(最大檔案數乘以32) = 全部
; FBD 所佔大小

xor dx,dx ; 清除 DX,因為下一行 DIV 指令會用到 DX:AX
div WORD [bytesPerSector] ; 全部 FBD 所佔大小除以磁區大小 = 根目錄全部 FBD
; 所佔磁區數

mov [secPerRoot],ax ; 用 rootStart 保存根目錄全部 FBD 所佔磁區數

; 計算資料磁區的開始位置
add si,ax ; 跳過根目錄磁區(即跳過FBD 所佔磁區數)
adc di,0 ; DI:SI = 第一個資料磁區位置
mov [dataStart],si ; 用 dataStart 保存第一個資料磁區的位置
mov [dataStart+2],di



後記

這一段程式,唯一比較令我有些疑問的是 mov cl,5 這行,shl 有時會需要用到 cl 來設定平移的 bit 數這我能理解,可是在它下一行的 shl 是直接指定數值 5 當平移量,並非以 shl ax,cl 來做平移操作,那麼,設定 cl=5 是有必要的嗎?還希望有知道的人能給我一些回答。