1. 程式人生 > >30天自制作業系統---第3天

30天自制作業系統---第3天

一,製作真正的IPL(啟動程式裝載器) 今天的目的是將昨天的啟動程式裝載器來裝載程式。         ①:磁碟最初的512位元組是啟動區。為了裝載下一個512位元組內容的程式,對之前的程式進行修改,得到了今天的harib00a程式;         ②:緩衝區地址 是記憶體地址。將磁盤裡面的程式載入到記憶體中    
; haribote-ipl
; TAB=4
 
 
        ORG        0x7c00            ; このプログラムがどこに読み込まれるのか
 
 
; 以下は標準的なFAT12フォーマットフロッピーディスクのための記述
 
 
        JMP        entry
        DB        0x90
        DB        "HARIBOTE"        ; ブートセクタの名前を自由に書いてよい(8バイト)
        DW        512                ; 1セクタの大きさ(512にしなければいけない)
        DB        1                ; クラスタの大きさ(1セクタにしなければいけない)
        DW        1                ; FATがどこから始まるか(普通は1セクタ目からにする)
        DB        2                ; FATの個數(2にしなければいけない)
        DW        224                ; ルートディレクトリ領域の大きさ(普通は224エントリにする)
        DW        2880            ; このドライブの大きさ(2880セクタにしなければいけない)
        DB        0xf0            ; メディアのタイプ(0xf0にしなければいけない)
        DW        9                ; FAT領域の長さ(9セクタにしなければいけない)
        DW        18                ; 1トラックにいくつのセクタがあるか(18にしなければいけない)
        DW        2                ; ヘッドの數(2にしなければいけない)
        DD        0                ; パーティションを使ってないのでここは必ず0
        DD        2880            ; このドライブ大きさをもう一度書く
        DB        0,0,0x29        ; よくわからないけどこの値にしておくといいらしい
        DD        0xffffffff        ; たぶんボリュームシリアル番號
        DB        "HARIBOTEOS "    ; ディスクの名前(11バイト)
        DB        "FAT12   "        ; フォーマットの名前(8バイト)
        RESB    18                ; とりあえず18バイトあけておく
 
 
; プログラム本體
 
 
entry:
        MOV        AX,0            ; レジスタ初期化
        MOV        SS,AX
        MOV        SP,0x7c00
        MOV        DS,AX
 
 
; ディスクを読む
; ===============================這次新增的內容START=================================
;這裡就開始了讀寫磁碟的方式,下面就會更具 驅動器  柱面 扇區 磁頭 確定最終讀取的位置
 
        MOV        AX,0x0820
        MOV        ES,AX
        MOV        CH,0            ; 柱面0  CH表示的是柱面號
        MOV        DH,0            ; 磁頭0  磁頭號
        MOV        CL,2            ; 扇區2  CL扇區號
 
 
        MOV        AH,0x02         ;AH=0x02 : 讀盤(0x03是寫磁碟)
        MOV        AL,1            ;1個扇區  AL處理物件的扇區數;(只能同時處理連續的扇區)
        MOV        BX,0
        MOV        DL,0x00         ;A驅動器
        INT        0x13            ;呼叫磁碟BIOS 註釋:呼叫BIOS磁碟0x13號函式。
        JC        error            ;註釋:這次的新指令JC:大意是:如果進位標誌是1的話,就跳轉。   
        ;這裡特別解釋一下:通過上面一連串的配置,再執行INT 0x13 我們就會去讀磁碟內容(為什麼是讀,因為我們AH那個地方配置的0x02),如果讀磁碟成功了,那麼我們就返回0,如果錯誤就會返回1。
        ;我們這裡可以這樣理解,從 MOV        AX,0x0820 這裡到 MOV        DL,0x00 都是我們傳遞給INT        0x13函式的引數(C語言式理解),那麼JC        error 就是對函式返回值的判斷。
        ;那我們傳遞給函式的引數究竟什麼意思呢?主要是告訴這個函式我到底去哪個位置讀取我想要的資料呢? 畢竟磁碟大如海,想要知道具體去那一片資料還是不容易的。
        ;下面來看怎麼確定讀取磁碟想要的位置:①首先加入有多個驅動器,那麼我們要指定從哪個驅動器讀取,這就是DL乾的事;②然後00000
;======================================END===========================================
 
; 読み終わったけどとりあえずやることないので寢る
 
 
fin:
        HLT                        ; 何かあるまでCPUを停止させる
        JMP        fin                ; 無限ループ
 
 
error:
        MOV        SI,msg
putloop:
        MOV        AL,[SI]
        ADD        SI,1            ; SIに1を足す
        CMP        AL,0
        JE        fin
        MOV        AH,0x0e            ; 一文字表示ファンクション
        MOV        BX,15            ; カラーコード
        INT        0x10            ; ビデオBIOS呼び出し
        JMP        putloop
msg:
        DB        0x0a, 0x0a        ; 改行を2つ
        DB        "load error"
        DB        0x0a            ; 改行
        DB        0
 
 
        RESB    0x7dfe-$        ; 0x7dfeまでを0x00で埋める命令
 
 
        DB        0x55, 0xaa
  二:試錯         目的:就是為了防止再軟盤出現偶爾錯誤的時候,程式不會立即終止,仍然去嘗試再次讀取磁碟,才有了第二節的程式:         註釋:JNC:進位標誌是0的話跳轉    JAE大於或等於時跳轉         
; haribote-ipl
; TAB=4
 
 
        ORG        0x7c00            ; このプログラムがどこに読み込まれるのか
 
 
; 以下は標準的なFAT12フォーマットフロッピーディスクのための記述
 
 
        JMP        entry
        DB        0x90
        DB        "HARIBOTE"        ; ブートセクタの名前を自由に書いてよい(8バイト)
        DW        512                ; 1セクタの大きさ(512にしなければいけない)
        DB        1                ; クラスタの大きさ(1セクタにしなければいけない)
        DW        1                ; FATがどこから始まるか(普通は1セクタ目からにする)
        DB        2                ; FATの個數(2にしなければいけない)
        DW        224                ; ルートディレクトリ領域の大きさ(普通は224エントリにする)
        DW        2880            ; このドライブの大きさ(2880セクタにしなければいけない)
        DB        0xf0            ; メディアのタイプ(0xf0にしなければいけない)
        DW        9                ; FAT領域の長さ(9セクタにしなければいけない)
        DW        18                ; 1トラックにいくつのセクタがあるか(18にしなければいけない)
        DW        2                ; ヘッドの數(2にしなければいけない)
        DD        0                ; パーティションを使ってないのでここは必ず0
        DD        2880            ; このドライブ大きさをもう一度書く
        DB        0,0,0x29        ; よくわからないけどこの値にしておくといいらしい
        DD        0xffffffff        ; たぶんボリュームシリアル番號
        DB        "HARIBOTEOS "    ; ディスクの名前(11バイト)
        DB        "FAT12   "        ; フォーマットの名前(8バイト)
        RESB    18                ; とりあえず18バイトあけておく
 
 
; プログラム本體
 
 
entry:
        MOV        AX,0            ; レジスタ初期化
        MOV        SS,AX
        MOV        SP,0x7c00
        MOV        DS,AX
 
 
; ディスクを読む
 
 
        MOV        AX,0x0820
        MOV        ES,AX
        MOV        CH,0            ; 柱面0  CH表示的是柱面號
        MOV        DH,0            ; 磁頭0  磁頭號
        MOV        CL,2            ; 扇區2  CL扇區號
 
;===============================這次新增的新內容START=================================
        MOV        SI,0            ; 記錄失敗次數的暫存器
retry:
        MOV        AH,0x02         ; 讀盤(0x03是寫磁碟)  註釋: 看來每次讀寫資料,都要進行AH暫存器的配置,不像上面CL,可以儲存,只配置一次
        MOV        AL,1            ; 1扇區  註釋:這裡是讀寫扇區的數目,和上面的CL是不同的
        MOV        BX,0
        MOV        DL,0x00         ; A驅動器
        INT        0x13            ; 呼叫磁碟BIOS
        JNC        fin             ; 沒出錯的話,就跳轉到fine
        ADD        SI,1            ; 往SI+1
        CMP        SI,5            ; 比較SI與5
        JAE        error           ; SI >= 5 大於5時跳轉到error
        MOV        AH,0x00
        MOV        DL,0x00         ; A驅動器
        INT        0x13            ; 重置驅動器
        JMP        retry
;======================================END===========================================
 
