`
spartan1
  • 浏览: 360101 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

ucore-project1: boot(3),终于搞定了

 
阅读更多

哈哈,终于解决了昨天搞到半夜快三点没有搞定的问题:在C语言代码中无法使用串口输出的问题!

 

说到底很简单,把COM1输出端口号搞错了,把0x3F8写成了0x3B8,结果就死活不出来。实际上昨晚还有最初还有另外一个问题:gdt中的segment descriptor创建出错,本来应该是((type & 0x0F) | 0x90),结果写成了((type & 0x0F) & 0x90),结果看了一遍又一遍,就是没有发现。

 

在gdb没法调试这些16位代码的情况下,唯一的手段就是使用输出查看。想想昨晚的解决方法是这样的,首先写16位代码中通过COM1口打印的函数putc16,然后在多个地方插入该函数,看看是在哪里出错。直到lgdt加载gdt时都没错,不过一执行写CR0切换到保护模式立刻出问题,不断重复打印前面的输出,说明前面16位代码不断被重新执行,搞不懂为什么。不过至少说明切换到保护模式失败了。切换保护模式失败可能是切换的指令写错了,也可能是定义gdt的地方写错了。反复确认切换指令没错,把定义段描述符的宏定义比较了多遍,重点比较其中左移的数字,都是一样的,然后.byte指令我是分开两个写了,他们是一个写的,把这个改一下,明知道这个可能不管用,果然不管用。最后某一次终于发现了|和&的问题。

 

刚才的0x3F8和0x3B8也一样,也是在实验了各种方法,在c语言中写了各种函数调用,最好才偶尔发现的。

 

在调试时一定要抓住重点,反复确认重点的东西是否出错。对于汇编,重点就是各个数字,包括对这些数字的逻辑运算,尤其是一些端口编号等,一定要重点确认,反而是一些写法、形式不重要,大体看看就好。

 

ucore第一个工程的总结:

本工程比较简单,全部代码都在MBR扇区中,实际上编译出来后所有代码一共只有256字节,主要做了如下几件事:

1. 启动A20地址线

2. 切换到保护模式

3. 在保护模式下,通过串口打印helloworld

之后就是死循环。其中前两步都是在汇编中使用16位代码做的,第三步是使用C语言写的。

 

在第一步中了解了A20 gate的历史,以及如何使用键盘控制器或者fast A20 gate启用它。

 

在第二步中重新复习了x86的保护地址模式,复习了段寄存器、段描述符、段选择子以及GDT的相关知识。第二步最后是调用C语言函数,这里没有预先声明C函数,直接就可调用。

 

第三步中串口打印通过直接往COM1输出端口0x3F8写数据实现,这个使用outb汇编指令,因此牵扯到C语言中使用嵌入汇编实现。本次试验也重新复习了一下嵌入汇编是怎么用的。

 

16位汇编和32位汇编中,也写了通过串口打印单个字符的函数,但在汇编中写打印字符串的函数就要复杂很多,相对来说C语言实现这种功能就非常easy。

 

在自己实现过程中把原先的编译系统(Makefile)过了一遍,原先Makefile太多定义,第一次看很晕,整理后重新写了一份Makefile。

 

原先实现中通过写了一个C工具sign来实现将0x55AA写到MBR扇区最后,自己写时去掉了sign,直接通过xxd一行shell脚本搞定。

 

本次试验花的时间很长,刚刚在计划的最后一天完成本实验。后续大部分试验将不会有本次这么多空余时间,一定要加快进度。当然第一次也的确会比较慢。坚持!

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics