专注于操作系统27之对GetFATEntry函数的理解

来源:互联网 发布:小学生口语打分软件 编辑:程序博客网 时间:2024/03/29 10:31

       在《自己动手写操作系统》的第四章中作者给出了这个函数。作者说这个函数的输入是扇区号,输出是其对应的fat项的值。我觉得说函数的输入是扇区号让人会产生疑惑,说函数的输入是Sector在FAT中的序号更恰当,在源代码中作者也是这么注释的。还有就是函数中有区别对待ax是奇数还是偶数。ax的值是Sector在FAT中的序号。这个函数的目的是根据这个序号,得到该序号所对应的fat项的值。一个fat项占1.5个字节。Sector在FAT中的序号是从0开始的。

      当Sector在FAT中的序号是偶数时,假设为0(其实序号0在FAT是不会用的,但为了说明简单,其它偶数也是一样的)。下面给出一张图,图中fat0表示序号为0的fat项,ax是16位的,它存放了两个字节,而fat值是1.5个字节,即12位的,所以我们要把其它的四位置为0,当序号是偶数时,其它四位是ax中的高四位(源代码中是and ax,0fffh).

图中被红线划掉的部分表示不需要的4位。




      当Sector在FAT中的序号为奇数时,假设为1(其实序号1在FAT是不会用的,但为了说明简单,其它奇数也是一样的)。下面给出一张图,图中fat1表示序号为1的fat项,ax是16位的,它存放了两个字节,而fat值是1.5个字节,即12位的,所以我们要把其它的四位置为0,当序号是奇数时,其它四位是ax中的低四位(源代码中是shr ax,4).

图中被红线划掉的部分表示不需要的4位。


下面是该函数的源代码

;----------------------------------------------------------------------------; 函数名: GetFATEntry;----------------------------------------------------------------------------; 作用:;找到序号为 ax 的 Sector 在 FAT 中的条目, 结果放在 ax 中;需要注意的是, 中间需要读 FAT 的扇区到 es:bx 处, 所以函数一开始保存了 es 和 bxGetFATEntry:pushespushbxpushaxmovax, BaseOfLoader        ; ┓subax, 0100h; ┣ 在 BaseOfLoader 后面留出 4K 空间用于存放 FATmoves, ax; ┛popaxmovbyte [bOdd], 0movbx, 3mulbx; dx:ax = ax * 3movbx, 2divbx; dx:ax / 2  ==>  ax <- 商, dx <- 余数cmpdx, 0jzLABEL_EVENmovbyte [bOdd], 1   ;表示ax为奇数LABEL_EVEN:;偶数xordx, dx; 现在 ax 中是 FATEntry 在 FAT 中的偏移量. 下面来计算 FATEntry 在哪个扇区中(FAT占用不止一个扇区)movbx, [BPB_BytsPerSec]divbx; dx:ax / BPB_BytsPerSec  ==>ax <- 商   (FATEntry 所在的扇区相对于 FAT 来说的扇区号);dx <- 余数 (FATEntry 在扇区内的偏移)。pushdxmovbx, 0; bx <- 0于是, es:bx = (BaseOfLoader - 100):00 = (BaseOfLoader - 100) * 10haddax, SectorNoOfFAT1; 此句执行之后的 ax 就是 FATEntry 所在的扇区号movcl, 2callReadSector; 读取 FATEntry 所在的扇区, 一次读两个, 避免在边界发生错误, 因为一个 FATEntry 可能跨越两个扇区popdxaddbx, dxmovax, [es:bx]cmpbyte [bOdd], 1  ;比较是否为奇数,如果不是则转到LABEL_EVEN_2jnzLABEL_EVEN_2shrax, 4      ;为奇数时LABEL_EVEN_2:     ;为偶数时andax, 0FFFhLABEL_GET_FAT_ENRY_OK:popbxpopesret;----------------------------------------------------------------------------