; 読み終わったけどとりあえずやることないので寢る
 
 
fin:
        HLT                        ; 何かあるまでCPUを停止させる
        JMP        fin                ; 無限ループ
 
 
error:
        MOV        SI,msg
putloop:
        MOV        AL,[SI]
        ADD        SI,1            ; SIに1を足す
        CMP        AL,0
        JE        fin
        MOV        AH,0x0e            ; 一文字表示ファンクション
        MOV        BX,15            ; カラーコード
        INT        0x10            ; ビデオBIOS呼び出し
        JMP        putloop
msg:
        DB        0x0a, 0x0a        ; 改行を2つ
        DB        "load error"
        DB        0x0a            ; 改行
        DB        0
 
 
        RESB    0x7dfe-$        ; 0x7dfeまでを0x00で埋める命令
 
 
        DB        0x55, 0xaa

 

  本節新新增的程式碼轉化成C語言,大致如下(僅供參考,畢竟也是個菜雞)
ErrorHandling()
{
    static int SI=0;
    AH=0x002;
    AL=1;
    BX=0;
    DL=0x00;
    BOOL VAL=ExecutivDrive() ;
    if(FALSE == VAL)
    {
        執行fine函式;
    }
    else
    {
        SI++;
    }
    if(SI >= 5)
    {
        執行error函式;
    }
    else
    {
        AH=0x00;
        DL=0x00;
        BOOL VAL =ExecutivDrive();//執行驅動器
        if(TRUE == VAL)
        {
            ErrorHandling();
        }
    }
}
 
 
ExecutivDrive()
{
    INT  0x13;
}

 

  三,讀到18扇區         這節的目的主要就是教會我們怎麼利用迴圈讀寫其他扇區 柱面的內容。 同樣的下一屆的內容也就自然會了。
; haribote-ipl
; TAB=4
 
 
        ORG        0x7c00            ; このプログラムがどこに読み込まれるのか
 
 
; 以下は標準的なFAT12フォーマットフロッピーディスクのための記述
 
 
        JMP        entry
        DB        0x90
        DB        "HARIBOTE"        ; ブートセクタの名前を自由に書いてよい(8バイト)
        DW        512                ; 1セクタの大きさ(512にしなければいけない)
        DB        1                ; クラスタの大きさ(1セクタにしなければいけない)
        DW        1                ; FATがどこから始まるか(普通は1セクタ目からにする)
        DB        2                ; FATの個數(2にしなければいけない)
        DW        224                ; ルートディレクトリ領域の大きさ(普通は224エントリにする)
        DW        2880            ; このドライブの大きさ(2880セクタにしなければいけない)
        DB        0xf0            ; メディアのタイプ(0xf0にしなければいけない)
        DW        9                ; FAT領域の長さ(9セクタにしなければいけない)
        DW        18                ; 1トラックにいくつのセクタがあるか(18にしなければいけない)
        DW        2                ; ヘッドの數(2にしなければいけない)
        DD        0                ; パーティションを使ってないのでここは必ず0
        DD        2880            ; このドライブ大きさをもう一度書く
        DB        0,0,0x29        ; よくわからないけどこの値にしておくといいらしい
        DD        0xffffffff        ; たぶんボリュームシリアル番號
        DB        "HARIBOTEOS "    ; ディスクの名前(11バイト)
        DB        "FAT12   "        ; フォーマットの名前(8バイト)
        RESB    18                ; とりあえず18バイトあけておく
 
 
; プログラム本體
 
 
entry:
        MOV        AX,0            ; レジスタ初期化
        MOV        SS,AX
        MOV        SP,0x7c00
        MOV        DS,AX
 
 
; ディスクを読む
 
 
        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
;===============================這次新增的新內容START=================================
        JNC        next            ; 沒有出錯就跳轉到next
        ADD        SI,1            ; 往SI中+1  註釋:把他當作C語言中的臨時變數或者說靜態變數就好了
        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
        ADD        AX,0x0020       ; 0x0020是十六進位制下512除以16的結果。所以這裡的意思就是下一個512的地方。我們知道最開始的啟動區就是512,我們以512為一個扇區。
        MOV        ES,AX           ; ADD ES,0x020 という命令がないのでこうしている
        ADD        CL,1            ; CL+1 註釋: 這裡的意思是當讀取一個扇區成功後緊接著讀下一個扇區。
        CMP        CL,18           ; 比較CL與18  註釋:是否18個扇區都讀完了 
        JBE        readloop        ; 如果CL <= 18 就跳轉到read loop  註釋:小於等於就跳轉
