练习四呢
假定进入这个保护模式之后
我们Bootloader需要干的很重要一个事情
就是要能够加载ELF文件
为什么要加载ELF文件呢
因为我们的kernel 就是uCoreOS
是以ELF形式存在在硬盘上的
什么文件呢 就这个文件
可以看到这个kernel
就是我们这个uCore
它完成了刚才说的
负责把这个中断初始化好
然后产生时钟中断
能够把这个信息显示在屏幕上等等
这些功能都是uCore完成的很基本的一些功能
那这里面比较有意思的是
Bootloader怎么能够
把uCore给加载到内存当中去
其实它需要完成很重要的两步事情
第一步 是怎么能够读取硬盘中的信息
这需要Bootloader能够访问硬盘
第二个是Bootloader把这个硬盘数据读出来之后
要把其中ELF格式这个文件给分析出来
从而知道我们uCore它的代码段
应该放在什么地方
应该有多大一块空间放这个代码段数据
哪一段空间是放数据段的数据
然后把它加载内存当中去
然后同时还知道
跳转到uCore哪个地方去执行
那这一块代码 其实我们也是一样的
有专门一个小的Project来完成这个事情
我们的Project2就是干这个事情的
那在Project2我们可以看到
跟Project1比起来 它增加了一段代码
这个代码主要是能够
刚才说到这个 读扇区
和分析这个文件
读扇区呢主要是这个函数 readsect
这是读取扇区 它用到了这个in b
和out b这种机器指令
那我们可以看到这里面
其实inb和outb的实现
都是用我们说的
刚在lab0中介绍到过的
内联汇编来实现的
它采取了一种IO空间的寻址方式
能够把外设的数据给读到内存中来
这也是一种X86里面的寻址方式
除了正常memory方式之外
还有IO一种寻址方式
好 那这一块细节呢其实大家不用特别看
只是知道我们这个Bootloader
知道怎么去从哪开始
把相应的扇区给读进来
以及它读多大 读完之后
它就需要去进一步的分析
那这个分析呢 需要去了解
了解相应的格式ELF的格式
好 我们可以看到在bootmain里面呢
它有一个对ELF格式一个判断
它怎么知道读进来这个扇区的数据
是一个ELF格式的文件呢
它其实是读取了一个ELF的header
从磁盘中读取ELFheader
然后判断它的一个特殊的成员变量 e magic
看它是否等于一个特定的值
如果等于特定值
就认为是确实是一个合法的ELF格式的文件
那我们在lab1里面
有更详细把这个文件的ELF格式文件信息
给读取进来一段判断
大家可以看这个
在这个bootmain里面呢有相应一些实现
这个bootmain函数
它怎么能够根据ELFheader和proghdr程序头
来读出相应的代码段和数据段
然后加到相应的地方去
最后这一条比较关键
这就决定了到底Bootloader把这个加载完之后
到底要跳到什么地方去
把控制权交给uCore去执行
这就是Bootloader干的最主要的事情
那其实也可以看到 我们练习一到练习四
主要是对lab1Bootloader这一块
给大家做相应一些练习
那么练习五和六
主要是针对这个uCore本身了
那练习五主要是考虑的是
怎么能够分析函数的调用栈
练习六呢 主要是建立中断
这两块相对来说要复杂一些
需要大家去编程
这里面显示练习五
这一段输出呢 是正确的输出结果
可以看出来
如果你能正确的分析出这个栈帧格式
栈帧它这个依赖关系
栈帧格建立的链表
那我们就可以把相应函数代码关系给展示出来
那这就是一个最后展示的结果
那怎么去把正确的ESP和EBP给读取出来
这是完成这个lab5实验的关键
这里面其实填的内容很少 就两句话
但是你要把相应的细节要掌握清楚
才能够正确的填写相应的代码