您的位置:首页 > 其它

动手制作操作系统——一点分析问题的经验

2016-05-19 12:42 316 查看
书中讲解ldt部分的例子和代码很简单,本以为抄完运行一下马上就能结束这章。但是很尴尬,在抄完书中的代码后,编译运行,实际运行的结果和书中的结果并不一样,程序只运行了一半就导致系统崩溃了,干瞪眼看代码看了半天,和书中的代码明明写的一样,那么为什么会出现这个问题呢?

书中程序运行在FreeDOS上,大致意思如下:

在程序开头部分建立GDT,LDT和GDT选择子,LDT选择子等,等程序加载至内存后,

1、跳至一个在实模式下运行的代码段,这段代码负责初始化GDT,LDT中的描述符和进入保护模式的准备工作(记做A代码段);

2、跳至保护模式,一个32位的代码段(记做B代码段),在这里显示一串字符串;

3、进入LDT中的一个描述符所表示的代码段(记做C代码段),这里显示一个字符L;

4、回到实模式,程序结束。

而我的程序写完后,只输出了字符串,C代码段中的'L'并未显示,系统就崩溃了

 

首先粗略分析问题,B中的字符串已经显示成功,C中的'L'未显示,那么问题大致的位置就定位在A或者A之前

第一个问题来了,由于这个示例程序是运行在FreeDos上的,我们的程序被Dos加载到内存中什么地方我是不知道的,而bochsdbg想要设置断点就必须要知道程序的运行地址,我应该怎么设置断点?。

在网上找到了一个方法:

1、在程序开头处建立一个标记LABEL_BEGIN;

2、向400h:0处(也可以别的未被占用的内存地址)写入代表跳转至LABEL BEGIN 处(jmp far)的16进制机器码;

3、跳至400h;0处

然后在操作系统运行前在400h:0处设置断点,就可以调试程序了。

解决无法调试的问题后单步执行程序,执行完跳转至C代码段的指令后。程序跳转到了一个奇怪的地址,不是C代码段所在的地址,显然,问题出在建立或者初始化GDT,LDT,选择子的部分上

那么单步执行程序至加载完LDT处,用info ldt命令查看GDT和LDT,GDT中的LDT描述符的段基址和段界限中没有问题,而LDT中唯一的描述符基址出现了错误,为0x00002600,与应该得到的结果0x00032600不符,至此,问题的位置已经找到了,就在A中 初始化LDT中的描述符(记做D)处。

继续调试D处的代码,明明应该右移的数据却左移了,我将我抄写完的代码中的D处和书中的代码的D处对比了一下,发现,原来只是因为我把书中的shr抄成了shl。只因为一个字符,指令的含义完全改变了。整个程序就因为这一个字符而崩溃。

问题虽小但是解决这个问题的过程也收获很多经验,遇到bug的大致思路就是:大致定位问题,找出问题发生的具体位置,解决问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  操作系统 经验