;這一段程式碼主要是為了讀完18個扇區,這從最後的CL 與18的比較也能看出來。如果沒有讀完就返回最上面,如果讀完了就繼續執行到下面fine中
;======================================END===========================================
 
; 読み終わったけどとりあえずやることないので寢る
 
 
fin:
        HLT                        ; 何かあるまでCPUを停止させる
        JMP        fin                ; 無限ループ
 
 
error:
        MOV        SI,msg
putloop:
        MOV        AL,[SI]
        ADD        SI,1            ; SIに1を足す
        CMP        AL,0
        JE        fin
        MOV        AH,0x0e            ; 一文字表示ファンクション
        MOV        BX,15            ; カラーコード
        INT        0x10            ; ビデオBIOS呼び出し
        JMP        putloop
msg:
        DB        0x0a, 0x0a        ; 改行を2つ
        DB        "load error"
        DB        0x0a            ; 改行
        DB        0
 
 
        RESB    0x7dfe-$        ; 0x7dfeまでを0x00で埋める命令
 
 
        DB        0x55, 0xaa
 

 

      四,10個柱面         註釋:C0-H0-S1(柱面0;磁頭0,扇區1的縮寫);上一節中每次王CL中+1,更改的就是扇區。這把要讀柱面。可以看出,在位看書的i情況下,先行猜測,是在上一節上,在加個迴圈。來個cmp小於等於10  就行了。(純屬猜測,也不行改了)         
; haribote-ipl
; TAB=4
 
 
CYLS    EQU        10                ; 相當於巨集定義,將CYLS的值等於10
 
 
        ORG        0x7c00            ; このプログラムがどこに読み込まれるのか
 
 
; 以下は標準的なFAT12フォーマットフロッピーディスクのための記述
 
 
        JMP        entry
        DB        0x90
        DB        "HARIBOTE"        ; ブートセクタの名前を自由に書いてよい(8バイト)
        DW        512                ; 1セクタの大きさ(512にしなければいけない)
        DB        1                ; クラスタの大きさ(1セクタにしなければいけない)
        DW        1                ; FATがどこから始まるか(普通は1セクタ目からにする)
        DB        2                ; FATの個數(2にしなければいけない)
        DW        224                ; ルートディレクトリ領域の大きさ(普通は224エントリにする)
        DW        2880            ; このドライブの大きさ(2880セクタにしなければいけない)
        DB        0xf0            ; メディアのタイプ(0xf0にしなければいけない)
        DW        9                ; FAT領域の長さ(9セクタにしなければいけない)
        DW        18                ; 1トラックにいくつのセクタがあるか(18にしなければいけない)
        DW        2                ; ヘッドの數(2にしなければいけない)
        DD        0                ; パーティションを使ってないのでここは必ず0
        DD        2880            ; このドライブ大きさをもう一度書く
        DB        0,0,0x29        ; よくわからないけどこの値にしておくといいらしい
        DD        0xffffffff        ; たぶんボリュームシリアル番號
        DB        "HARIBOTEOS "    ; ディスクの名前(11バイト)
        DB        "FAT12   "        ; フォーマットの名前(8バイト)
        RESB    18                ; とりあえず18バイトあけておく
 
 
; プログラム本體
 
 
entry:
        MOV        AX,0            ; レジスタ初期化
        MOV        SS,AX
        MOV        SP,0x7c00
        MOV        DS,AX
 
 
; ディスクを読む
 
 
        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個扇區 註釋:這裡是讀寫扇區的數目,和上面的CL是不同的
        MOV        BX,0
        MOV        DL,0x00            ; Aドライブ
        INT        0x13            ; ディスクBIOS呼び出し
        JNC        next            ; エラーがおきなければ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進める
        ADD        AX,0x0020
        MOV        ES,AX            ; ADD ES,0x020 という命令がないのでこうしている
        ADD        CL,1            ; CLに1を足す
        CMP        CL,18            ; CLと18を比較
        JBE        readloop        ; CL <= 18 だったらreadloopへ
