進入32位模式並導入C語言

製作真正的IPL
1.helloos.nas文件及註解

; hello-os
; TAB=4

; 以下是一段是標準的fat12格式軟盤專用的代碼

        DB      0xeb, 0x4e, 0x90
        DB      "HELLOIPL"      ;啓動區的名稱可以使任意的字符串
        DW      512             ;每個扇區的大小(必?512DB      1               ; 簇的大小
        DW      1               ; fat的起始位置
        DB      2               ; fat的個數
        DW      224             ; 根目錄的大小(一般設置成224)
        DW      2880            ; 該磁盤的大小(必須是2880扇區)
        DB      0xf0            ;磁盤的種類(必須是0xf0DW      9               ;fat的長度(必須是9扇區)
        DW      18              ; 1個磁道有幾個扇區(必須是18DW      2               ; 磁頭數
        DD      0               ; 不使用分區,必須是0
        DD      2880            ; 重寫一次磁盤大小(必須是2880DB      0,0,0x29        ;意義不明,固定
        DD      0xffffffff      ; (可能是)卷標號碼
        DB      "HELLO-OS   "   ; 磁盤的名稱
        DB      "FAT12   "      ;磁盤格式名稱
        RESB    18              ;先空出18字節

; 程序主體

        DB      0xb8, 0x00, 0x00, 0x8e, 0xd0, 0xbc, 0x00, 0x7c
        DB      0x8e, 0xd8, 0x8e, 0xc0, 0xbe, 0x74, 0x7c, 0x8a
        DB      0x04, 0x83, 0xc6, 0x01, 0x3c, 0x00, 0x74, 0x09
        DB      0xb4, 0x0e, 0xbb, 0x0f, 0x00, 0xcd, 0x10, 0xeb
        DB      0xee, 0xf4, 0xeb, 0xfd

;信息顯示部分

        DB      0x0a, 0x0a      ; 改行
        DB      "hello, world"
        DB      0x0a            ; 改行
        DB      0

        RESB    0x1fe-$            ;

        DB      0x55, 0xaa

; 以下是啓動區意外部分的輸出

        DB      0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00
        RESB    4600
        DB      0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00
        RESB    1469432
  1. ipl.nas
; haribote-ipl
; TAB=4

        ORG     0x7c00          ; 啓動區入口

; 以下是一段是標準的fat12格式軟盤專用的代碼

        JMP     entry
        DB      0x90
        DB      "HELLOIPL"      ;啓動區的名稱可以使任意的字符串
        DW      512             ;每個扇區的大小(必?512)
        DB      1               ; 簇的大小
        DW      1               ; fat的起始位置
        DB      2               ; fat的個數
        DW      224             ; 根目錄的大小(一般設置成224)
        DW      2880            ; 該磁盤的大小(必須是2880扇區)
        DB      0xf0            ;磁盤的種類(必須是0xf0)
        DW      9               ;fat的長度(必須是9扇區)
        DW      18              ; 1個磁道有幾個扇區(必須是18)
        DW      2               ; 磁頭數
        DD      0               ; 不使用分區,必須是0
        DD      2880            ; 重寫一次磁盤大小(必須是2880)
        DB      0,0,0x29        ;意義不明,固定
        DD      0xffffffff      ; (可能是)卷標號碼
        DB      "HELLO-OS   "   ; 磁盤的名稱
        DB      "FAT12   "      ;磁盤格式名稱
        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

        MOV     AH,0x02         ; AH=0x02 : 讀盤
        MOV     AL,1            ; 1個磁區
        MOV     BX,0
        MOV     DL,0x00         ; A驅動器
        INT     0x13            ; 調用磁盤BIOS
        JC      error



fin:
        HLT                     ; 讓CPU停止;等待指令
        JMP     fin             ; 無限循環

error:
        MOV     SI,msg
putloop:
        MOV     AL,[SI]
        ADD     SI,1            ;給si加一
        CMP     AL,0
        JE      fin
        MOV     AH,0x0e         ; 顯示一個文字
        MOV     BX,15           ; 指定字符顏色
        INT     0x10            ; 調用顯卡BIOS
        JMP     putloop
msg:
        DB      0x0a, 0x0a      ;換行兩次
        DB      "load error"
        DB      0x0a            ; 改行
        DB      0

        RESB    0x7dfe-$       

        DB      0x55, 0xaa

1張軟盤有80個柱面,2個磁頭,18個扇區,每個扇區有512個字節。所以一張軟盤的容量爲80*2*18*512=1440kb

試錯
軟盤有可能發生不能讀數據的錯誤情況,所以決定利用循環重試5次。
添加的代碼如下:

;讀磁盤
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             ; 沒錯的話跳入fin
        ADD     SI,1            ; 否則si加一
        CMP     SI,5            ; SI與5比較
        JAE     error           ; SI >= 5 跳轉到error
        MOV     AH,0x00
        MOV     DL,0x00         ; A驅動器
        INT     0x13            ; 充值驅動器
        JMP     retry

出錯後的處理:重新讀盤之前,做了如下處理:
AH=0x00,DL=0x00,INT=0x13。這些代碼的作用是系統復位,復位軟盤狀態。

3.讀到18扇區
本次添加的代碼:

; 讀磁盤

        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                ; 沒錯的話跳入fin
        ADD     SI,1            ; 否則si加一
        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      

要讀下一個扇區,只需要將cl加一,ES加上0x20就行了。cl爲扇區號,es爲讀入的地址。es加上20相當於bx加上512.

4.讀入10個柱面
本次添加的代碼如下:

;讀磁盤

        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                ; 沒錯的話跳入fin
        ADD     SI,1            ; 否則si加一
        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

注意在程序的開頭用瞭如下代碼:CYLS EQU 10意思是CYLS=10
現在把軟盤最初的10*2*18*512=184320byte=180kb裝載到內存中去了。填在內存0x08200~0x34fff的地方。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章