D_D系统构建-MBR(6)加载loader文件代码MBR解析

上一章节,我们把当前完成的代码都列出来,包括主体代码boot.asm, loader.asm , 还有两个 include文件: base_phy.inc, filesystem.inc; base_phy.inc之前已经介绍过,且都是定义了一些地址宏,不再重复介绍;loader.asm只是简单的显示 一句话,也比较简单。相比之下 , boot.asm, filesystem.inc文件比较复杂,我们分开介绍。

下面介绍下本次用到的boot.asm,它的流程抽象如下;

D_D系统构建-MBR(6)加载loader文件代码MBR解析_第1张图片


(1)根据mbr总长度,将剩余内容从4096扇区起始处加载到内存0x7e00处

对应 我们的13行到181行,这一点和之前 一样,进行改变。


(2)读取文件系统块区,检查Inode是否有占用,没有占用返回错误

D_D系统构建-MBR(6)加载loader文件代码MBR解析_第2张图片

D_D系统构建-MBR(6)加载loader文件代码MBR解析_第3张图片

182-199行,我们先定义了一此全局变量,这些在后面我们要用来显示字符串或者 保存数据, 

200-218行,检查Inode是否有占用;这一步在显示完loader尝试加载的信息后(203-209)就读取系统块区,这个对应的我们的扇区1.这里面我们把这个扇区内容保存以tempbuffer里面;读取后,检查相对tempbuffer偏移MACRO_DDFS_FILESYSTEM_SYSTEMBLOCK_OFFSET_USEDINODENUM(定义在filesystem.inc中,值为12),这是保存Inode已经使用的数目, 如果为0,就不需要处理,到这一步你就可以关机睡觉了。

由于我们已经用了这个inode来保存Loader。bin,所以这个数值会是1,这时218行不满足,继续执行下面的流程。


(3)读取Inodebitmap,从inode0开始搜索置位图中置1的位; 搜索结束没有找到Loader.bin提示错误

D_D系统构建-MBR(6)加载loader文件代码MBR解析_第4张图片

221-224行,读取inodebitmap内容到tempbuffer,后面我们要通过这个位图来得到哪个inode被使用。

226-244行,遍历整个tempbuffer,检查每一个位图是否被置位;如果遍历完整个位图都没有发现置位的,或者有置位的都不是Loader.bin,则跳转到loadernotdound(244行),否则跳到getinodeinfo处执行(240),这个分支的处理主要获取indoinfo,检查是否是loader.bin,注意当前已经置位的inodeindex是保存在ax中,后面处理时,注意保护这个寄存器


(4)根据置位的Inode,读取它所有的Inodeinfo信息

D_D系统构建-MBR(6)加载loader文件代码MBR解析_第5张图片

248-253行:主要来获取inodeinfo,使用保存在ax中的inodeindex,将inodeinfo值保存到tempinodeinfobuffer中,


(5)比较文件名是否为Loader.bin,如果不是,则返回(3)

对应上面的255-269行:根据上面获取到的tempinodeinfobuffer(保存的是inodeinfo值),连同保存“loader.bin”的loadername一起传入checkFileNameIsSame(对应行255-267),如果 文件名是一样的,则tempoutresult值 为1, 否则 值为0(268-269);这里如果值为0,表示当前Inode不是loader.bin的,则跳转到241行search_next_bit处,继续检查下一个索引;如果一样,则表示已经找到,继续下面的file_is_same流程。


(6)加载起始扇区内容到内存0x10000处,并读取扇区对应的filesectorlist信息

D_D系统构建-MBR(6)加载loader文件代码MBR解析_第6张图片

273-275:获取对应的起始扇区值 ,它相对tempinodeinfobuffer 的偏移为MACRO_DDFS_FILESYSTEM_INODEINFO_OFFSET_FILESTARTSECTOR,将起始扇区保存在ax中

277行:设置Loader.bin要加载的 内存地址,这个MACRO_LOADER_ADDR 实际为0x10000(base_phy.inc中定义)


(7)filesectorlist中指示还有下一个扇区,则读取下一个扇区内容到内存上一次结尾处;如果没有则跳转到0x10000处执行Loader

(8)再读取扇区对应的filesectorlist信息,重复步骤7

278-304:完成所有的loader.bin的内容查找及加载,

(1)279-287:完成当前扇区的加载,此时 ax保存扇区号,ebx保存内存起始地址,在第一次执行时这个ax为起始扇区值,ebx为0x10000;当然这并不是表示扇区已经加载 结束了,还要读取这个扇区对应的filesectorlist信息,检查是否还有下一个扇区。

(2)290-296:根据当前扇区来获取它对应的filesectorlist信息,这个信息里面会保存是否还存在下一个扇区,及下一个扇区的编号 。传入ax 当前扇区值,调用getFileSectorListBySector,将获取的文件扇区列表保存到tempbuffer中

(3)298-304:首先检查下下一个扇区是否存在,基于这个tempbuffer偏移MACRO_DDFS_FILESYSTEM_FILESECTORLIST_OFFSET_ISNEXTVALID就是保存的下一个扇区是否合法,如果是合法的,这个值是1,非法则为0;对于 非法的情况,表示已经没有下一个扇区了,loader.bin已经全部加载完毕,需要执行它的代码了(行300);否则 获取下一个扇区值(偏移MACRO_DDFS_FILESYSTEM_FILESECTORLIST_OFFSET_NEXTSECTOR, 行302), 将它赋值给ax,同时将内存地址ebx增加512,用来 保存下一个扇区内容,再跳转到上面的loader_all_loader执行扇区加载及下一扇区的判断(302-304);

这样通过 循环加载,循环判断,只到不存在下一个扇区后,所有的loader.bin内容加载完毕 ,就可以去执行Loader。bin内容了。


通上面的步骤,loader.bin已经可以运行了,此时 通过跳转到loader.bin空间执行即可 。记住,它的起始地址是0x10000

D_D系统构建-MBR(6)加载loader文件代码MBR解析_第7张图片

307-311行:用来计算0x10000对应的基地址及偏移,在保护模式下,段地址是实际 地址向右偏移4位的,实际 的物理地址=段地址*4+偏移地址, 

313-315行:将偏移地址与段基址分别保存到tempbuffer及tempbuffer+2处,这个顺序不能乱!!,然后执行Jmp far,这个指令依次取tempbuffer+2:tempbuffer到cs:ip中;至于用这个jmp far的原因是因为在实地址下,一人段的最长地址j64K,对应16进制0xFFFF,而我们的loader.bin是加载到0x10000的,已经超过mbr可访问的空间了。因此需要切换它的cs值,通过 far来完成cs的重新赋值。


还剩下这个317-327行未分析,这个317-324实际 是loadnotfound的调用,就是上面我们如果遍历完整个inodebitmap都找不到loader.bin时走到的分支。这个很简单,就打印个loader.bin不存在的错误,然后就挂在这里面(326行,jmp $), Jmp $中的$表示当前代码

D_D系统构建-MBR(6)加载loader文件代码MBR解析_第8张图片

















你可能感兴趣的:(操作系统,MBR,MBR.loader)