;===============================這次新增的新內容START=================================
        MOV        CL,1            ;這裡為什麼讀完18個扇區後,讀下一個柱面的時候,CL先+1呢? 整個磁碟是一個迴圈。洗一個柱面從第一個扇區開始讀寫的。
        ADD        DH,1            ;有兩個磁頭,正反面,反正我是這樣理解的
        CMP        DH,2
        JB        readloop        ; 如果DH < 2 就跳轉到readloop。
        MOV        DH,0            ;反面讀完了,那麼從正面在開始讀,磁頭便置零了
        ADD        CH,1            ;好了,柱面也開始+1了
        CMP        CH,CYLS        ; 這裡還用了一個巨集定義。代表10個柱面
        JB        readloop        ; 如果CH < CYLS 就跳轉到readloop
;======================================END===========================================
 
; 読み終わったけどとりあえずやることないので寢る
 
 
fin:
        HLT                        ; 何かあるまでCPUを停止させる
        JMP        fin                ; 無限ループ
 
 
error:
        MOV        SI,msg
putloop:
        MOV        AL,[SI]
        ADD        SI,1            ; SIに1を足す
        CMP        AL,0
        JE        fin
        MOV        AH,0x0e            ; 一文字表示ファンクション
        MOV        BX,15            ; カラーコード
        INT        0x10            ; ビデオBIOS呼び出し
        JMP        putloop
msg:
        DB        0x0a, 0x0a        ; 改行を2つ
        DB        "load error"
        DB        0x0a            ; 改行
        DB        0
 
 
        RESB    0x7dfe-$        ; 0x7dfeまでを0x00で埋める命令
 
 
        DB        0x55, 0xaa
 

 

    到這裡是完成了啟動區的製作。其實到這裡回過頭來看下,作者只是將10×2×18×512=184320byte=180KB內容完整無誤的裝在到記憶體裡面了。這裡有個疑問:裝載到類裡面然後幹啥? 我們的程式(C語言的main)就能運行了? 如果我的main不止這個數呢? 哦 這裡只是啟動區,它可以接著呼叫main函式? 害這裡還是不理解,不能舉一反三,真特麼的垃圾,接著往後面看:  
  五,著手開發作業系統         好吧我覺的這節太扯了。表示其實沒有真的看懂,大致知道怎麼回事。仔細想想又不知道具體是怎麼回事。          六,從啟動區執行作業系統         對ORG的應用。其他的在地五節已經講過了  
; haribote-ipl
; TAB=4
 
 
CYLS    EQU        10                ; どこまで読み込むか
 
 
        ORG        0x7c00            ; このプログラムがどこに読み込まれるのか
 
 
; 以下は標準的なFAT12フォーマットフロッピーディスクのための記述
 
 
        JMP        entry
        DB        0x90
        DB        "HARIBOTE"        ; ブートセクタの名前を自由に書いてよい(8バイト)
        DW        512                ; 1セクタの大きさ(512にしなければいけない)
        DB        1                ; クラスタの大きさ(1セクタにしなければいけない)
        DW        1                ; FATがどこから始まるか(普通は1セクタ目からにする)
        DB        2                ; FATの個數(2にしなければいけない)
        DW        224                ; ルートディレクトリ領域の大きさ(普通は224エントリにする)
        DW        2880            ; このドライブの大きさ(2880セクタにしなければいけない)
        DB        0xf0            ; メディアのタイプ(0xf0にしなければいけない)
        DW        9                ; FAT領域の長さ(9セクタにしなければいけない)
        DW        18                ; 1トラックにいくつのセクタがあるか(18にしなければいけない)
        DW        2                ; ヘッドの數(2にしなければいけない)
        DD        0                ; パーティションを使ってないのでここは必ず0
        DD        2880            ; このドライブ大きさをもう一度書く
        DB        0,0,0x29        ; よくわからないけどこの値にしておくといいらしい
        DD        0xffffffff        ; たぶんボリュームシリアル番號
        DB        "HARIBOTEOS "    ; ディスクの名前(11バイト)
        DB        "FAT12   "        ; フォーマットの名前(8バイト)
        RESB    18                ; とりあえず18バイトあけておく
 
 
; プログラム本體
 
 
entry:
        MOV        AX,0            ; レジスタ初期化
        MOV        SS,AX
        MOV        SP,0x7c00
        MOV        DS,AX
 
 
