在Blog<自己动手写操作系统>2011031601中把编译好的bin写出到虚拟软驱中,在启动虚拟机以软驱启动,能出现:hello ,OS world!
重新启动另一虚拟器(已装Xp),以虚拟机默认启动进入到Xp,双击软驱,会出现磁盘需要格式化的问句
这里要涉及到一个概念:文件系统
FAT12文件系统
FAT(File Allocation Table)文件系统规格在20世纪70年代末和80年代初形成,是微软的MS-DOS操作系统使用的文件系统格式,主要有:FAT12,FAT16,FAT32
FAT文件系统的主要信息,都被提供在前几个扇区内,其中第0号扇区尤其重要。这个扇区隐藏了一个叫做BPB(BIOS Parameter Block)的数据结构,一旦我们把这个数据结构谢对了,格式化过程基本完成了。
引导扇区是软盘的第0个扇区,在这个扇区中有一个很重要的数据结构叫BPB(BIOS Parameter Block),下面是引导扇区格式,其中BPB_开头的属于BPB,以BS_开头的只是BOOT Sector的一部分,不属于BPB。
名称 | 开始字节 | 长度 | 内容 | 参考值 |
BS_jmpBOOT | 0 | 3 | 一个短跳转指令 | jmp SHORT Label_07c00H nop |
BS_OEMName | 3 | 8 | 厂商名 | 'HHHHHHHH' |
BPB_BytesPerSec | 11 | 2 | 每扇区字节数(Bytes/Sector)单位字节Byte | 0x200=512 |
BPB_SecPerClus | 13 | 1 | 每簇扇区数(Sector/Cluster)应为2的幂,FAT12为1 | 0x1 |
BPB_ResvdSecCnt | 14 | 2 | Boot记录占用多少扇区,保留扇区,FAT12/16应为1 | 0x1 |
BPB_NumFATs | 16 | 1 | 共有多少FAT表,FAT结构数目,一般为2 | 0x2 |
BPB_RootEntCnt | 17 | 2 | 根目录区文件最大数,FAT12为224 | 0xE0=224 |
BPB_TotSec16 | 19 | 2 | 扇区总数,1.44M软盘为2880 | 0xB40[2*80*18]=2880 |
BPB_Media | 21 | 1 | 介质描述符,1.44M软盘为F0H | 0xF0 |
BPB_FATSz16 | 22 | 2 | 每个FAT表所占扇区数,9 | 0x9 |
BPB_SecPerTrk | 24 | 2 | 每磁道扇区数(Sector/track),18 | 0x12 |
BPB_NumHeads | 26 | 2 | 磁头数(面数),2 | 0x2 |
BPB_HiddSec | 28 | 4 | 隐藏扇区数 | 0 |
BPB_TotSec32 | 32 | 4 | 如果BPB_TotSec16=0,则由这里给出扇区数 | 0 |
BS_DrvNum | 36 | 1 | INT 13H的驱动器号,0为软盘 | 0 |
BS_Reserved1 | 37 | 1 | 保留,未使用 | 0 |
BS_BootSig | 38 | 1 | 扩展引导标记(29h) | 0x29 |
BS_VolID | 39 | 4 | 卷序列号 | 0 |
BS_VolLab | 43 | 11 | 卷标 | 'Solrex 0.01' |
BS_FileSysType | 54 | 8 | 文件系统类型 | 'FAT12 ' |
引导代码及其他内容 | 62 | 448 | 引导代码及其他数据 | 引导代码(剩余空间用0填充) |
结束标志0xAA55 | 510 | 2 | 第510字节为0x55,第511字节为0xAA | 0xAA55 |
整理一份完整的代码:
org 07c00h ; 告诉编译器程序加载到7c00处
jmp SHORT Main
nop
BS_OEMName:db "HHHHHHHH"
BPB_BytePerSec:dw 512
BPB_SecPerCluster:db 1
BPB_ResvdSecCnt:dw 1
BPB_NumFATs:db 2
BPB_RootEntCnt:dw 224
BPB_TotSec16:dw 2880
BPB_Media:db 0xf0
BPB_FATSz16:dw 9
BPB_SecPerTrk:dw 18
BPB_NumHeads:dw 2
BPB_HiddSec:dd 0
BPB_TotSec32:dd 0
BS_DrvNum:db 0
BS_Reserved1:db 0
BS_BootSig:db 29h
BS_VolID:dd 0
BS_VolLab:db "Solrex 0.01"
BS_FileSysType:db "FAT12 "
Main:
mov ax, cs
mov ds, ax
mov es, ax
call DispStr ; 调用显示字符串例程
jmp $ ; 无限循环
DispStr:
mov ax, BootMessage
mov bp, ax ; ES:BP = 串地址
mov cx, 16 ; CX = 串长度
mov ax, 01301h ; AH = 13, AL = 01h
mov bx, 000ch ; 页号为0(BH = 0) 黑底红字(BL = 0Ch,高亮)
mov dl, 0
int 10h ; 10h 号中断
ret
BootMessage: db "Hello, OS world!"
times 510-($-$$) db 0 ; 填充剩下的空间,使生成的二进制代码恰好为512字节
dw 0xaa55 ; 结束标志
PS:特别注意第二句,应该是jmp SHORT Main,而不是jmp Main.如果按此书中所写jmp Main,最后编译出来是4个字节,比预计要多1个字节,原因在于反编译bin那句话成了jmp word 0x????