以上的流程图为自己理解描绘的,下面的代码为《30天自制操作系统》书中的源码,我加以注释
; haribote-ipl
; TAB=4
CYLS EQU 10 ; 定义的常量
ORG 0x7c00 ; 将程序加载到内存的地址
;FAT12软盘的专用格式
JMP entry
DB 0x90
DB "BlueSea " ; 必须为8个字节的启动扇区名称
DW 512 ; 每个扇区的字节数
DB 1 ; 簇的大小(每个簇有多少个扇区)
DW 1 ; FAT的起始位置
DB 2 ; FAT的个数
DW 224 ; 根目录的大小
DW 2880 ;该磁盘的大小(必须为2880个扇区)
DB 0xf0 ; 磁盘种类
DW 9 ;FAT长度
DW 18 ; 磁道含有的扇区个数
DW 2 ; 磁头数
DD 0 ; 不使用分区
DD 2880 ; 重写一次磁盘大小
DB 0,0,0x29;
DD 0xffffffff;
DB "HARIBOTEOS " ; 磁盘名称(11字节)
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
readloop:
MOV SI,0 ; SI记录读取失败的次数
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 ; 调用BIOS函数
JMP retry
next:
MOV AX,ES ; AX作为过渡的寄存器
ADD AX,0x0020 ; ES的值与0x0020相加
MOV ES,AX ; 相加结果放入ES偱偙偆偟偰偄傞
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 的连接
MOV [0x0ff0],CH ; IPL启动程序加载了的柱面数
JMP 0xc200
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
fin:
HLT ;
JMP fin;
msg:
DB 0x0a, 0x0a ; 两个换行符
DB "load error"
DB 0x0a ; 换行
DB 0
RESB 0x7dfe-$ ; 保证510,511字节是55 aa
DB 0x55, 0xaa