上一章节解析了boot.asm文件,这个文件包含了两个Inc文件,base_phy.inc及filesystem.inc,均在我们的include文件夹下。
同时这两个 文件在前面 已经提供了代码,大家可以到http://blog.youkuaiyun.com/b06030927/article/details/75269497处取代码(
DD系统构建-MBR(5)加载loader文件
)。base_phy.inc里面定义了一些基础模块的内存起始地址,比如我们的boot, loader,及后面的kernel,页表等。这个文件都是一些宏值定义,非常容易理解。
MACRO_BOOT_ADDR equ 0x7c00
MACRO_BOOT_LEFT_START_SECTOR equ 4096
MACRO_BOOT_LEFT_START_ADDR equ MACRO_BOOT_ADDR+512
MACRO_LOADER_ADDR equ 0x10000
MACRO_KERNEL_ADDR equ 0x500000
MACRO_GDT_ADDR equ 0x8000
MACRO_PAGEDIR_ADDR equ 0x20000
MACRO_PAGETBL_ADDR equ 0x21000
重点是我们的filesystem.inc文件,这个文件包括两部分:文件系统常量定义、文件系统 内容读取操作定义(文件参考http://blog.youkuaiyun.com/b06030927/article/details/75269497)
1-18行,分别定义了我们的文件系统 内各个内容所有的扇区信息,包括文件系统块区扇区1,占用一个扇区; 扇区位图在扇区2, inodebitmap在扇区3,均占用一个扇区; inodeinfo起始扇区为4,占用512个扇区;文件列表起始扇区为516, 占用32个扇区;文件系统区在这里结束,后面是用户数据 区;用户数据区起始扇区为548,占用3548个扇区;再超出这个扇区暂时没有分配(实际上也用 了,我们前一章节的分段boot还记得不,就偷偷的用了4096之后 的扇区,只是这些扇区用户无法感知)
20-24行:定义了文件系统块区的相关信息,包括占用的大小,每个扇区偏移表示 的含义,这里要和工具里面的定义一致。实际它是按照tools/ddfs.h翻译过来的。
比如在我们的ddfs.h中定义的数据如下(http://blog.youkuaiyun.com/b06030927/article/details/73050529 D_D系统构建-文件写入方法):
27-31行:定义了Inode信息区的内容,包括信息区大小,各个字段的偏移,这个定义同上面的系统块一样,与ddfs.h结构对应,如下:
23-35行:定义了文件列表区信息,包括信息区大小,各个字段的偏移,这个定义同上面的系统块一样,与ddfs.h结构对应,如下:
38行定义了Inode数目,4096 , 41行预留了人全局数据 区,看大小也应该能猜到这是用来干嘛的(用来保存里面临时读取的一个扇区内容)
从43行开始,定义了相关的文件系统内容的读取,我们分函数来描述。
getDiskDataFromSectors
这个函数应该很眼熟了,没错,它和boot.asm里面的getDataFromSectors函数一模一样的。这里重新命名了下,原因简单,首先这个文件里面读取扇区需要,其次,我们不好直接访问boot.asm里面的接口,这个文件是提供公共文件系统访问的。
getSystemBlockData
这个用来 读取我们的文件系统区,实际就是从扇区1读取一个扇区到指定的缓存中。
getInodeBitMapData
获取inodebitmap数据到用户指定的内存区域,实际就是读扇区3的一个扇区。实现和上面读取系统块一样。
getInodeInfoByInodeIndex
这个函数用来 获取指定inode索引对应的inodeinfo内容,这个比较重要。
212-219行:根据当前的索引值(保存在ax),先计算总共偏移的字节数(212-215),然后除以一个扇区大小(217-218),这样可以得到扇区偏移值(ax),及扇区内偏移值(dx),再配合Inodeinfo起始扇区,可以定位到它在磁盘中的位置(219)。
221-230行:根据得到的扇区值,调用getDiskDataFromSectors来得到本扇区的值 ,这里面扇区值保存到上面申请的全局数据globalSectorSpace中;
232-255行:将对应的inodeinfo信息拷贝到用户区中。由于此时 取出的是整个扇区的信息,我们只需要获取我们需要的inodeinfo值,它的偏移保存在dx中。涉及到拷贝,我们会改变现存的ds/es值,因此要先保存起来(233-234),然后将用户相对globalSectorSpace的偏移地址依次赋值给ds/si这两个 寄存器(236-243);245行获取用户内存区,将其赋值为es/di; 设置重复次数为inodeinfo大小。执行rep指令,该指定会重复执行movsb,完成将ds/si内容拷贝到es/di中;
257-263行:恢复数据,调用结束。
getFileSectorListBySector:
这个函数用来获取指定扇区对应的扇区列表信息,这个用来检查是否还存在下一个扇区,它的实现与上面的获取inodeinfo一样,不再重复介绍。
checkFileNameIsSame
这个函数用来 比较用户输入的文件名是否也inodeinfo中的文件名相同;
356-370行:将用户输入文件名内存地址与inodeinfo内存分别赋值给ds/si, es/di;
372-374行:比较文件名是否相同,这里面使用的repz cmpsb; 如果cmpsb发现ds/si与es/di里面的值不相同,则会设置z标志非0,那么repz会结束,此时cx肯定是小于文件名长度的;反之,如果cx等于文件名长度,则表示字符都相同,如果相同,则在file_name_same和设置返回值 为1, 并返回。否则设置返回值为0.由于在374行用了repz cmpsb,修改了ds/es,因此需要先保存ds/es,在完成后再恢复。