一个操作系统的实现笔记:加载Loader进入内存

       一个操作系统从开机到开始运行,大致经历“引导→加载内核入内存→跳入保护模式→开始执行内核”这样一个过程。也就是说,在内核开始执行之前不但要加载内核,而且还有准备保护模式等一系列工作,如果全都交给引导扇区来做,512字节很可能是不够用的,所以,不妨把这个过程交给另外的模块来完成,我们把这个模块叫做Loader。

       引导扇区负责把Loader加载入内存并且把控制权交给它,其他工作放心地交给Loader来做,因为它没有512字节的限制,将会灵活得多。

一、准备工作

1.FAT12各区分布

       引导扇区和Loader肯定是存在磁盘或软盘中,这里我们存在软盘中,并且使用的是FAT12文件系统,软盘中各分区的分布情况:
在这里插入图片描述
       引导扇区位于磁盘的0柱面,0磁头,1扇区,在这个扇区中有一个很重要的数据结构叫做BPB(BIOS ParameterBlock)。关于FAT12的引导扇区和根目录区可以参考:FAT12引导扇区格式及根目录区条目格式其中就有对BPB各项的描述。

2.数据区位置计算

       数据区的第一个扇区的位置可以通过计算根目录所占的扇区数得到。具体公式是:

RootDirSector = BPB_RootEntCnt×32÷BPB_BytsPerSec

       这是余数为零的情况下,如果余数不为零,则根目录扇区数:

RootDirSector = BPB_RootEntCnt×32÷BPB_BytsPerSec+1

       RootDirSector就是要计算的根目录区扇区数由FAT12引导扇区格式及根目录区条目格式中对BPB的介绍可以知道,BPB_RootEntCnt是根目录区条目数最大值,每个条目32字节,BPB_BytsPerSec是每扇区字节数。

3.FAT表

       虽然由此可以找到文件,但是还不够,因为有的文件大于512字节(一个扇区512字节),超过512字节的内容我们需要根据FAT表找到。FAT表在引导扇区和根目录区之间,FAT表有两个,FAT2可看做是FAT1的备份,它们通常是一样的。

其中,每12位称为一个FAT项(FATEntry),代表一个簇。第0个和第1个FAT项始终不使用,从第2个FAT项开始表示数据区的每一个簇,也就是说,第2个FAT项表示数据区第一个簇,以此类推。

       说到这里好像还没说清FAT表的具体功能,对于FAT表的具体功能后面再说,下面先来说说怎么辨认FAT表的每一项,我第一次看的时候还真没看懂。

       假设下面是一组FAT表的表项:
       0000200: F0 FF FF FF 8F 00 09 A0 00

       因为FAT表的第0和第1项始终不使用,所以前三个字节不用管它。以第2、3表项为例(FF 8F 00),3个字节包含了两个FAT表表项,第2个表项的低8位就是第一个字节,即FF;第2个表项的高4位就是第二个字节的低4位,也就是F,所以第2个表项的值为0xF FF。而第3个表项的低4位就是第二个字节的高4位,即8,第3个表项的高8位就是第3个字节,即00,所以第3个表项的值为0x00 8;以此类推,第四个表项的值就是0x0 09,第五个表项的值为0x00 0。

       然后再说说FAT表项的值的功能:FAT项的值代表的是文件下一个簇号,但如果值大于或等于0xFF8,则表示当前簇已经是本文件的最后一个簇。如果值为0xFF7,表示它是一个坏簇。

       根目录条目中有一项是DIR_FstClus,这个条目对应的是文件的开始簇号,即在数据区中的簇号,同时它也对应了FAT表中的项,如果FAT表项的值小于0xFF8,则此值对应的就是文件的下一个簇号和FAT表的下一个表项。举个例子:假如一个长一点的文件FLOWER.TXT,它的DIR_FstClus值为3,对应第3个FAT项。此FAT项值为0x008,也就是说,这个簇不是文件的最后一个簇,下一个簇号为8。我们再找到第8个FAT项,发现值为0x009,接下来第9个FAT项值为0x00A,第0xA个FAT项值为0xFFF。所以,FLOWER.TXT占用了第3、8、9、10,共计4个簇。

二、写入过程

       要加载Loader肯定要先找到Loader,我们规定Loader放在根分区也就是根目录中,所以从跟分区的第一个分区开始找,比较每个分区第一个条目(Loader的名称)是不是“LOADER BIN”,如果找到,就将LOADER.BIN的起始扇区号加载入内存,在此之前,将此扇区在FAT表中的序号入栈。起始扇区加载完后,将其扇区在FAT表中的序号出栈,然后计算出FAT表项的值,将此值和“0FFFh”比较,相等的话说明此簇是文件的最后一个簇之前说只要fat表项值大于等于0FF8h就说明此簇是文件的最后一个簇,所以为什么要和0FFFh比较呢,我在网上搜了相关资料,fat12的fat表文件结束簇是0FF8h~0FFFh,所以我将代码改了一下:

	cmp	ax, 0FFFh
	jz	LABEL_FILE_LOADED

改为

	cmp	ax, 0FF8h
	jnb	LABEL_FILE_LOADED

运行结果都一样,但是改为

	cmp	ax, 0FF8h
	jz	LABEL_FILE_LOADED

就不行,所以我认为判断此簇是否文件最后一个簇fat表项的值应比较到0FFFh。

       本来想在解释一下代码的,但是代码太多,解释起来又麻烦,又得写好长,就算写好了,这么长的文章也很难让人耐着性子去看,所以决定关于代码另写几篇博客,这里就不在多说。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值