我依稀記得當初看到這一節標題的時候很是很是的興奮,由於能夠用C語言了。windows
首先是咱們要來製做真正的IPL了,回顧一下,IPL就是那512個啓動字節,讓他來引導真正的操做系統,由於512個字節太少了,不能作太多邏輯。安全
MOV AX,0x0820 MOV ES,AX MOV CH,0 ; 柱面0 MOV DH,0 ; 磁頭0 MOV CL,2 ; 扇區2 MOV AH,0x02 ; AH=0x02 : 讀盤 MOV AL,1 ; 1個扇區 MOV BX,0 MOV DL,0x00 ; A驅動器 INT 0x13 ; 調用磁盤BIOS JC error
這裏又調用了一箇中斷,上一個中斷是向顯示器上輸出一個字符,這個中斷的做用就是對磁盤進行操做的,若是把他看成C語言或者其餘高級語言來說會很方便,就是這是個對磁盤操做的函數,而後調用前,你給這些寄存器傳一些參數,而後會經過標誌位的方式返回讀取結果,即CF標誌位。函數
介紹一下軟盤,這玩意兒淘寶上還能買到,我最開始學的時候買過,實體店早已看不到了,一點幾MB的內存,我小倉老師的照片都放不了。。。要它何用。軟盤分正反,叫磁頭。柱面,能夠理解在這個軟盤上畫了更多的圓圈,而後再分紅扇形,也就有了,柱面和扇區。磁盤號是指那麼多個軟盤,你讀哪一個。
咱們的IPL就會放在C0-H0-S1(也就是柱面0,磁頭0,扇區1),本人不太理解,爲啥柱面從0開始而扇區不是。
這裏要介紹個新玩意兒了段寄存器,我記得我在學彙編時很經典的一句話,物理地址=段地址 x 10 + 偏移地址 (基於10進制,若是是16進制x16就行了)。若是指定用法就得把段寄存器與偏移地址寫在一起,若是不寫默認以DS做爲默認段寄存器,昨天就用到了[],暫時還沒講這個東西次。記得和C語言保持一個習慣,變量初始化,這裏的DS也記得初始化,否則會讀到其餘的內存地址去。
by the way Makefile裏面的變量特別像PHP裏的變量。oop
;多式幾回操作系統
MOV AX,0x0820 MOV ES,AX MOV CH,0 ; 柱面0 MOV DH,0 ; 磁頭0 MOV CL,2 ; 扇區2 MOV SI,0 ; 記錄失敗次數
retry:命令行
MOV AH,0x02 ; AH=0x02 : 讀盤 MOV AL,1 ; 1個扇區 MOV BX,0 MOV DL,0x00 ; A驅動器 INT 0x13 ; 調用磁盤BIOS JNC fin ; 若OK則跳轉至fin ADD SI,1 ; 往SI加1 CMP SI,5 ; 比較SI是否大於5 JAE error ; 若SI >= 5,則跳轉到error MOV AH,0x00 MOV DL,0x00 ; A驅動器 INT 0x13 ; 重置驅動器 JMP retry
JNC會去判斷CF標誌位的狀態如果0則會跳轉。
JAE大於等於則跳轉code
MOV AX,0x0820 MOV ES,AX MOV CH,0 ; 柱面0 MOV DH,0 ; 磁頭0 MOV CL,2 ; 扇區2
readloop:內存
MOV SI,0 ;
retry:開發
MOV AH,0x02 ; AH=0x02 : 讀盤 MOV AL,1 ; 1個扇區 MOV BX,0 MOV DL,0x00 ; A驅動器 INT 0x13 ; 調用磁盤BIOS JNC next ; 若OK則跳轉至next ADD SI,1 ; 往SI加1 CMP SI,5 ; 比較SI是否大於5 JAE error ; 若SI >= 5,則跳轉到error MOV AH,0x00 MOV DL,0x00 ; A驅動器 INT 0x13 ; 重置驅動器 JMP retry
next:編譯器
MOV AX,ES ; 把內存地址後移0x200(512字節) ADD AX,0x0020 MOV ES,AX ; ADD ES,0x020 由於沒有這個指令因此只能找中介 ADD CL,1 ; 往CL里加1 CMP CL,18 ; 比較CL與18 JBE readloop ; 若是CL <= 18 跳轉至readloop
JBE只要是拿來控制讀取到18扇區的,小於等於則跳轉。
咱們知道磁盤讀出來後的內容都放到了ES:BX了,然而咱們分別設置了ES與BX,因此程序也就裝載到相應位置啦。
接下來是讀取是個柱面,這裏就不貼代碼了。直接說說新指令把。
JB就是小於等於跳轉。還有EQU 這個很是建議寫一些常常要改的東西這樣寫,由於稍微作過項目就知道這種玩意兒不寫成這樣那是找罵呀。
如今磁盤上的180KB字節就存儲在ES:BX這個地方啦。沒什麼太多難度,就是須要每句去理解。
着手開發操做系統啦。。。
這裏做者給了一個很是簡單的操做系統。。
but...這是歷史的轉折點,這畢竟是在啓動區以外了,咱們要讀取IPL以外的代碼了,從harib00e(光盤目錄)看得出來多了一個文件haribote.nas,這個就是咱們的操做系統啦,由剛纔的main函數(IPL),調用到了這邊來,而後做者經過二進制軟件一頓分析,得出了以下結論 1.文件名會寫在0x002600之後的地方 2.文件的內容會寫在0x004200之後的地方 其實我在糾結一個問題,要是0x002600-0x004200之間都寫了文件名咋辦。不過他說的是0x002600之後,並不是之間,嗯,那我就放心了。知道這個文件的內存地址後,如今咱們就要來讀取這個文件啦。
從啓動區執行操做系統
若是咱們是把程序裝載在0的位置那麼直接使用0x004200就好了,但問題是操做系統有它應該放的位置,因此前面咱們放在了0x0820的位置,一開始做者說0x8000我小楞了一下,不是放在0x0820位置的嗎?(我仍是解釋一下,怕有些出血朋友不能理解到)首先,這是個段地址會進行偏移,偏移爲0x8200,而後200,一想是512個字節,因此這就是咱們的啓動區嘛,因此正確,就是0x8000。因此咱們的程序須要從0x8000+0x4200 = 0xc200地址讀取咱們的hairbote.nas文件。
這裏又新調用了一個「函數」 int 0x10,配合上參數這個的做用是把屏幕弄成VGA圖形模式,因此咱們要開始作圖形界面啦,而非一部份書是作命令行模式的(固然這並不表明我對那種書的差評,我直是以爲一上來作圖形界面,會讓初學者更又興趣)
立刻要進入32位模式啦
優勢固然是更多的內存空間可使用,與安全性。
; 有關BOOT_INFO
CYLS EQU 0x0ff0 ; 設定啓動項
LEDS EQU 0x0ff1
VMODE EQU 0x0ff2 ; 關於顏色數目的信息。顏色的位數
SCRNX EQU 0x0ff4 ; 分辨率的X
SCRNY EQU 0x0ff6 ; 分辨率的Y
VRAM EQU 0x0ff8 ; 圖像緩衝區的開始地址
ORG 0xc200 ; 將程序裝載到0xc200處 MOV AL,0x13 ; VGA顯卡,320*200*8位彩色 MOV AH,0x00 INT 0x10 MOV BYTE [VMODE],8 ; 記錄畫面模式 MOV WORD [SCRNX],320 MOV WORD [SCRNY],200 MOV DWORD [VRAM],0x000a0000
; 用BIOS去得鍵盤上各類LED指示燈的狀態
MOV AH,0x02 INT 0x16 ; keyboard BIOS MOV [LEDS],AL
這裏呢,也沒作啥實際的操做,就是把各類數據記錄下來了,而後經過int 0x16取得了鍵盤上各類指示燈的狀態
開始導入C語言
從一開始我就說要開始C語言了,結果到了今天快結束纔開始說導入C語言
雖然說導入吧,其實有不少原理性的東西,在這裏不會講,其實裏面就是後面的GDT等內容,我也是看到後面的GDT開始有些卡主了,因此這裏做者沒有講,而是直接來看bootpack.c吧。
void HariMain(void)
{
fin:
goto fin;
}
看到這種代碼,我又從新找回了自信,畢竟我不是那個時代過來的人,沒有每天寫過彙編,因此彙編和C,固然是C更親近些。我想這玩意兒C代碼也不用解釋太多。至因而如何調用到這裏來的,後面再細談。
關於對編譯器的解釋,也很簡單。解釋的那麼清楚,而後與windows,mac上如此成熟的集成開發環境作了對比,意思是相對於那種,咱們搞這麼複雜,可是步奏是可控的。
最後做者必定要讓計算機處於HALT那就來吧。
; naskfunc
; TAB=4
[FORMAT "WCOFF"] ; 製做目標文件的模式
[BITS 32] ; 製做32位模式用的機械語言
; 製做目標文件的信息
[FILE "naskfunc.nas"] ; 源文件名信息
GLOBAL _io_hlt ; 程序中包含的函數名
; 如下是實際的函數
[SECTION .text] ; 目標文件中寫了這些以後再些程序
_io_hlt: ; void io_hlt(void);
HLT RET
而後回來在C語言聲明一下,就能夠調用啦,不過至於今天許多的細節問題,後面會又深刻講解的。總的來講咱們能夠用C語言寫代碼啦。