MIT 6.828 JOS学习笔记9. Exercise 1.5
Lab 1 Exercise 5
再一次追踪一下boot loader的一开始的几句指令,找到第一条满足如下条件的指令处:
当我修改了boot loader的链接地址,这个指令就会出现错误。
找到这样的指令后,把boot loader的链接地址修改一下,我们要在boot/Makefrag文件中修改它的链接地址,修改完成后运行 make clean, 然后通过make指令重新编译内核,再找到那条指令看看会发生什么。 最后别忘了改回来。
答:
这道题希望我们能够去修改boot loader的链接地址,在Lab 1中,作者引入了两个概念,一个是链接地址,一个是加载地址。链接地址可以理解为通过编译器链接器处理形成的可执行程序中指令的地址,即逻辑地址。加载地址则是可执行文件真正被装入内存后运行的地址,即物理地址。
那么在boot loader中,由于在boot loader运行时还没有任何的分段处理机制,或分页处理机制,所以boot loader可执行程序中的链接地址就应该等于加载地址。在Lab中作者说,BIOS默认把boot loader加载到0x7C00内存地址处,所以就要求boot loader的链接地址也要在0x7C00处。boot loader地址的设定是在boot/Makefrag中完成的,所以根据题目的要求,我们需要改动这个文件的值。
首先按照题目要求,在lab目录下输入make clean,清除掉之前编译出来的内核可执行文件,在清除之前你可以先把 obj/boot/boot.asm文件拷贝出来,之后可以用来比较。然后打开这个boot/Makefrag文件,我们会发现下列语句:
其中的-Ttext 0x7C00,就是指定链接地址,我们可以把它修改为0x7E00,然后保存退出。
然后在lab下输入make,重新编译内核,首先查看一下obj/boot/boot.asm,并且和之前的那个obj/boot/boot.asm文件做比较。下图是新编译出来的boot.asm:
下图是修改之前的boot.asm
可以看出,二者区别在于可执行文件中的链接地址不同了,原来是从0x7C00开始,现在则是从0x7E00开始。
然后我们还是按照原来的方式,调试一下内核:
由于BIOS会把boot loader程序默认装入到0x7c00处,所以我们还是再0x7C00处设置断点,并且运行到那里,结果发现如下:
可见第一条执行的指令仍旧是正确的,所以我们接着往下一步步运行。
接下来的几步仍旧是正常的,但是直到运行到一条指令:
图中的0x7c1e处指令,
lgdtw 0x7e64
这条指令我们之前讲述过,是把指令后面的值所指定内存地址处后6个字节的值输入全局描述符表寄存器GDTR,但是当前这条指令读取的内存地址是0x7e64,我们在图中也展示了一下这个地址处后面6个单元存放的值,发现是全部是0。这肯定是不对的,正确的应该是在0x7c64处存放的值,即图中最下面一样的值。可见,问题出在这里,GDTR表的值读取不正确,这是实现从实模式到保护模式转换的非常重要的一步。
我们可以继续运行,知道发现下面这句:
正常来说,0x7c2d处的指令
ljmp $0x08m $0x7e32
应该跳转到的地址应该就是ljmp的下一条指令地址,即0x7c32,但是这里给的值是0x7e32,所以造成错误,此时下条指令变成了0xfe05b。自此程序走向了不归路~
MIT 6.828 JOS学习笔记9. Exercise 1.5的更多相关文章
- MIT 6.828 JOS学习笔记11 Exercise 1.8
Exercise 1.8 我们丢弃了一小部分代码---即当我们在printf中指定输出"%o"格式的字符串,即八进制格式的代码.尝试去完成这部分程序. 解答: 在这个练 ...
- MIT 6.828 JOS学习笔记12 Exercise 1.9
Lab 1中Exercise 9的解答报告 Exercise 1.9: 判断一下操作系统内核是从哪条指令开始初始化它的堆栈空间的,以及这个堆栈坐落在内存的哪个地方?内核是如何给它的堆栈保留一块内存空间 ...
- MIT 6.828 JOS学习笔记13 Exercise 1.10
Lab 1 Exercise 10 为了能够更好的了解在x86上的C程序调用过程的细节,我们首先找到在obj/kern/kern.asm中test_backtrace子程序的地址, 设置断点,并且探讨 ...
- MIT 6.828 JOS学习笔记8. Exercise 1.4
Lab 1 Exercise 4 阅读关于C语言的指针部分的知识.最好的参考书自然是"The C Programming Language". 阅读5.1到5.5节.然后下载poi ...
- MIT 6.828 JOS学习笔记5. Exercise 1.3
Lab 1 Exercise 3 设置一个断点在地址0x7c00处,这是boot sector被加载的位置.然后让程序继续运行直到这个断点.跟踪/boot/boot.S文件的每一条指令,同时使用boo ...
- MIT 6.828 JOS学习笔记3. Exercise 1.2
这篇博文是对Lab 1中的Exercise 2的解答~ Lab 1 Exercise 2: 使用GDB的'si'命令,去追踪ROM BIOS几条指令,并且试图去猜测,它是在做什么.但是不需要把每个细节 ...
- MIT 6.828 JOS学习笔记2. Lab 1 Part 1.2: PC bootstrap
Lab 1 Part 1: PC bootstrap 我们继续~ PC机的物理地址空间 这一节我们将深入的探究到底PC是如何启动的.首先我们看一下通常一个PC的物理地址空间是如何布局的: ...
- MIT 6.828 JOS学习笔记0. 写在前面的话
0. 简介 操作系统是计算机科学中十分重要的一门基础学科,是一名计算机专业毕业生必须要具备的基础知识.但是在学习这门课时,如果仅仅把目光停留在课本上一些关于操作系统概念上的叙述,并不能对操作系统有着深 ...
- MIT 6.828 JOS学习笔记7. Lab 1 Part 2.2: The Boot Loader
Lab 1 Part 2 The Boot Loader Loading the Kernel 我们现在可以进一步的讨论一下boot loader中的C语言的部分,即boot/main.c.但是在我们 ...
随机推荐
- Mysql如何创建短索引(前缀索引)
Mysql如何创建短索引 为什么要用短索引 有时需要索引很长的字符列,它会使索引变大并且变慢.一个策略就是模拟哈希索引.但是有时这也不够好,那么应该怎么办呢?通常可以索引开始的几个字符,而不是全部值, ...
- oracle---jdbctest--laobai
import java.sql.CallableStatement; import java.sql.Connection; import java.sql.ResultSet; import ora ...
- C# byte[]、struct、intptr等的相互转换
1.struct byte[]互相转换 //struct转换为byte[] public static byte[] StructToBytes(object structObj) { int siz ...
- 每日学习笔记:js中可以直接用id名调用的问题?
在JavaScript中,标准的id选择器调用语法是: document.getElementById('myid').style.width = pc + "%"; 但是,今天发 ...
- kindeditor在光标处插入编辑器外的数据
页面 <div class="form-group clearfix"> <label class="control-label col-sm-3 co ...
- 跟随 Web 标准探究DOM -- Node 与 Element 的遍历
写在前面 这篇没有什么 WebKit 代码的分析,因为……没啥好分析的,在实现里无非就是树的(先序DFS)遍历而已,囧哈哈哈……在WebCore/dom/Node.h , WebCore/dom/Co ...
- 白话讲MyIsam和InnoDB的区别
"MyISAM类型不支持事务处理等高级处理,而InnoDB类型支持"这是网上对MyISAM和InnoDB的解释,很抽象吧,我们用白话的方式解释一下其实也比较简单所谓事务处理,就是原 ...
- 布局之按钮的图片分辨率--Android Studio
在布局页面,想把取消按钮和确认钮大小一致,刚开始想法是错的,不用在控制层设置,也不用在布局层压缩图片,有两个方法法: 1.直接用美图秀秀“尺寸”功能,修改成另一按钮一样的分辨率. 2.设置按钮相同高度 ...
- 如何给Apache添加虚拟路径和虚拟主机?
在本地开发,一般只用一个Apache服务器,然后通过配置文件实现多个站点访问,要么是“虚拟路径(别名)”的形式,要么是“虚拟主机”的形式,相关配置参考如下: 说明:我给Apache设置的端口为:,即 ...
- 06OC之内存管理
在高级语言中,例如C#是通过垃圾回收机制(GC)来解决这个问题,但是在OC并没有类似的垃圾回收机制,因此必须由程序员手动去维护.今天就讲讲OC中的内存管理: 一.内存管理原理 在Xcode4.2之后的 ...