30天自制操作系统
上QQ阅读APP看书,第一时间看更新

6 操作系统开发中的困难

现在市面上众多的C编译器都是以开发Windows或Linux上的应用程序为前提而设计的,几乎从来没有人想过要用它们来开发其他的软件,比如自己的操作系统。笔者所提供的编译器,也是以Windows版的gccGNU项目组开发的免费C编译器,GNU C Compiler的简称。有时也指GNU开发的各种编译器的集合(GNU Compiler Collection)。为基础稍加改造而做成的,与gcc几乎没什么不同。或许也有为开发操作系统而设计的C编译器,不过就算有,恐怕也只有开发操作系统的公司才会买,所以当然会很贵。这次我们用不了这么高价的软件。

因为这些原因,我们只能靠开发应用程序用的C编译器想方设法编写出一个操作系统来。这实际上是在硬来,所以当中就会有很多不方便的地方。

就比如说printf(“hello\n”);吧,这个函数总是出现在C语言教科书的第一章,但我们现在就连它也无法使用。为什么呢?因为printf这个函数是以操作系统提供的功能为前提编写的,而我们最开始的操作系统可是什么功能都没有。因此,如果我们硬要执行这个函数的话,CPU会发生一般保护性异常电脑的CPU非常优秀,如果接到无视OS保护的指令或不可能执行的指令时,首先会保存当前状态,中断正在执行的程序,然后调用事先设定的函数。这种机制称为异常保护功能,比如除法异常、未定义指令异常、栈异常等。不能归类到任何异常类型中去的异常事态被称为一般保护异常。这种异常保护功能或许会让老Windows用户想起那噩梦般的蓝屏画面,但是如果经历过操作系统开发以后,大家就会觉得这种机制实在是太有用了。,直接罢工。刚开始的时候不仅是printf,几乎所有的函数都无法使用。

关于这次开发语言的选择,如果非要说出个所以然的话,其实也是因为C语言还算是很少依赖操作系统功能的语言,基本上只要不用函数就可以了。如果用C++的话,像new/delete这种基本而重要的运算符都不能用了,另外对于类的做法也会有很多要求,这样就无法发挥C++语言的优势了。当然,为了使用这些函数去开发操作系统,只要我们想办法,还是能够克服种种困难的。但是如果做到这个份上,我们不禁会想,到底是在用C++做操作系统呢,还是在为了C++而做操作系统呢。对别的语言而言这个问题会更加突出,所以这次还是决定使用C语言,希望大家予以理解。

顺便插一句,在开发操作系统时不会受到限制的语言大概就只有汇编语言Assembler,与机器语言最接近的一种编程语言。过去掌握这种语言的人会备受尊敬,而现在这种人恐怕要被当作怪人了,真是可悲啊。原本汇编语言的正式名称应该是Assembly语言,而Assembler一般指的是编译程序。不过像笔者这样的老程序员,往往不对这两个词进行区分,统称为Assembler。了。还是汇编语言最厉害读到这里,大家可能还不理解为什么这么说,越往后看就越能慢慢体会到了。(笑)。但是如果本书仅用汇编来编写操作系统的话,恐怕没几个人会看,所以就算是做事管前不顾后的笔者也不得不想想后果。

另外,在开发操作系统时,需要用到CPU上的许多控制操作系统的寄存器Register,有些类似机器语言中的变量。对CPU而言,内存是外部存储装置,在CPU内核之中,存储装置只有寄存器。全部寄存器的容量加起来也不到1KB。。一般的C编译器都是用于开发应用程序的,所以根本没有任何操作这些寄存器的命令。另外,C编译器还具有非常优秀的自动优化功能,但有时候这反而会给我们带来麻烦。

归根到底,为了克服以上这些困难,有些没法用C语言来编写的部分,我们就只好用汇编语言来写了。这个时候,我们就必须要知道C编译器到底是怎样把程序编译成机器语言的。如果不能够与C编译器保持一致的话,就不能将汇编语言编写的部分与C语言编写的部分很好地衔接起来。这可是在编写普通的C语言程序时所体会不到哦!不过相比之下,今后的麻烦可比这种好处多得多啊(苦笑)。

同样,如果用C++来编写操作系统,也必须知道C++是如何把程序编译成机器语言的。当然,C++比C功能更多更强,编译规则也更复杂,所以解释起来也更麻烦,我们选用C语言也有这一层理由。总之,如果不理解自己所使用的语言是如何进行编译的,就没法用这种语言来编写操作系统。

书店里有不少C语言、C++的书,当然也还有Delphi、Java等其他各种编程语言的书,但这么多书里没有一本提到过“这些源代码编译过后生成的机器语言到底是什么样的”。不仅如此,虽然我们是在通过程序向CPU发指令的,但连CPU的基本结构都没有人肯给我们讲一讲。作为一个研究操作系统的人,真觉得心里不是滋味。为了弥补这一空缺,我们这本书就从这些基础讲起(但也仅限于此次开发操作系统所必备的基础知识)。

我们具备了这样的知识以后,说不定还会改变对程序设计的看法。以前也许只想着怎么写出漂亮的源代码来,以后也许就会更注重编译出来的是怎样的机器语言。源代码写得再漂亮,如果不能编译成自己希望的机器语言,不能正常运行的话,也是毫无意义的。反过来说,即便源代码写得难看点儿,即便只有特定的C编译器才能编译,但只要能够得到自己想要的机器语言就没有问题了。虽然不至于说“只要编译出了想要的机器语言,源代码就成了一张废纸”,但从某种意义上说还真就是这样。

对于开发操作系统的人而言,源程序无非是用来得到机器语言的“手段”,而不是目的。浪费太多时间在手段上就是本末倒置了。

对了,还有一点或许会有人担心,所以在这里事先说明一下:虽然操作系统是用C语言和汇编语言编写的,但并不是用C++编写的应用程序就无法在这个操作系统上运行。编写应用程序所用的语言,与开发操作系统所使用的语言是没有任何关系的,大家大可不必担心。