Day_03 进入32位模式并导入C语言

发布于 2021-05-05  466 次阅读


制作真正的IPL

IPL(Initial Program Loader,启动程序装载器)。
磁盘最初的512字节是启动区,所以要装载下一个512字节的内容。

; haribote-ipl
; TAB=4

        ORG     0x7c00          ; 指明程序的装在地址

; 以下的记述用于标记FAT12格式的软盘

        JMP     entry
        DB      0x90
        DB      "HARIBOTE"        ; 启动区的名称可以是任意是字符串(8字节)
        DW      512             ; 每个扇区(sector)的大小(必须为512字节)
        DB      1               ; 簇(cluster)的大小(必须为1个扇区)
        DW      1               ; FAT的起试位置(一般从第一个扇区开始)
        DB      2               ; FAT的个数(必须为2)
        DW      224             ; 根目录的大小(一般设置成224项)
        DW      2880            ; 该磁盘的大小(必须是2880扇区)
        DB      0xf0            ; 磁盘的种类(必须是0xf0)
        DW      9               ; FAT的长度(必须是9扇区)
        DW      18              ; 1个磁道(track)有几个扇区(必须是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

        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加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-$        ;填写0x00,直到0x001fe

        DB      0x55, 0xaa

JC(如果进位标志是1的化,就跳转)
‘INT 0x13’调用BIOS0x13号函数。
file
file
进位标志是一个只能存储1位信息的寄存器。CPU还又其他几个1位寄存器,1位寄存器我们称为标志。标志在英文中位flag(旗帜)。开关就像升旗降旗的状态一样。
这次CF的作用是报告BIOS函数调用是否有错的。
CH,CL,DH,DL分别是柱面号、扇区号、磁头号、驱动器号
file
file
file
file
缓冲地址:这是个内存地址,表明要把从软盘上读出的数据装载到内存的哪个位置。当时为了寻址,设计了起辅助作用的段寄存器(segment register)在指定内存地址的时候,可以使用这个段寄存器。
ES:BX 这种方式来表示地址,写成MOV AL,[ES:BX], 他代表ES×16+BX的内存地址。
file
不管要指定内存的什么地址,都必须同时指定段寄存器这是规定。一般如果是省略的话,就会把'DS:'作为默认的段寄存器。
‘MOV CX,[1234]’其实是‘MOV CX,[DS: 1234]’的意思。在汇编语言中,可以省略默认的段寄存器DS
因为有这样的规则,所以DS必须预先指定位0,否则地址的值就要加上这个数的16倍,就会读写到其他地方,引起混乱。
file

试错

        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加1
        CMP     SI,5            ; 比较SI与5
        JAE     error           ; SI >= 5 跳转到error
        MOV     AH,0x00
        MOV     DL,0x00         ; A驱动器
        INT     0x13            ; 重置驱动器
        JMP     retry

JNC是另外一个条件跳转指令'jump if not carry'的缩写。也就是说进位标志是0的话就跳转。JAE也是条件跳转指令,‘Jump if above or equal’,意思是大于或等于时跳转。
file

读到18扇区

; haribote-ipl
; TAB=4

        ORG     0x7c00          ; 指明程序的装在地址

; 以下的记述用于标记FAT12格式的软盘

        JMP     entry
        DB      0x90
        DB      "HARIBOTE"        ; 启动区的名称可以是任意是字符串(8字节)
        DW      512             ; 每个扇区(sector)的大小(必须为512字节)
        DB      1               ; 簇(cluster)的大小(必须为1个扇区)
        DW      1               ; FAT的起试位置(一般从第一个扇区开始)
        DB      2               ; FAT的个数(必须为2)
        DW      224             ; 根目录的大小(一般设置成224项)
        DW      2880            ; 该磁盘的大小(必须是2880扇区)
        DB      0xf0            ; 磁盘的种类(必须是0xf0)
        DW      9               ; FAT的长度(必须是9扇区)
        DW      18              ; 1个磁道(track)有几个扇区(必须是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

; 虽然读完了,但是因为没有要做的事情所以睡眠

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      ; 换行两行
        DB      "load error"
        DB      0x0a            ; 换行
        DB      0

        RESB    0x7dfe-$        ; 以0x00填充到0x7dfe为止的命令

        DB      0x55, 0xaa

JBE条件跳转指令,是“Jump if below or equal”的缩写,小于等于则跳转。
file
file
file


擦肩而过的概率