学操作系统是枯燥的,所以需要一些成果来调剂一下,今天就来写一个引导区吧。由于书上是用软盘启动(或虚拟硬盘),所以先准备一个空的虚拟软盘映像吧,这个网上教程很多就不细说了。注:软盘用FAT12格式1.44M的。
要写一个从软盘引导的程序就首先要知道软盘的组织结构,
;引导扇区格式
;-----------------------------------------------------------------------------------
;start length 内容 值
;0 3 一个短跳转指令 jmp LABEL_START nop
;3 8 厂商名 '********'(任意8字节)
;11 2 每扇区字节数 0x200
;13 1 每簇扇区数 0x01
;14 2 Boot记录占用多少扇区 0x0001 -------BPB_TecSec16
;16 1 共有多少FAT表 0x02
;17 2 根目录文件数最大值 0xe0
;19 2 扇区总数 0xB40
;21 1 介质描述符 0xf0
;22 2 每FAT扇区数 0x09
;24 2 每磁道扇区数 0x12
;26 2 磁头数(面数) 0x02
;28 4 隐藏扇区数 0
;32 4 若BPB_TecSec16=0,记录扇区数 0
;36 1 中断13的驱动器号 0
;37 1 表使用 0
;38 1 扩展引导标记(29h) 0x29
;39 4 卷序列号 0
;43 11 卷标 '***********'(任意11字节)
;54 8 文件系统类型 'FAT12 '(8字节)
;62 448 引导代码 引导代码
;510 2 510:0x55 511:0xaa 0xaa55
;----------------------------------------------------------------------------------
注:最后两字节的结束标志必不可少(少了它计算机将不能将它识别为引导区),事实上FAT12磁盘头可以没有,但这样系统将无法正常访问软盘映像。
那么接下来就开始写引导代码吧
ORG 0x7c00
jmp short LABEL_START ; Start to boot.
nop ; 这个 nop 不可少
; 下面是 FAT12 磁盘的头
BS_OEMName DB 'aby-tec ' ; OEM String, 必须 8 个字节
BPB_BytsPerSec DW 512 ; 每扇区字节数
BPB_SecPerClus DB 1 ; 每簇多少扇区
BPB_RsvdSecCnt DW 1 ; Boot 记录占用多少扇区
BPB_NumFATs DB 2 ; 共有多少 FAT 表
BPB_RootEntCnt DW 224 ; 根目录文件数最大值
BPB_TotSec16 DW 2880 ; 逻辑扇区总数
BPB_Media DB 0xF0 ; 媒体描述符
BPB_FATSz16 DW 9 ; 每FAT扇区数
BPB_SecPerTrk DW 18 ; 每磁道扇区数
BPB_NumHeads DW 2 ; 磁头数(面数)
BPB_HiddSec DD 0 ; 隐藏扇区数
BPB_TotSec32 DD 0 ; 如果 wTotalSectorCount 是 0 由这个值记录扇区数
BS_DrvNum DB 0 ; 中断 13 的驱动器号
BS_Reserved1 DB 0 ; 未使用
BS_BootSig DB 29h ; 扩展引导标记 (29h)
BS_VolID DD 0 ; 卷序列号
BS_VolLab DB 'aby-tec ' ; 卷标, 必须 11 个字节
BS_FileSysType DB 'FAT12 ' ; 文件系统类型, 必须 8个字节
LABEL_START:
mov ax, cs
mov ds, ax
mov es, ax
Call DispStr ; 调用显示字符串例程
jmp $ ; 无限循环
DispStr:
mov ax, bootMessage
mov bp, ax ; ES:BP = 串地址
mov cx, bootMassageEnd-bootMassage ; CX = 串长度
mov ax, 01301h ; AH = 13, AL = 01h,准备后面的10号中断调用
mov bx, 000ch ; 页号为0(BH = 0) 黑底红字(BL = 0Ch,高亮)
mov dl, 0
int 10h ; 调用10号中断
ret
bootMessage:
db "Hello, aby-tec!" ;显示内容
bootMassageEnd:
db 0x0a ;换行,bootMassage的结束标志
times 510-($-$$) db 0 ; 填充剩下的空间,使生成的二进制代码恰好为512字节
dw 0xaa55 ; 结束标志
;10中断ah=13 显示字符串
;ES:BP = 串地址
;CX = 串长度
;DH, DL = 起始行列
;BH = 页号
;AL = 0,BL = 属性 -光标返回起始位置 串:Char,char,……,char
;AL = 1,BL = 属性 -光标跟随移动 串:Char,char,……,char
;AL = 2 -------------光标返回起始位置 串:Char,attr,……,char,attr
;AL = 3 -------------光标跟随串移动 串:Char,attr,……,char,attr
一般在引导区都会将加载器读到内存之中,并将cpu控制权交给加载器,不过现在只是测试就不管那么多了。
接下来就来测试一下吧。
写好代码保存为boot.asm;打开cmd转到工作目录下;使用nasm编译boot.asm:nasm boot.asm -o boot.bin;
用winimage制作一个空的软盘映像abytec.img(用winimage制作的软盘映像后缀为.ima改为.img即可);
用FloppyWriter将boot.bin写入abytec.img;在vBox新建一个虚拟机,并在虚拟机上添加软盘控制器,然后添加虚拟软盘abytec.img;
可以看到它成功显示了"Hello, aby-tec!"。软盘启动就到这里,之后再讲虚拟硬盘启动。
转载自:
https://blog.csdn.net/lingxufire/article/details/79934856