进入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的地方。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值