; ディスクを読む
 
 
        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            ; エラーがおきなければ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進める
        ADD        AX,0x0020
        MOV        ES,AX            ; ADD ES,0x020 という命令がないのでこうしている
        ADD        CL,1            ; CLに1を足す
        CMP        CL,18            ; CLと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 < CYLS だったらreadloopへ
 
 
; 読み終わったのでharibote.sysを実行だ!
 
;===============================這次新增的新內容START=================================
        JMP        0xc200            
        ;這裡就是,將之前說的180KB的內容裝進了記憶體中,並且我們知道了我們的程式在0xc200的位置
        ;所以前面做的只是讀取,這裡有點犯迷糊。仔細想一想,之前是讀取磁碟的內容到一個記憶體中
        ;假設他們的地址從0~100,現在我們讀完之後,到自己的記憶體中c200的位置去執行。好吧反正我是覺得挺繞的。
        ;另外我們的磁碟大小就是180KB,我想知道如果程式不在這個180 中怎麼辦?或者180沒讀完怎麼辦?????
;======================================END===========================================
error:
        MOV        SI,msg
putloop:
        MOV        AL,[SI]
        ADD        SI,1            ; SIに1を足す
        CMP        AL,0
        JE        fin
        MOV        AH,0x0e            ; 一文字表示ファンクション
        MOV        BX,15            ; カラーコード
        INT        0x10            ; ビデオBIOS呼び出し
        JMP        putloop
fin:
        HLT                        ; 何かあるまでCPUを停止させる
        JMP        fin                ; 無限ループ
msg:
        DB        0x0a, 0x0a        ; 改行を2つ
        DB        "load error"
        DB        0x0a            ; 改行
        DB        0
 
 
        RESB    0x7dfe-$        ; 0x7dfeまでを0x00で埋める命令
 
 
        DB        0x55, 0xaa
 
 
 
 
七,確認作業系統的執行情況
        註釋:這節主要的目的是給顯示其以色彩。呼叫顯使能
; haribote-ipl
; TAB=4
 
 
CYLS    EQU        10                ; どこまで読み込むか
 
 
        ORG        0x7c00            ; このプログラムがどこに読み込まれるのか
 
 
; 以下は標準的なFAT12フォーマットフロッピーディスクのための記述
 
 
        JMP        entry
        DB        0x90
        DB        "HARIBOTE"        ; ブートセクタの名前を自由に書いてよい(8バイト)
        DW        512                ; 1セクタの大きさ(512にしなければいけない)
        DB        1                ; クラスタの大きさ(1セクタにしなければいけない)
        DW        1                ; FATがどこから始まるか(普通は1セクタ目からにする)
        DB        2                ; FATの個數(2にしなければいけない)
        DW        224                ; ルートディレクトリ領域の大きさ(普通は224エントリにする)
        DW        2880            ; このドライブの大きさ(2880セクタにしなければいけない)
        DB        0xf0            ; メディアのタイプ(0xf0にしなければいけない)
        DW        9                ; FAT領域の長さ(9セクタにしなければいけない)
        DW        18                ; 1トラックにいくつのセクタがあるか(18にしなければいけない)
        DW        2                ; ヘッドの數(2にしなければいけない)
        DD        0                ; パーティションを使ってないのでここは必ず0
        DD        2880            ; このドライブ大きさをもう一度書く
        DB        0,0,0x29        ; よくわからないけどこの値にしておくといいらしい
        DD        0xffffffff        ; たぶんボリュームシリアル番號
        DB        "HARIBOTEOS "    ; ディスクの名前(11バイト)
        DB        "FAT12   "        ; フォーマットの名前(8バイト)
        RESB    18                ; とりあえず18バイトあけておく
 
 
; プログラム本體
 
 
entry:
        MOV        AX,0            ; レジスタ初期化
        MOV        SS,AX
        MOV        SP,0x7c00
        MOV        DS,AX
 
 
; ディスクを読む
 
 
        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            ; エラーがおきなければ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進める
        ADD        AX,0x0020
        MOV        ES,AX            ; ADD ES,0x020 という命令がないのでこうしている
        ADD        CL,1            ; CLに1を足す
        CMP        CL,18            ; CLと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 < CYLS だったらreadloopへ
 
 
; 読み終わったのでharibote.sysを実行だ!
 
 
;===============================這次新增的新內容START=================================
 
        MOV        [0x0ff0],CH        ; 記下IPL讀到哪裡了。  註釋:咱也不知道這裡是幹啥用的,後面看看再說
                                        ;理解:大致意思是我們當前在哪一個柱面
        JMP        0xc200
