全面剖析《自己动手写操作系统》第四章

上一节我们已经详细介绍了FAT12文件系统的数据结构,下面我们需要思考的是两个问题:1、引导扇区通过怎样的步骤才能找到文件;2、如何能够把文件内容全都读出来并加载进入内存。

下面我们先解决第一个问题:

1、 如何读取软盘?

(1)我们需要使用BIOS中断int 13h来读取软盘。它的用法如下表所示:

在这里我们只介绍了2种工作方式,中断int 13h还有其他的工作方式,如果需要可以自行查看内容。

(2)由上表我们可以知道:当读取某些扇区时,需要柱面(磁道)号(ch),起始扇区号(cl),磁头号(dh)。我们如何通过计算得到这些数据呢?

(3)现在万事俱备只欠东风了,下面我们就书写读取软盘扇区的函数ReadSector。

首先我们要知道该函数需要什么参数,这些参数存储在什么位置?

参数1:扇区号,存储在ax中

参数2:要读取扇区的个数,存储在cl中

参数3:数据缓冲区,即读取扇区数据后,将其存储在什么位置,用es:bx指向该缓冲区。

即函数的作用:从第ax个Sector开始,将cl个Sector读入es:bx中。

;———————————————————————–;函数名:ReadSector;——————————————————;作用:从第ax个Sector开始,将cl个Sector读入es:bx中ReadSector:;———————————————;怎样由扇区号求扇区在磁盘中的位置(扇区号->柱面号,起始扇区,磁头号);———————————————;设扇区号为x;┌ 柱面号 = y >> 1;x┌ 商 y ┤; ————– => ┤└ 磁头号 = y & 1; 每磁道扇区数│;└ 余 z => 起始扇区号 = z + 1;辟出两个字节的堆栈区间保存要读取的扇区数:byte[bp-2]push bpmov bp, spsub esp, 2mov byte[bp-2], cl;将参数cl,存储在byte[bp-2],将要读取扇区的个数。push bx;保存bx,因为下面要使用bx进行计算。mov bl, [BPB_SecPerTrk];bl:除数=18;ax存储的是扇区号,bl是每磁道扇区数,执行ax/bl=al—-ah,;即商y在al中,商z在ah中。div blinc ah;ah(z)++,即起始扇区号=z+1,mov cl, ah;将ah值赋值给cl,中断int 13h中,cl保存的恰好是起始扇区号mov dh, al;将al(y),赋值给dhshr al, 1;对al(y)进行右移一位,即得到柱面号=y>>1,mov ch, al;然后将al赋值给ch,在中断int 13h中,ch保存着柱面(磁道)号and dh, 1;将dl(y)进行&1运算,即得到磁头号=y&1,在中断int 13h中,dh保存着;磁头号pop bx;恢复bx值;到此为止,“柱面(磁道)号(ch),起始扇区号(cl),磁头号(dh),缓冲地址(es:bx)”全部准备就绪mov dl, [BS_DrvNum];在中断int 13中,dl保存着驱动器号。此时dl=[BS_DrvNum]=0.GoOnReading:;下面对ah,al进行赋值,ah=2,al=要读取的扇区数,前面将参数cl存储在byte[bp-2],现在从这里重新获取;并赋值给al。mov ah, 2mov al, byte[bp-2];中断int 13一切准备就绪,然后执行int 13int 13hjc.GoOnReading;如果读取错误,CF会被置为1,这时就不停地读,直到正确为止。add esp, 2;恢复堆栈pop bpret

2、 如何在软盘中寻找Loader.bin文件

(1)结合上一节所介绍的FAT12数据结构,从中我们可以知道,要寻找一个文件,首先需要在根目录区中寻找该文件的根目录条目;然后根据根目录条目获取文件开始簇数(也就是在数据区中存储的扇区);最后读取文件内容到内存。

(2)嗯,是的,下面就让我们来完成第一步—–在根目录区中寻找该文件的根目录条目。

让我们开始思考这个问题,

首先要知道根目录区的开始扇区号是19,也就是说从第19扇区开始,根目录区占用扇区总数为14,也就是说,如果不能发现Loader.bin,需要将14个扇区都进行查找,于是需要一个大的循环在外围,控制着扇区的读取。

紧接着,我们每读取一个扇区,一个扇区是512个字节,一个根目录条目占32个字节,故一个扇区中存在512/32=16个根目录条目,所以需要添加一个循环,控制根目录条目的变化,从0—16进行循环。

最后,针对每一个根目录条目,我们只是要比较文件名,一个根目录条目的文件名占用11个字节,所以需要对每一个字节与"LOADER BIN"中的每一个字节进行比较,所以还是要添加一个循环,来控制字符的变化,即从0—11.

用C语言来表示该问题就是:

for( i = 根目录区的起始扇区号(19); i < 根目录区占有的扇区数(14); i++) {

for( j = 0;j < 一个扇区内存储的根目录条目个数(512/32=16); j++) {

for(k =0; k < 根目录条目中文件名占用的空间(11个字符); k++) {

if(k=10)jmp LABEL_FILENAMEFOUND

if(ds:si= es:di) si++; di++;

这一生我只牵你的手,因为今生有你早已足够。

全面剖析《自己动手写操作系统》第四章

相关文章:

你感兴趣的文章:

标签云: