2007年10月8日 星期一

OrzMicrokernel 陪我度過颱風天的阿宅生活

Standard
最近幾次少數能以『強烈的颱風』身份影響並登陸台灣的,大概就屬這次的颱風了。還沒登陸,風就已經重擊了家裡的窗戶,呼呼砰砰聲搞得我醒著做事覺得煩、睡也睡不好。前兩天晚上去逛敦南誠品,在去的路上,風狂野的在短短一個街口,就把我的雨傘給吹成奇形怪狀﹝比翻過來還可怕﹞,後來回家時只好淋著雨一身濕答答的走回停車處。在被風玩弄之後,我就決定這兩天不出門了,弄得自己閒得發荒,一直在家當阿宅 Orz。

我突然想起前陣子 Jserv 寫的 OrzMicrokernel,一直沒能好好的找個時間去讀它,所以,藉著這次颱風過境,就好好品嘗一下了﹝笑﹞。一切果然如同大家所說, OrzMicrokernel 真的是簡潔有力,是一個作業系統設計的優良範例,它的設計非常直觀易懂;可是我也有聽到一群朋友,看得要死還是看不大懂 OrzMicrokernel 。搞半天,原來他們對組合語言並不是說非常熟悉,還有對磁碟 LBA、CHS、FAT12 等等這種格式定義很陌生!不過也難怪,大多人平時寫程式都太高階了,早就忘了電腦是怎麼動起來的。

尋思如果很多想了解的人,都卡在對組合語言的一點不熟悉和資料結構定義這種問題上,導致無法踏入 OrzMicrokernel 的話,那真的是太可惜了。所以,無聊到極點的我,就決定開始幫 OrzMicrokernel 逐行中文註解,希望從組合語言指令用法開始加註說明,還有說明重要的資料結構﹝註解寫起來比程式碼還多行,驚!﹞。為了說明的完全清晰正確,我還重新查資料驗證自己的觀念,生怕有一點遺漏。

以下是 boot.asm 讀取磁區的註解片段:

; DX:AX = LBA 磁區位置, ES:BX = 緩衝區位址
ReadSector:
; 磁區 CHS 表示法
; 磁碟和磁片的記錄方式『不是』一整面的磁區用完再換面儲存,而是以空心圓柱狀的方式。
; 因為磁片只有簡單兩面,以磁片為例:
; 正確的磁片資料記錄順序為:第零面第零軌、第一面第零軌、第零面第一軌、第一面第一軌...
; 每面的同一軌都用滿後才換下一個磁軌紀錄資料,形狀如同空心圓柱,故稱磁柱(cylinder)。
; 因此以磁片來說,第 0 面第 0 軌和第 1 面第 0 軌就是第 0 磁柱

; 磁區 LBA 表示法
; LBA 編號法是不考慮磁區的實體 CHS 上,純粹將所有磁區統一由 0, 1, 2...編號到最後一個磁區

; 以 LBA 表示法換算成 CHS (磁柱、磁頭、磁區) 的表示法
; 計算 CHS 的磁區編號
div WORD [sectPerTrack] ; LBA 磁區位置除以每磁軌的磁區數 = 磁區在第幾磁軌 = AX
inc dl ; 上一行除法運算的餘數(DL)加一 = 磁區編號
mov cl, dl ; 設 CL 為磁區編號

; 計算 CHS 磁頭編號
xor dx,dx ; 清除歸零 DX
div WORD [heads] ; 磁軌數量(AX)除以磁頭數﹝面數﹞
mov dh,dl ; 設 DH = 磁頭編號(餘數)

mov ch,al ; 設 CH = 磁柱
mov dl,[curDrive] ; DL = 磁碟裝置

mov ax,$0201 ; AH = 02H 讀取指定的磁碟資料、讀取的磁區數目 AL = 1
int $13 ; 磁碟的 BIOS 服務中斷,ES:BX 會被設為存放資料的記憶體指標
; 如果錯誤會設旗標 CF=1
jc PrintError ; 如果 CF=1 呼叫 PrintError 函式顯示錯誤
ret


後記

以上只是其中一小段落,其餘得我大概還要花很大工夫才能完成,因為每一句註解我都重複修改了很多次以求完美,所以很費工時。或許有很多人覺得我的註解非常囉嗦甚至是脫褲子放屁,但為了考慮到各種程度的人都看得懂,可能沒辦法不這樣做了。另外,如果以上註解有誤,還請大家不吝賜教。謝謝。