;======================================END===========================================
 
error:
        MOV        SI,msg
putloop:
        MOV        AL,[SI]
        ADD        SI,1            ; SIに1を足す
        CMP        AL,0
        JE        fin
        MOV        AH,0x0e            ; 一文字表示ファンクション
        MOV        BX,15            ; カラーコード
        INT        0x10            ; ビデオBIOS呼び出し
        JMP        putloop
fin:
        HLT                        ; 何かあるまでCPUを停止させる
        JMP        fin                ; 無限ループ
msg:
        DB        0x0a, 0x0a        ; 改行を2つ
        DB        "load error"
        DB        0x0a            ; 改行
        DB        0
 
 
        RESB    0x7dfe-$        ; 0x7dfeまでを0x00で埋める命令
 
 
        DB        0x55, 0xaa




 
;haribote.nas
; haribote-os
; TAB=4
 
 
 
 
 
;===============================這次新增的新內容START=================================
        ORG        0xc200            ; 這個程式要被裝在到記憶體的什麼地方呢?  
                                     ;這個意思就是說,我們的程式所有的最初的地方是從這個地址開始的
 
 
        MOV        AL,0x13            ; 這裡的AL和之前的啟動區的AL 和 AH不大一樣。注意區分!這裡是VGA顯示卡,320×200×8位彩色
        MOV        AH,0x00
        INT        0x10            ;沒猜錯這裡的INT就是顯示卡的 那個BIOS,和之前的CPU的BIOS一樣的方式。先設定引數,在呼叫這裡。上面的AH應該就是引數了
;======================================END===========================================
fin:
        HLT
        JMP        fin

 

解釋:     八,32位的前期準備         
; haribote-os
; TAB=4
 
 
; BOOT_INFO関係
CYLS    EQU        0x0ff0            ; 設定啟動區
LEDS    EQU        0x0ff1
VMODE    EQU        0x0ff2            ; 關於顏色數目的資訊。顏色的位數
SCRNX    EQU        0x0ff4            ; 解析度的X
SCRNY    EQU        0x0ff6            ; 解析度的Y
VRAM    EQU        0x0ff8            ; 影象緩衝區的開始地址  註釋:VRAM是顯示卡記憶體
 
 
        ORG        0xc200            ; 這個程式要裝載到的記憶體的地方
 
 
        MOV        AL,0x13            ; VGA顯示卡,320x200x8位彩色
        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
 
 
fin:
        HLT
        JMP        fin

 

      九:開始匯入C語言         
;asmhead.nas
; haribote-os boot asm
; TAB=4
 
 
BOTPAK    EQU        0x00280000        ; bootpackのロード先
DSKCAC    EQU        0x00100000        ; ディスクキャッシュの場所
DSKCAC0    EQU        0x00008000        ; ディスクキャッシュの場所(リアルモード)
 
 
; BOOT_INFO関係
CYLS    EQU        0x0ff0            ; ブートセクタが設定する
LEDS    EQU        0x0ff1
VMODE    EQU        0x0ff2            ; 色數に関する情報。何ビットカラーか?
SCRNX    EQU        0x0ff4            ; 解像度のX
SCRNY    EQU        0x0ff6            ; 解像度のY
VRAM    EQU        0x0ff8            ; グラフィックバッファの開始番地
 
 
        ORG        0xc200            ; このプログラムがどこに読み込まれるのか
 
 
; 畫面モードを設定
 
 
        MOV        AL,0x13            ; VGAグラフィックス、320x200x8bitカラー
        MOV        AH,0x00
        INT        0x10
        MOV        BYTE [VMODE],8    ; 畫面モードをメモする(C言語が參照する)
        MOV        WORD [SCRNX],320
        MOV        WORD [SCRNY],200
        MOV        DWORD [VRAM],0x000a0000
 
 
; キーボードのLED狀態をBIOSに教えてもらう
 
 
        MOV        AH,0x02
        INT        0x16             ; keyboard BIOS
        MOV        [LEDS],AL
