详细注释GetFATEntry(转载)
转载与http://daikof622.wordpress.com/2009/12/18/%E6%B3%A8%E9%87%8Agetfatentry/
花了将近两天的时间,反复比对书上的概念和网上前辈们的总结,总算把这段代码给搞清楚了。(这里使用的是FAT12软盘结构)
函数GetFATEntry。参数存放在ax寄存器中,表示一个簇号。输出结果是该簇号在FAT表中的FATENTRY,它的内容仍然是一个簇号,表示文件下一部分所在簇的簇号。这里要仔细地体会“簇号”和“簇”之间的差别,否则在看代码的时候,很容易就会迷失。“簇”表示一个或多个扇区的集合。FAT12中,一个簇就是一个扇区,512字节。簇号,从软盘的数据区开始,从2开始编号(0,1为系统使用),本质上是一个基于FAT表的索引。
GetFATEntry:
push es
push bx
;函数中使用到了es和bx所以要进行保存,保存在栈上。
;es:bx会被函数ReadSector所使用,是int 13h所要求的,指向了一个缓冲区,保存从软盘读进来的数据。
push ax
mov ax, BaseOfLoader
sub ax, 0100h
;以上在BaseOfLoader之后留出4KB空间。为什么明明是0100h(256),怎么说是4K?
;因为这是个段基址,0100h还要乘上个16。
mov es, ax
pop ax
mov byte [bOdd], 0
mov bx, 3
mul bx
mov bx, 2
div bx
cmp dx, 0
jz LABEL_EVEN
mov byte [bOdd], 1
;以上部分是整个函数的难点所在,用户计算簇号在FAT表中所对应的FATENTRY相对于FAT首地址的偏移。
;从书上可以得知,FAT12中每个FATENTRY是12位的。所以如下:
7654 | 3210(byte1) 7654|3210(byte2) 7654|3210(byte3)
byte1和byte2的低4位表示一个Entry;根据Big-Endian,Entry内容为:3210(byte2)76543210(byte1)
byte3和byte2的高4位表示一个Entry;根据Big-Endian,Entry内容为:76543210(byte3)7654(byte2)
所以这里存在一个奇偶数的问题,以字节为单位。以上为例,Entry0偏移为0,Entry1偏移为1,Entry2偏移为3。
以INT[“簇号”*1.5]的方式增加。这也就是为什么上面先乘3再除2来计算。
根据DIV指令规定,商保存在ax中,余数在dx中。所以此时ax就是FATENTRY在FAT中以字节为边界的偏移量。
——————————————————————————————–
LABEL_EVEN:
xor dx, dx
mov bx, [BPB_BytsPerSec]
div bx
;dx:ax/BPB_BytsPerSec,所以ax现在是扇区的个数,dx是在最后一个扇区中的偏移。
push dx
mov bx, 0
;es:bx指向了目标空间的首地址,就是函数开始在BaseOfLoader之后留出的4KB空间。
add ax, SectorNoOfFAT1
;SectorNoOfFAT1是FAT1的相对扇区号,物理上就是0面0道1扇区。FAT12有两个完全一样的FAT表,FAT1和FAT2。
mov cl, 2
;cl总保存ReadSector函数的参数,表示要连续读入2个扇区。另一个参数ax在前面已经给出。
call ReadSector
pop dx
add bx, dx
;在add之前,bx为目标空间的首地址,其中内容是包含FATEntry的扇区。bx+dx就定位到了该FATEntry。
mov ax, [es:bx]
;ax中为es:bx指向的空间的内容。
cmp byte [bOdd], 1
;是奇数的簇号还是偶数的簇号??
jnz LABEL_EVEN_2
shr ax, 4
;7654 | 3210(byte1) 7654|3210(byte2) 7654|3210(byte3)
根据上面这个例子,奇数的簇号,1,偏移为1,所以读要ax中的时候,因为ax是16位,所以根据Big-Endian,ax的内容为7654|3210(byte3)|7654|3210(byte2),所以右移4位就可以了。
偶数簇号,0,偏移为0,读入ax后,ax的内容为7654|3210(byte2)7654 | 3210(byte1),我们只需要低12位即可,
所以and ax,0FFFh。
——————————————————————————————–
LABEL_EVEN_2:
and ax, 0FFFh
LABEL_GET_FAT_ENRY_OK:
pop bx
pop es
ret