【原创】:《一个操作系统的实现》书中的一处思考:P129页,84行之:and di,0fff0h 2011年4月

《一个操作系统的实现》是本好书,奇书,读了一点点,发现了点点疑惑

                                                                   /xichen

这学期在上嵌入式课程,老师在讲boot loader的时候让看于渊的那本《一个操作系统的实现》(第一版叫自己动手写操作系统),买了一本,翻看了下果然是宝贝,一口气读了2章,在看第4,5章的时候关于laoder问题的时候,也就是在第四章就出现的那个寻找文件,然后拷贝文件的时候,代码如下:

 

and di, 0FFF0h ; di -> 当前条目的开始

 push eax

 mov eax, [es : di + 01Ch] ;01ch=26---->DIR

 mov dword [dwKernelSize], eax ; / 保存 KERNEL.BIN 文件大小

 pop eax

 

 add di, 01Ah ; di -> 首 Sector //1Ah = 26---->DIR_frsclus

 mov cx, word [es:di]

 push cx ; 保存此 Sector 在 FAT 中的序号

 add cx, ax

 add cx, DeltaSectorNo ; cl <- KERNEL.BIN 的起始扇区号(0-based)

 mov ax, BaseOfKernelFile

 mov es, ax ; es <- BaseOfKernelFile

 mov bx, OffsetOfKernelFile ; bx <- OffsetOfKernelFile

 mov ax, cx ; ax <- Sector 号

 

 LABEL_GOON_LOADING_FILE:

 push ax ; `.

 push bx ; |

 mov ah, 0Eh ; | 每读一个扇区就在 "Loading " 后面

 mov al, '.' ; | 打一个点, 形成这样的效果:

 mov bl, 0Fh ; | Loading ......

 int 10h ; |

 pop bx ; |

 pop ax ; /

 

 mov cl, 1

 call ReadSector ;//读扇区函数

 pop ax ; 取出此 Sector 在 FAT 中的序号

 call GetFATEntry

 cmp ax, 0FFFh ;//判断有没有别的扇区了 0xfffh

 jz LABEL_FILE_LOADED

 push ax ; 保存 Sector 在 FAT 中的序号

 mov dx, RootDirSectors

 add ax, dx

 add ax, DeltaSectorNo

 add bx, [BPB_BytsPerSec]

 jmp LABEL_GOON_LOADING_FILE

 LABEL_FILE_LOADED:

 

 call KillMotor ; 关闭软驱马达

 

 mov dh, 1 ; "Ready."

 call DispStr ; 显示字符串

 

 jmp $

 

 

 

网上有很多关于标识红色的代码的争论:and di,0fff0h;的争论,我也争论下:

 

首先我们看这句话什么意思,读起来很简单就是 di低5位置0,这样子就使di是32的整数倍了,为什么是32?因为我们在寻找kernel.bin的时候,是从根目录一项项寻找的,而一项就是32byte;

 

那么我们看下是怎么寻找kernel.bin, 首先到根目录区第一项比对前11个字节,为什么是11字节?因为前11字节是DIR_Name,顾名思义,8个字节文件名,扩展民3个字节;

 

 那么我们寻找,首先我们让di指向根目录的首项(要不,就把它想成指针吧),然后比对11个字节,如果是了,那就找到了,如果不是呢?那就让di加32?不是,我们首先应该让di指回开始的位置,然后呢再加32就到了下个目录区:

 

and di,0ffe0h;

 

add di,20h;

 

第一句话就把之前比对的11字节对di的影响而消除了,然后再加32,就这样的找法,知道之后就跳到上面的很多代码的地方了。

 

 

 

好,那我们来看关于争议的地方:and di,0fff0h;和and di ,0ffe0h;

 

0fff0h: 1111 1111 1111 0000;   offe0h:1111 1111 1110 0000;

 

它们之间的区别就在倒数第五位,一个是保持,一个是置零;

 

而之前我们分析了di的操作:也就是那个11和32;

 

我们可以认为;di =32n+x;  0<=x<=11;

 

11: 0000 1011;di在一个目录项中,最多是di+11,而11根本不会影响倒数第5位,

 

如果没找到,and di ,offe0;又把之前的加的x又消除了,同样倒数第5位没变化;

 

加32的过程,实际上就是加 100 0000;对倒数第5位也是没有影响;

 

那么到这里,我或许可以下个结论,如果开始时执行了倒数第5位清零的操作,后面这个位一直是0;

 

结论:执行and di,0fff0h,和 and di ,0ffe0h;实际上没有区别的;

 

完!

posted @ 2012-04-28 19:46  xichen  阅读(382)  评论(0编辑  收藏  举报