;===============================這次新增的新內容START=================================
;這裡就是為了系統能夠呼叫C語言做的準備,但是作者目前沒有說,期待之後的補充
; PICが一切の割り込みを受け付けないようにする
;    AT互換機の仕様では、PICの初期化をするなら、
;    こいつをCLI前にやっておかないと、たまにハングアップする
;    PICの初期化はあとでやる
 
 
        MOV        AL,0xff
        OUT        0x21,AL
        NOP                        ; OUT命令を連続させるとうまくいかない機種があるらしいので
        OUT        0xa1,AL
 
 
        CLI                        ; さらにCPUレベルでも割り込み禁止
 
 
; CPUから1MB以上のメモリにアクセスできるように、A20GATEを設定
 
 
        CALL    waitkbdout
        MOV        AL,0xd1
        OUT        0x64,AL
        CALL    waitkbdout
        MOV        AL,0xdf            ; enable A20
        OUT        0x60,AL
        CALL    waitkbdout
 
 
; プロテクトモード移行
 
 
[INSTRSET "i486p"]                ; 486の命令まで使いたいという記述
 
 
        LGDT    [GDTR0]            ; 暫定GDTを設定
        MOV        EAX,CR0
        AND        EAX,0x7fffffff    ; bit31を0にする(ページング禁止のため)
        OR        EAX,0x00000001    ; bit0を1にする(プロテクトモード移行のため)
        MOV        CR0,EAX
        JMP        pipelineflush
pipelineflush:
        MOV        AX,1*8            ;  読み書き可能セグメント32bit
        MOV        DS,AX
        MOV        ES,AX
        MOV        FS,AX
        MOV        GS,AX
        MOV        SS,AX
 
 
; bootpackの転送
 
 
        MOV        ESI,bootpack    ; 転送元
        MOV        EDI,BOTPAK        ; 転送先
        MOV        ECX,512*1024/4
        CALL    memcpy
 
 
; ついでにディスクデータも本來の位置へ転送
 
 
; まずはブートセクタから
 
 
        MOV        ESI,0x7c00        ; 転送元
        MOV        EDI,DSKCAC        ; 転送先
        MOV        ECX,512/4
        CALL    memcpy
 
 
; 殘り全部
 
 
        MOV        ESI,DSKCAC0+512    ; 転送元
        MOV        EDI,DSKCAC+512    ; 転送先
        MOV        ECX,0
        MOV        CL,BYTE [CYLS]
        IMUL    ECX,512*18*2/4    ; シリンダ數からバイト數/4に変換
        SUB        ECX,512/4        ; IPLの分だけ差し引く
        CALL    memcpy
 
 
; asmheadでしなければいけないことは全部し終わったので、
;    あとはbootpackに任せる
 
 
; bootpackの起動
 
 
        MOV        EBX,BOTPAK
        MOV        ECX,[EBX+16]
        ADD        ECX,3            ; ECX += 3;
        SHR        ECX,2            ; ECX /= 4;
        JZ        skip            ; 転送するべきものがない
        MOV        ESI,[EBX+20]    ; 転送元
        ADD        ESI,EBX
        MOV        EDI,[EBX+12]    ; 転送先
        CALL    memcpy
skip:
        MOV        ESP,[EBX+12]    ; スタック初期値
        JMP        DWORD 2*8:0x0000001b
 
 
waitkbdout:
        IN         AL,0x64
        AND         AL,0x02
        JNZ        waitkbdout        ; ANDの結果が0でなければwaitkbdoutへ
        RET
 
 
memcpy:
        MOV        EAX,[ESI]
        ADD        ESI,4
        MOV        [EDI],EAX
        ADD        EDI,4
        SUB        ECX,1
        JNZ        memcpy            ; 引き算した結果が0でなければmemcpyへ
        RET
; memcpyはアドレスサイズプリフィクスを入れ忘れなければ、ストリング命令でも書ける
 
 
        ALIGNB    16
GDT0:
        RESB    8                ; ヌルセレクタ
        DW        0xffff,0x0000,0x9200,0x00cf    ; 読み書き可能セグメント32bit
        DW        0xffff,0x0000,0x9a28,0x0047    ; 実行可能セグメント32bit(bootpack用)
 
 
        DW        0
GDTR0:
        DW        8*3-1
        DD        GDT0
 
 
        ALIGNB    16
bootpack:
;======================================END===========================================
 
 
    
void HariMain(void)
{
 
 
fin:
    /* ここにHLTを入れたいのだが、C言語ではHLTが使えない! */
    goto fin;
 
 
}

 

          &nbs