30天自制操做系統-3

我依稀記得當初看到這一節標題的時候很是很是的興奮,由於能夠用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語言寫代碼啦。

相關文章
相關標籤/搜索