《一个操作系统的实现》(四):让操作系统走进保护模式

来源:互联网 发布:一分钟心理学 知乎 编辑:程序博客网 时间:2024/05/29 19:04

一个操作系统从开机到开始运行,大致经历“引导->加载内核入内存->跳入保护模式->开始执行内核”这样一个过程。

几乎所有的文件系统都会把磁盘划分为若干层次以方便组织和管理,这些层次包括扇区(磁盘上的最小数据单元),簇(一个或多个扇区),分区(通常指整个文件系统)。

对于FAT12文件系统来说,第0号扇区为引导扇区,其中有一个叫做BPB(BIOS Parameter Block)的数据结构,格式如下表,其中BPB_开头的属于BPB,其余的只是引导扇区的一部分。

FAT12引导扇区的格式名称偏移长度内容Orange's的值BS_jmpBoot03一个短跳转指令jmp LABEL_START
nopBS_OEMName38厂商名'ForrestY'BPB_BytesPerSec112每扇区字节数0x200BPB_SecPerClus131每簇扇区数0x1BPB_RsvdSecCnt142Boot记录占用多少扇区0x1BPB_NumFATs161共有多少FAT表0x2BPB_RootEntCnt172根目录文件最大值0xE0BPB_TotSec16192扇区总数0xB40BPB_Media211介质描述符0xF0BPB_FATSz16222每FAT扇区数0x9BPB_SecPerTrk242每磁道扇区数0x12BPB_NumHeads262磁头数(面数)0x2BPB_HiddSec284隐藏扇区数0BPB_TotSec32324如果BPB_TotSec16是0,由这个值记录扇区数0BS_DrvNum361中断13的驱动器号0BS_Reserved1371未使用0BS_BootSig381扩展引导标记(29h)0x29BS_VolID394卷序列号0BS_VolLab4311卷标'OrangeS0.02'BS_FileSysType548文件系统类型'FAT12'引导代码及其他62448引导代码、数据及其他填充字符等引导代码(剩余部分被0填充)结束标志51020xAA550xAA55接下来扇区号1-9、10-18分别由两个完全相同的表(FAT1和FAT2)占用,接下来是根目录区(长度非固定,需计算),剩余的是数据区(截止到2879号)。

根目录区由若干个目录条目组成,每个条目占32字节,条目最多有BPB_RootEntCht个,即根目录区大小依赖于BPB_RootEntCht。
根目录区中的条目格式名称偏移长度描述DIR_Name00xB文件名8字节,扩展名3字节DIR_Attr0xB1文件属性保留位0xC10保留位DIR_WrtTime0x162最后一次写入时间DIR_WrtDate0x182最后一次写入日期DIR_FstClus0x1A2此条目对应的开始簇号DIR_FileSize0x1C4文件大小注意,数据区的第一个簇号是2,而不是0或1。

实际上,对于小于512字节的文件来说,FAT表用处不大,但如果文件大于512字节,就需要FAT表来找到所有的簇(扇区)。通常FAT项的值代表的是文件下一个簇号。还需要注意的是一个FAT项可能会跨越两个扇区。

引导扇区需要有BPB等头信息才能被识别,书上BPB的代码如下:

jmp short LABEL_START; Start to boot.nop; 这个 nop 不可少; 下面是 FAT12 磁盘的头BS_OEMNameDB 'ForrestY'; OEM String, 必须 8 个字节BPB_BytsPerSecDW 512; 每扇区字节数BPB_SecPerClusDB 1; 每簇多少扇区BPB_RsvdSecCntDW 1; Boot 记录占用多少扇区BPB_NumFATsDB 2; 共有多少 FAT 表BPB_RootEntCntDW 224; 根目录文件数最大值BPB_TotSec16DW 2880; 逻辑扇区总数BPB_MediaDB 0xF0; 媒体描述符BPB_FATSz16DW 9; 每FAT扇区数BPB_SecPerTrkDW 18; 每磁道扇区数BPB_NumHeadsDW 2; 磁头数(面数)BPB_HiddSecDD 0; 隐藏扇区数BPB_TotSec32DD 0; wTotalSectorCount为0时这个值记录扇区数BS_DrvNumDB 0; 中断 13 的驱动器号BS_Reserved1DB 0; 未使用BS_BootSigDB 29h; 扩展引导标记 (29h)BS_VolIDDD 0; 卷序列号BS_VolLabDB 'OrangeS0.02'; 卷标, 必须 11 个字节BS_FileSysTypeDB 'FAT12   '; 文件系统类型, 必须 8个字节  LABEL_START:

要加载一个文件如内存的话免不了要读软盘。这时候需要用到int 13h中断,此中断参数详见这篇文章。中断参数需要柱面号、磁头号、当前柱面上的扇区号三个分量,这三个分量的计算方法如下:

扇区号/每磁道扇区数(18),得商Q和余数R。柱面号为Q>>1,磁头号为Q&1,起始扇区号为R+1。

Loader要做的事情至少有两件:加载内核入内存;跳入保护模式。因为内核开始执行的时候一定在保护模式下。.COM的内核可以直接放入内存,但是ELF格式的内核不能直接放进内存(下一章会讲)。


---------------------

在编译生成boot.bin后,还需要这样做:首先用bximage生成一个软盘映像(直接执行bximage),然后执行如下命令

nasm loader.asm -o loader.bin

dd if=boot.bin of=a.img bs=512 count=1 conv=notrunc

sudo mount -o loop a.img /mnt/floppy/

sudo cp loader.bin /mnt/floppy/ -v

sudo umount /mnt/floppy/

原创粉丝点击