由于<30天自制操作系统>这本书是在06年于日本出版的,10年后的今天很多资料都遗失了,所以开发过程中还真不顺利。辛亏网上有很多例子可以参考,比如:https://blog.slinuxer.com
磁盘引导需要使用一个新的中断 Int 0x13,下面是代码。
// ip.asm ORG 0x7c00 ; FAT12 磁盘相关参数 JMP entry DB 0xeb, 0x4e, 0x90 DB "12345678" DW 512 DB 1 DW 1 DB 2 DW 224 DW 2880 DB 0Xf0 DW 9 DW 18 DW 2 DD 0 DD 2880 DB 0, 0, 0x29 DD 0xffffffff DB "0123456789A" DB "FAT12 " RESB 18 entry: MOV AX, 0 ; 寄存器初始化 MOV SS, AX ; SS:[SP] MOV SP, 0x7c00 MOV DS, AX ; DS:[SI] MOV ES, AX ; ES:[DI] MOV SI,msg putloop: MOV AL,[SI] ADD SI,1 ; 给SI加1 CMP AL,0 JE rddisk MOV AH,0x0e ; 显示一个文字 MOV BX,15 ; 指定字符颜色 INT 0x10 ; 调用显卡BIOS JMP putloop ; 读取磁盘 int 0x13 rddisk: MOV AX, 0x0820 MOV ES, AX MOV CH, 0 ; 0 柱面 0 磁头 2 扇区 MOV DH, 0 MOV CL, 2 MOV AH, 0x02 ; 读磁盘 MOV AL, 1 ; 连续读取扇区1 MOV BX, 0 MOV DL, 0x00 ; 软盘A INT 0x13 JMP 0x8200 fin: HLT JMP fin msg: DB 0x0a, 0x0a DB "read disk..." DB 0x0a DB 0 error: DB 0x0a, 0x0a DB "read disk error!" DB 0x0a DB 0 RESB 0x1fe-($-$$) DB 0x55, 0xaa // hello.asm ORG 0x8200 ; 0x8200 MOV AX,0 ; 初始化寄存器 MOV SS,AX MOV SP,0x8200 MOV DS,AX MOV ES,AX 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 "boot success" DB 0x0a ; 换行 DB 0
代码的原理是:ipl.asm的前512 byte会自动被bios复制到0x7c00并执行。但是由于512 byte空间并不足以放下一个系统,所以需要在0x7c00里实现一个简单的loader把磁盘里的程序拷贝到0x8200的位置。难点是int 0x13的寄存器意义。