来自《30天自制操作系统》
程序以二进制形式存储在启动盘的第一个扇区,系统启动时,bios自动读入启动盘的第一个扇区,检测其最后两个字节,发现是0x55和0xaa,表面该扇区是启动扇区,于是载入该扇区的程序,放到0x7c00的内存位置(操作系统的启动区皆放于此),然后如程序所示,载入操作系统所在的扇区后,跳转到操作系统所在的内存开始执行···
; haribote-ipl
; TAB=4
CYLS EQU 10 ; 读入的柱面个数
ORG 0x7c00 ; 载入内存的位置
; 以下这段是表中FAT12格式软盘专用的代码
JMP entry
DB 0x90
DB "HARIBOTE" ; 启动区的名字可以使人员字符串
DW 512 ; 每个扇区的大小(512个字节)
DB 1 ; 簇的大小,一个扇区
DW 1 ; FAT的起始位置,一般冲第一个扇区开始
DB 2 ; FAT的个数,必须为2
DW 224 ; 根目录的大小,一般设置成224项
DW 2880 ; 该磁盘的大小,一般设置为2880扇区
DB 0xf0 ; 磁盘的种类
DW 9 ; FAT的长度,此处是九扇区
DW 18 ; 一个磁道的扇区数目
DW 2 ; 磁头数目
DD 0 ; 不使用分区,此处是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 ; 记录失败次数的寄存器,最多重试五次
retry:
MOV AH,0x02 ; AH=0x02 : 读盘
MOV AL,1 ; 一个扇区
MOV BX,0
MOV DL,0x00 ; A驱动器
INT 0x13 ; 调用磁盘BIOS,磁盘读写
JNC next ;
ADD SI,1 ; 往SI加一
CMP SI,5 ; 比较
JAE error ; SI >= 5 ,跳至错位处理程序
MOV AH,0x00
MOV DL,0x00 ; A驱动器
INT 0x13 ; 重置驱动器
JMP retry
next:
MOV AX,ES ; 把内存地址后移0x200,表示为十进制为512个字节,即一个扇区的大小
ADD AX,0x0020
MOV ES,AX ; ADD ES,0x020 这个指令没法实现,所以通过AX来中转
ADD CL,1 ; CL加1
CMP CL,18 ; 比较CL与18,一个柱面得到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在哪里读到的记录,CH为10(读入的柱面数目)
JMP 0xc200 ;操作系统载入到的内存地址(开始载入位置+ 内容相对位置)
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 ; 换行两次
DB "load error"
DB 0x0a ; 执行
DB 0
RESB 0x7dfe-$ ; 0x7dfe地址以前填充0x00
DB 0x55, 0xaa ;扇区最后两个字节,表面该扇区存储的是启动程序