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

       在《自己动手写操作系统》的第四章中作者给出了这个函数。作者说这个函数的输入是扇区号,输出是其对应的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 和 bx
GetFATEntry:
	push	es
	push	bx
	push	ax
	mov	ax, BaseOfLoader        ; ┓
	sub	ax, 0100h		; ┣ 在 BaseOfLoader 后面留出 4K 空间用于存放 FAT
	mov	es, ax			; ┛
	pop	ax
	mov	byte [bOdd], 0
	mov	bx, 3
	mul	bx			; dx:ax = ax * 3
	mov	bx, 2
	div	bx			; dx:ax / 2  ==>  ax <- 商, dx <- 余数
	cmp	dx, 0
	jz	LABEL_EVEN
	mov	byte [bOdd], 1   ;表示ax为奇数
LABEL_EVEN:;偶数
	xor	dx, dx			; 现在 ax 中是 FATEntry 在 FAT 中的偏移量. 下面来计算 FATEntry 在哪个扇区中(FAT占用不止一个扇区)
	mov	bx, [BPB_BytsPerSec]
	div	bx			; dx:ax / BPB_BytsPerSec  ==>	ax <- 商   (FATEntry 所在的扇区相对于 FAT 来说的扇区号)
					;				dx <- 余数 (FATEntry 在扇区内的偏移)。
	push	dx
	mov	bx, 0			; bx <- 0	于是, es:bx = (BaseOfLoader - 100):00 = (BaseOfLoader - 100) * 10h
	add	ax, SectorNoOfFAT1	; 此句执行之后的 ax 就是 FATEntry 所在的扇区号
	mov	cl, 2
	call	ReadSector		; 读取 FATEntry 所在的扇区, 一次读两个, 避免在边界发生错误, 因为一个 FATEntry 可能跨越两个扇区
	pop	dx
	add	bx, dx
	mov	ax, [es:bx]
	cmp	byte [bOdd], 1  ;比较是否为奇数,如果不是则转到LABEL_EVEN_2
	jnz	LABEL_EVEN_2
	shr	ax, 4      ;为奇数时

LABEL_EVEN_2:     ;为偶数时
	and	ax, 0FFFh

LABEL_GET_FAT_ENRY_OK:

	pop	bx
	pop	es
	ret
;----------------------------------------------------------------------------


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值