30天自制操作系统
74页1、 着手开发之前 前言 何谓操作系统 开发操作系统的各种方法 无知则无畏 如何开发操作系统 操作系统开发中的困难 学习本书时的注意事项(重要! ) 各章内容摘要 1 前言 现在,挑选自己喜欢的配件来组装一台世界上独一无二的、个性化的PC(个人电脑)对我们来说已不再困难。不仅如此,只要使用合适的编译器,我们就可以自己编写游戏、制作自己的工具软件;使用网页制作工具,我们还可以轻而易举地制作主页;如果看过名著CPU制作法的话,就连自制CPU也不在话下。 然而,在“自制领域”里至今还有一个无人涉足的课题自己制作操作系统(OS),它看起来太难以至于初学者不敢轻易挑战。电脑组装也好,游戏、工具软件制作也好,主页也好,CPU也好,这些都已经成为初学者能够尝试的项目,而唯独操作系统被冷落在一边,实在有些遗憾。 “既然还没有这样的书,那我就来写一本。 ”这就是笔者撰写本书的初衷。 也许是因为面向初学者的书太少的缘故吧,一说起操作系统,大家就会觉着那东西复杂得不得了,简直是高深莫测。特别是像Windows和Linux这些操作系统,庞大得一张光盘都快装不下了,要是一个人凭着兴趣来开发的话,不知道需要历经多么漫
2、长的过程才能完成。笔者也认为,像这么复杂的操作系统,单凭一个人来做,一辈子都做不出来。 英文为compiler,指能够将源代码编译成机器码的软件。 CPU制作法 ,渡波郁著,每日Communications出版公司,ISBN 4-8399-0986-5。 Operating System的缩写,汉语译作“操作系统” 。Windows、Linux、MacOS、MS-DOS等软件的总称。 第 0 天 1 2 第 0天:着手开发之前 不过大家也不必担心太多。笔者就成功地开发过一个小型操作系统,其大小还不到80KB。麻雀虽小,五脏俱全,这个操作系统的功能还是很完整的。有人也许会怀疑: “这么小的操作系统,是不是只有命令行窗口啊?要不就是没有多任务?”不,这些功能都有。 怎么样,只有80KB的操作系统,大家不觉得稍作努力就可以开发出来吗?即使是初学者,恐怕也会觉得这不是件难事吧?没错,我们用一个月的时间就能写出自己的操作系统!所以大家不用想得太难,我们轻轻松松地一起来写写看吧。 以本书作者为主角开发的操作系统OSASK 大家一听到编译后的文件大小为80KB可能会觉得它作为程序来讲已经很小了,不过
3、曾经编过程序的人可以查一查自己编的程序(.exe文件)的大小,这样就能体会到80KB到底是难是易了。 kilobyte,程序及数据大小的度量单位,1字节 (byte)的1024倍。 一张软盘的容量是1440KB。顺便提一下,1024KB等于1MB(兆字节) 。1字节是8个比特,正好能记录8位0和1的信息。B到底是指字节(byte) ,还是指比特(bit) ,有时容易混淆。这里根据一般的规则,用大写B表示字节,小写b表示比特。 console,通过键盘输入命令的一种方式,基本上只用文字进行计算机操作,是MS-DOS等老式操作系统的主流操作方式。 在操作系统的世界里, 运行中的程序叫做 “任务” , 而同时执行多个任务的方式就被称为 “多任务”(multitask) 。 笔者与他人一起合作开发的操作系统(趁机宣传一下) 。虽然只有小小的78KB,不过为了做它也花了好几年的时间。而这次能在短时间内开发完成操作系统,是因为我们较好地总结了开发操作系统所必要的知识。也就是说,如果笔者在年轻时可以看到现在这本书的话,可能在短时间内就能开发出OSASK了,所以笔者很羡慕大家呀。 2 何谓操作系统 3
4、 0 3 20 21 8 10 16 9 22 7 12 11 13 15 14 15 没编过程序的人也可以下载一个看上去不是很复杂的自由软件, 看看它的可执行文件有多大。Windows 2000的计算器程序大约是90KB,大家也可以根据这个想象一下。 本书对于不打算自己写操作系统,甚至连想都没想过这个问题的人来说也会大有裨益。举个例子,读本自己组装PC的书就能知道PC是由哪些组件构成的,PC的性能是由哪些部分决定的;读本如何编写游戏的书,就能明白游戏是怎样运行的;同理,读了本书,了解了操作系统的开发过程, 就能掌握操作系统的原理。 所以说, 对操作系统有兴趣的人, 哪怕并不想自己做一个出来,也可以看看这本书。 阅读本书几乎不需要相关储备知识,这一点稍后还会详述。不管是用什么编程语言,只要是曾经写过简单的程序,对编程有一些感觉,就已经足够了(即使没有任何编程经验,应该也能看懂) ,因为这本书主要就是面向初学者的。书中虽然有很多C语言程序,但实际上并没有用到很高深的C语言知识,所以就算是曾经因为C语言太难而中途放弃的人也不用担心看不懂。当然,如果具备相关知识的话,理解起来会相对容易一些,
5、不过即使没有相关知识也没关系,书中的说明都很仔细,大家可以放心。 本书以IBM PC/AT兼容机(也就是所谓的Windows个人电脑)为对象进行说明。至于其他机型,比如Macintosh(苹果机)或者PC-9821等,虽然本书也参考了其中某些部分,但基本上无法开发出在这些机型上运行的操作系统,这一点还请见谅。严格地说,不是所有能称为AT兼容机的机型都可以开发我们这个操作系统,我们对机器的配置要求是CPU高于386(因为我们要开发32位操作系统) 。换句话说,只要是能运行Windows 95以上操作系统的机器就没有问题,况且现在市面上(包括二手市场)恐怕都很难找到Windows 95以下的机器了,所以我们现在用的机型一般都没问题。 另外,大家也不用担心内存容量和硬盘剩余空间,我们需要使用的空间并不大。只要满足以上条件,就算机器又老又慢,也能用来开发我们的操作系统。 2 何谓操作系统 说老实话,其实笔者也不是很清楚。估计有人会说: “连这个都不懂,还写什么书?”不好意思笔者见过很多种操作系统,有的功能非常多,而有的功能特别少。在比较了各种操作系统之后,笔者还是没有找到它们功能的共同点,无法
6、下定义。结果就是,软件作者坚持说自己做的就是操作系统,而周围的人也不深究,就那样默认了,以至于什么软件都可以算是操作系统。笔者现在就是这么认为的。 既然就操作系统而言各有各的说法,那笔者也可以反过来利用这一点,一开始就根据自己的需要来定义操作系统,然后开发出一个满足自己定义条件的软件就可以了。这当然也算是开发操 本书所讲的操作系统内容仅用Macintosh是开发不了的,并且开发出的操作系统也不能直接在Macintosh上运行。但是在PC上开发的操作系统,可以通过模拟器在Macintosh上运行。 2 4 第 0天:着手开发之前 作系统了。哪怕做一个MS-DOS那样的,在一片漆黑的画面上显示出白字,输入个命令就能执行的操作系统也可以,这对笔者来说很简单。 但这样肯定会让一些读者大失所望。现在初学者也都见多识广,一提到操作系统,大家就会联想到Windows、Linux之类的庞然大物,所以肯定期待自制操作系统至少能任意显示窗口、实现鼠标光标控制、同时运行几个应用程序,等等。所以为了满足读者的期待,我们这次就来开发一个具有上述功能的操作系统。 3 开发操作系统的各种方法 开发操作系统的方法也是
7、各种各样的。 笔者认为,最好的方法就是从既存操作系统中找一个跟自己想做的操作系统最接近的,然后在此基础上加以改造。这个方法是最节省时间的。 但本书却故意舍近求远,一切从零开始,完完全全是自己从头做起,这是因为笔者想向各位读者介绍从头到尾开发操作系统的全过程。如果我们找一个现成的操作系统,然后在此基础上删删改改的话,那这本书就不能涉及操作系统全盘的知识了,这样肯定无法让读者朋友满意。不过由于是全部从零做起,所以篇幅长些,还请读者朋友们耐下心来慢慢看。 要开发操作系统,首先遇到的问题就是使用什么编程语言,这次我们想以C语言为主。 “啊,C语言啊?” 笔者仿佛已经听到大家抱怨的声音了 (苦笑) 。 “这都什么年代了, 用C语言多土啊” 、“用C+多好呀” 、 “还是Java好” 、 “不,我就喜欢Delphi” 、 “我还是觉得Visual Basic最好”大家个人喜好习惯各不相同。这种心情笔者都能理解,但为了讲解时能简单一些,笔者还是想用C语言,请大家见谅。C语言功能虽不多,但用起来方便,所以用来开发操作系统刚好合适。要是用其他语言的话,仅讲解语言本身就要花很长时间,大家恐怕就没兴趣看下去
8、了。 在这里先向大家传授一个从零开始开发操作系统的诀窍, 那就是不要一开始就一心想着要开发操作系统,先做一个有点操作系统样子的东西就行了。如果我们一上来就要开发一个完整的操作系统的话,要做的东西太多,想想脑袋都大了,到时恐怕连着手的勇气也没有了。笔者就是因为这个,几年间遇到了很多挫折。所以在这本书里,我们不去大张旗鼓地想着要开发一个操作系统,而是编写几个像操作系统的演示程序就行了。其实在开发演示程序的过程中大家就会逐步发现,演示程序不再是简单的演示程序,而是越来越像一个操作系统了。 4 无知则无畏 当我们打算开发操作系统时,总会有人从旁边跳出来,罗列出一大堆专业术语,问这问那,像内核怎么做啦,外壳怎么做啦,是不是单片啦,是不是微内核啦,等等。虽然有时候提这些问 演示程序的英文是demonstration。指不是为了使用,而是为了演示给人看的软件。 3 4 4 无知则无畏 5 0 3 20 21 8 10 16 9 22 7 12 11 13 15 14 15 题也是有益的,但一上来就问这些,当然会让人无从回答。 要想给他们一个满意答复,让他们不再从旁指手画脚的话,还真得多学习,拿出点像
9、模像样的见解才行。但我们是初学者,没有必要去学那些麻烦的东西,费时费力且不说,当我们知道现有操作系统在各方面都考虑得如此周密的时候,就会发现自己的想法太过简单而备受打击没了干劲。如果被前人的成果吓倒,只用这些现有的技术来做些拼拼凑凑的工作,岂不是太没意思了。 所以我们这次不去学习那些复杂的东西,直接着手开发。就算知道一大堆专业术语、专业理论,又有什么意思呢?还不如动手去做,就算做出来的东西再简单,起码也是自己的成果。而且自己先实际操作一次, 通过实践找到其中的问题, 再来看看是不是已经有了这些问题的解决方案,这样下来更能深刻地理解那些复杂理论。不管怎么说,反正目前我们也无法回答那些五花八门的问题,倒不如直接告诉在一旁指手画脚的人们:我们就是想用自己的方法做自己喜欢的事情,如果要讨论高深的问题,就另请高明吧。 其实反过来看,什么都不知道有时倒是好事。正是因为什么都不知道,我们才可能会认真地去做那些专家们嗤之以鼻的没意义的“傻事” 。也许我们大多时候做的都没什么意义,但有时也可能会发掘出专家们千虑一失的问题呢。专家们在很多方面往往会先入为主,甚至根本不去尝试就断定这也不行那也不行,要么就浅
10、尝辄止。因此能够挑战这些问题的,就只有我们这种什么都不知道的门外汉。任何人都能通过学习成为专家,但是一旦成为专家,就再也找不回门外汉的挑战精神了。 所以从零开始, 在没有各种条条框框限制的情况下, 能做到什么程度就做到什么程度,碰壁以后再回头来学习相关知识,也为时未晚。 实际上笔者也正是这样一路磕磕绊绊地走过来,才有了今天。笔者没去过教授编程的学校,也几乎没学什么复杂的理论就开始开发操作系统了。但也正是因为这样,笔者做出的操作系统与其他的操作系统大不相同,非常有个性,所以得到了专家们的一致好评,而且现在还能有机会写这本书,向初学者介绍经验。总地说来,笔者从着手开发直到现在,每天都是乐在其中的。 正是像笔者这样自己摸着石头过河,一路磕磕绊绊走过来的人,讲出的东西才简单易懂。不过在讲解过程中会涉及失败的经验,以及如何重新修正最终取得成功,所以已经懂了的人看着可能会着急。不好意思,如果碰到这种情况请忍耐一下吧。 读了这部分内容或许有人会觉得“是不是什么都不学习才是最好的啊” ,其实那倒不是。比如工作上需要编写某些程序,或者一年之内要完成某些任务,这时没有时间去故意绕远路,所以为了避免不必要的
11、失败,当然是先学习再着手开发比较好。但这次我们是因为自己的兴趣而学习操作系统的开发的,既然是兴趣,那就是按自己喜欢的方式慢慢来,这样就挺好的。 6 第 0天:着手开发之前 5 如何开发操作系统 操作系统(OS)一般打开电源开关就会自动执行。这是怎么实现的呢?一般在Windows上开发的可执行文件(.exe) ,都要在操作系统启动以后,双击一下才能运行。我们这次想要做的可不是这种可执行程序,而是希望能够做到把含有操作系统的CD-ROM或软盘插入电脑,或者将操作系统装入硬盘后,只要打开电源开关就能自动运行。 为了开发这样的操作系统,我们准备按照如下的步骤来进行。 也就是说,所谓开发操作系统,就是想办法制作一张“含有操作系统的,能够自动启动的磁盘” 。 这里出现的“映像文件”一词,简单地说就是软盘的备份数据。我们想要把特定的内容写入磁盘可不是拿块磁铁来在磁盘上晃晃就可以的。所以我们要先做出备份数据,然后将这些备份数据写入磁盘,这样才能做出符合我们要求的磁盘。 软盘的总容量是1440KB,所以作为备份数据的映像文件也恰好是1440KB。一旦我们掌握了制作磁盘映像的方法,就可以按自己的想法制作任
12、意内容的磁盘了。 这里希望大家注意的是,开发操作系统时需要利用Windows等其他的操作系统。这是因为我们要使用文本编辑器或者C编译器,就必须使用操作系统。既然是这样,那么世界上第一个操作系统又是怎么做出来的呢?在开发世界上第一个操作系统时,当然还没有任何现成的操作系统可供利用,因此那时候人们不得不对照着CPU的命令代码表,自己将0和1排列起来,然后再把这些数据写入磁盘(估计那个时候还没有磁盘,用的是其他存储设备) 。这是一项非常艰巨的工作。 所以恐怕最初的操作系统功能非常有限, 做好之后人们再利用它来开发一个稍微像点样的操作系统, 然后再用这个来开发更实用的操作系统操作系统应该就是这样一步一步发展过来的。 source program,为了生成机器码所写的程序代码。可通过编译器编译成机器语言。 CPU能够直接理解的语言,由二进制的0和1构成。其实源代码也是由 0和1构成的(后述) 。 5 6 操作系统开发中的困难 7 0 3 20 21 8 10 16 9 22 7 12 11 13 15 14 15 由于这次大部分初学者都是Windows用户,所以决定使用Windows这个现成的操
13、作系统,Windows95/98/Me/2000/XP中任意一个版本都可以。肯定也有人会说还是Linux好用,所以笔者也总结了一下Linux上的做法,具体内容写在了帮助与支持里,有需要的人请一定看一看。 另外,如果C编译器和映像文件制作工具等不一样的话,开发过程中就会产生一些细微的差别,这很难一一解释,所以笔者就直接把所有的工具都放到附带光盘里了。这些几乎都是笔者所发布的免费软件,它们大都是笔者为了开发后面的OSASK操作系统而根据需要自己编写的。这些工具的源代码也是公开的。除此之外,我们还会用到其他一些免费软件,所有这些软件的功能我们会在使用的时候详细介绍。 6 操作系统开发中的困难 现在市面上众多的C编译器都是以开发Windows或Linux上的应用程序为前提而设计的,几乎从来没有人想过要用它们来开发其他的软件,比如自己的操作系统。笔者所提供的编译器,也是以Windows版的gcc为基础稍加改造而做成的, 与gcc几乎没什么不同。或许也有为开发操作系统而设计的C编译器,不过就算有,恐怕也只有开发操作系统的公司才会买,所以当然会很贵。这次我们用不了这么高价的软件。 因为这些原因,我们
14、只能靠开发应用程序用的C编译器想方设法编写出一个操作系统来。这实际上是在硬来,所以当中就会有很多不方便的地方。 就比如说printf(“hellon”);吧,这个函数总是出现在C语言教科书的第一章,但我们现在就连它也无法使用。为什么呢?因为printf这个函数是以操作系统提供的功能为前提编写的,而我们最开始的操作系统可是什么功能都没有。因此,如果我们硬要执行这个函数的话,CPU会发生一般保护性异常,直接罢工。刚开始的时候不仅是printf,几乎所有的函数都无法使用。 关于这次开发语言的选择,如果非要说出个所以然的话,其实也是因为C语言还算是很少依赖操作系统功能的语言,基本上只要不用函数就可以了。如果用C+的话,像new/delete这种基本而重要的运算符都不能用了,另外对于类的做法也会有很多要求,这样就无法发挥C+语言的优势了。当然,为了使用这些函数去开发操作系统,只要我们想办法,还是能够克服种种困难的。但是如果做到这个份上,我们不禁会想,到底是在用C+做操作系统呢, http:/hrb.osask.jp。 GNU项目组开发的免费C编译器, GNU C Compiler的简称。 有时也
15、指GUN开发的各种编译器的集合 (GNU Compiler Collection) 。 电脑的CPU非常优秀,如果接到无视OS保护的指令或不可能执行的指令时,首先会保存当前状态,中断正在执行的程序,然后调用事先设定的函数。这种机制称为异常保护功能,比如除法异常、未定义指令异常、栈异常等。不能归类到任何异常类型中去的异常事态被称为一般保护异常。这种异常保护功能或许会让老Windows用户想起那噩梦般的蓝屏画面,但是如果经历过操作系统开发以后,大家就会觉得这种机制实在是太有用了。 6 8 第 0天:着手开发之前 还是在为了C+而做操作系统呢。对别的语言而言这个问题会更加突出,所以这次还是决定使用C语言,希望大家予以理解。 顺便插一句,在开发操作系统时不会受到限制的语言大概就只有汇编语言了。还是汇编语言最厉害(笑) 。但是如果本书仅用汇编来编写操作系统的话,恐怕没几个人会看,所以就算是做事管前不顾后的笔者也不得不想想后果。 另外,在开发操作系统时,需要用到CPU上的许多控制操作系统的寄存器。一般的C编译器都是用于开发应用程序的,所以根本没有任何操作这些寄存器的命令。另外,C编译器还具有非常优
16、秀的自动优化功能,但有时候这反而会给我们带来麻烦。 归根到底,为了克服以上这些困难,有些没法用C语言来编写的部分,我们就只好用汇编语言来写了。这个时候,我们就必须要知道C编译器到底是怎样把程序编译成机器语言的。如果不能够与C编译器保持一致的话,就不能将汇编语言编写的部分与C语言编写的部分很好地衔接起来。这可是在编写普通的C语言程序时所体会不到哦!不过相比之下,今后的麻烦可比这种好处多得多啊(苦笑) 。 同样,如果用C+来编写操作系统,也必须知道C+是如何把程序编译成机器语言的。当然,C+比C功能更多更强,编译规则也更复杂,所以解释起来也更麻烦,我们选用C语言也有这一层理由。总之,如果不理解自己所使用的语言是如何进行编译的,就没法用这种语言来编写操作系统。 书店里有不少C语言、C+的书,当然也还有Delphi、Java等其他各种编程语言的书,但这么多书里没有一本提到过“这些源代码编译过后生成的机器语言到底是什么样的” 。不仅如此,虽然我们是在通过程序向CPU发指令的,但连CPU的基本结构都没有人肯给我们讲一讲。作为一个研究操作系统的人, 真觉得心里不是滋味。 为了弥补这一空缺, 我们这本
17、书就从这些基础讲起 (但也仅限于此次开发操作系统所必备的基础知识) 。 我们具备了这样的知识以后,说不定还会改变对程序设计的看法。以前也许只想着怎么写出漂亮的源代码来,以后也许就会更注重编译出来的是怎样的机器语言。源代码写得再漂亮,如果不能编译成自己希望的机器语言,不能正常运行的话,也是毫无意义的。反过来说,即便源代码写得难看点儿,即便只有特定的C编译器才能编译,但只要能够得到自己想要的机器语言就没有问题了。虽然不至于说“只要编译出了想要的机器语言,源代码就成了一张废纸” ,但从某种意 Assembler,与机器语言最接近的一种编程语言。过去掌握这种语言的人会备受尊敬,而现在这种人恐怕要被当作怪人了,真是可悲啊。原本汇编语言的正式名称应该是Assembly语言,而Assembler一般指的是编译程序。不过像笔者这样的老程序员,往往不对这两个词进行区分,统称为Assembler。 读到这里,大家可能还不理解为什么这么说,越往后看就越能慢慢体会到了。 Register,有些类似机器语言中的变量。对CPU而言,内存是外部存储装置,在CPU内核之中,存储装置只有寄存器。全部寄存器的容量加起来也
18、不到1KB。 7 学习本书时的注意事项(重要! ) 9 0 3 20 21 8 10 16 9 22 7 12 11 13 15 14 15 义上说还真就是这样。 对于开发操作系统的人而言,源程序无非是用来得到机器语言的“手段” ,而不是目的。浪费太多时间在手段上就是本末倒置了。 对了,还有一点或许会有人担心,所以在这里事先说明一下:虽然操作系统是用C语言和汇编语言编写的,但并不是用C+编写的应用程序就无法在这个操作系统上运行。编写应用程序所用的语言,与开发操作系统所使用的语言是没有任何关系的,大家大可不必担心。 7 学习本书时的注意事项(重要! ) 本书从第1章开始,写的是每一天实际开发的内容,虽然一共分成了30天,但这些都是根据笔者现在的能力和讲解的长度来大概切分的,并不是说读者也必须得一天完成一章。每个人觉得难的地方各不相同,有时学习一章可能要花上一星期的时间,也有时可能一天就能学会三章的内容。 当然,学习过程中可能会遇到看不太懂的章节,这种时候不要停下来,先接着往下读上个一两章也许会突然明白过来。如果往后看还是不明白的话,就先确认一下自己已经理解到哪一部分了,然后回过头来再从不
19、懂的地方重新看就是了。千万别着急,看第二遍时,没准就会豁然开朗了。 如果已经弄清了哪里没理解,而且没理解的部分看了很多遍还是不明白的话,大家可以参阅我们的帮助与支持页面,或许“问题与解答” (Q&A)页里会有解说。 本书对C语言的指针和结构体的说明与其他书籍有很大区别。这是因为本书先讲CPU的基本结构,然后讲汇编,最后再讲C语言,而其他的书都不讲这些基础知识,刚一提到指针,马上就转到变量地址如何如何了。所以就算大家“觉得”已经明白了那些书里讲的指针,也不要把本书的指针部分跳过去,相信这次大家能真正地理解指针。当然,如果真的已经弄明白了的话,大概看看就可以了。 从现在开始我们来一点一点地开发操作系统,我们会将每个阶段的进展情况总结出来,这些中间成果都刻在附带光盘里了,只要简单地复制一下就能马上运行。关于这些程序,有些需要注意的地方,我们在这里简单说明一下。 比如最初出现的程序是“helloos0” ,下一个出现的程序是“helloos1” 。 即使我们以helloos0 http:/hrb.osask.jp。 7 10 第 0天:着手开发之前 为基础,把书中讲解的内容一个不漏地全部做上一
20、遍,也不能保证肯定可以得到后面的helloos1。书中可能偶尔有讲解得很完整的地方,但其实大多部分都讲得不够明确,这主要是因为笔者觉得这些地方不讲那么仔细大家肯定也能明白。 笔者说这些主要就是想要告诉大家,不仅要看书里的内容,更要好好看程序。有时候书上写得很含糊,读起来晦涩难懂,但一看程序马上就明白了。本书的主角不是正文内容,而是附录中的程序。正文仅仅是介绍程序是如何做出来的。 所以说从这个意义上讲,与其说这是“一本附带光盘的书” ,倒不如说这是“一张附带一本大厚书的光盘” (笑) 。 关于程序还有一点要说明的这里收录的程序的版权全部归笔者所有。可是,读了这本书后打算开发自己的操作系统的话,可能有不少地方要仿照着附带程序来做;也有人可能想把程序的前期部分全盘照搬过来用;还有人可能想接着本书最后的部分继续开发自己的操作系统。 这是一本关于操作系统的教材,如果大家有上面这些想法却不能自由使用附录程序的话,这教材也就没什么意义了,所以大家可以随意使用这些程序,也不用事先提出任何申请。尽管大家最后做出来的操作系统中可能会包含笔者编写的程序,不过也不用在版权声明中署上笔者的名字。大家可以把它当作
21、自己独立开发的操作系统,也可以卖了它去赚钱。就算大家靠这个系统成了亿万富翁,笔者也不会要分毫的分成,大家大可放心。 而且这不只是买了本书的人才能享受的特权,从图书馆或朋友那儿借书看的人,甚至在书店里站着只看不买的人,也都享有以上权利。当然,大家要是买了这本书,对笔者、对出版社都是一个帮助。 (笑) 在引用本书程序时,只有一点需要注意,那就是大家开发的操作系统的名字。因为它已经不是笔者所开发的操作系统了,所以请适当地改个名字,以免让人误解,仅此一点请务必留意。不管程序的内部是多么相像,它都是大家自己负责发布的另外一个不同的操作系统。给它起个响亮的名字吧。 以上声明仅适用于书中的程序,以及附带光盘中收录的用作操作系统教材的程序。本书正文和附带光盘中的其他工具软件不在此列。复制或修改都受到著作权法的保护。请在法律允许范围内使用这些内容。与光盘中的工具软件相关的许可权会放在本书最后一章予以说明。 在版权署名时,如果有人执意要署上笔者的名字,笔者也不反对。另外,要是大家一不小心发了大财,一定要给笔者分红的话,笔者当然也会心存感激地接受下来(笑) 。 8 各章内容摘要 11 0 3 20 21 8
22、 10 16 9 22 7 12 11 13 15 14 15 8 各章内容摘要 估计看过目录大家就能大概了解各章内容了,但因为目录里项目太多,所以在这里概括总结一下。如果有人想要保留一份神秘感,想边看边猜“后面的内容会是什么” ,那么可以跳过本节不读(笑) 。这一部分可以说是全书的灯塔,当大家在阅读本书的过程中感觉有什么不放心的时候,就回过头来重新看看本节内容吧。 第一周(第1天 第7天) 一开始首先要考虑怎么来写一个 “只要一通电就能运行的程序” 。 这部分用C语言写起来有些困难,所以主要还是用汇编语言来写。 这步完成之后,下一步就要写一个从磁盘读取操作系统的程序。这时即便打开电脑电源,它也不会自动地将操作系统全部都读进来,它只能读取磁盘上最开始的512字节的内容,所以我们要编写剩余部分的载入程序。这个程序也要用汇编语言编写。 一旦完成了这一步,以后的程序就可以用C语言来编写了。我们就尽快使用C语言来学习开发显示画面的程序。同时,我们也能慢慢熟悉C语言语法。这个时候我们好像在做自己想做的事,但事实上我们还没有自由操纵C语言。 接下来,为了实现“移动鼠标”这一雄心,我们要对CPU进行
23、细致的设定,并掌握中断处理程序的写法。从全书总体看来,这一部分是水平相当高的部分,笔者也觉得放在这里有些不妥,但从本书条理上讲,这些内容必须放在这里,所以只好请大家忍耐一下了。在这里,CPU的规格以及电脑复杂的规格都会给我们带来各种各样的麻烦。 而且开发语言既有C语言, 又有汇编语言,这又给我们造成了更大的混乱。这个时候我们一点儿也不会觉得这是在做自己想做的事,怎么看都像是在“受人摆布” 。 渡过这个痛苦的时期,第一周就该结束了。 第二周(第8天 第14天) 一周的苦战还是很有意义的,回头一看,我们就会发现自己还是斩获颇丰的。这时我们已经基本掌握了C语言的语法,连汇编语言的水平也能达到本书的要求了。 所以现在我们就可以着手开发像样的操作系统了。但是这一次我们又要为算法头痛了。即使掌握了编程语言的语法,如果不懂得好的算法的话,也还是不能开发出来自己想要的操作系统。所以这一周我们就边学习算法边慢慢地开发操作系统。不过到了这一阶段,我们就能感觉到基本上不会再受技术问题限制了。 8 12 第 0天:着手开发之前 第三周(第15天 第21天) 现在我们的技术已经相当厉害了,可以随心所欲地开发自己
24、的操作系统了。首先是要支持多任务,然后是开发命令行窗口,之后就可以着手开发应用程序了。到本周结束时,就算还不够完备,我们也能拿出一个可以称之为操作系统的软件了。 第四周(第22天 第28天) 在这个阶段,我们可以尽情地给操作系统增加各种各样的功能,同时还可以开发出大量像模像样的应用程序来。这个阶段我们已经能做得很好了,这可能也是我们最高兴的时期。这部分要讲解的内容很少,笔者也不用再煞费苦心地去写那些文字说明了,可以把精力都集中在编程上(笑) 。对了,说起文字才想起来,正好在这个时期可以让我们的操作系统显示文字了。 免费赠送两天(第29天 第30天) 剩下的两天用来润色加工。这两天我们来做一些之前没来得及做,但做起来既简单又有趣的内容。 以上就是从第1天到第30天的内容摘要,越到后面介绍越短,这也说明最开始的内容是最复杂的。那么,就让我们做好准备,开始第一天的学习吧。啊,大家不用紧张,放松!放松! 从计算机结构到汇编程序入门 先动手操作 究竟做了些什么 初次体验汇编程序 加工润色 1 先动手操作 与其啰啰嗦嗦地写上一大堆,还不如实际动手开发来得轻松,我们这就开始吧。而且我们一上来就完全抛
25、开前面的说明,既不用C语言,也不用汇编程序,而是采用一个迥然不同的工具来进行开发(笑) 。 有一种工具软件名为“二进制编辑器” (Binary Editor),是一种能够直接对二进制数进行编辑的软件。我们现在要用它来编辑出下图这样的文件。 也许有人会说“这样的工具我从来没有见过呀” ,没关系,下面我们来详细地介绍一下。 首先打开下面这个网页: http:/www.zob.ne.jp/c.mos/soft/bz.html 原文直译为“二进制编辑器” (Binary Editor) ,在中国“二进制编辑器” 、 “十六进制编辑器”这两种说法都有,这里尊重原著保留了“二进制编辑器”的说法。译者注 如果此网页连接不上,也可用google等检索工具来搜索一下,从别处下载Bz1621.lzh。 第 1 天 1 14 第 1天:从计算机结构到汇编程序入门 用BZ打开helloos.img时的画面 点击“在此下载” (Download)的链接,下载文件Bz1621.lzh (在此非常感谢c.mos公司无偿公开这么好的软件) 。当你读到本书的时候,也许会有新的版本发布,所以文件名可能会有所不同。接下来,
26、安装下载下来的文件,然后双击启动Bz.exe程序。如果不能正常启动的话,可以参考上面网页的“注意”一项,按照上面的安装指导进行操作。 顺利启动的话屏幕上会出现如下画面。 BZ起动时的画面 好,让我们赶紧来输入吧,只要从键盘上直接输入EB4E904845就可以了,简单吧。其中字符之间的空格是这个软件在显示时为方便阅读自动插入的,不用自己从键盘上输入。另外,右边的.N.HELLOIPL部分,也不用从键盘输入,这是软件自动显示的。可能版本或者显示模式不一样的时候,右侧显示的内容会与下面的截图有所不同。不过不用往心里去,这些内容完全是锦上添花的东西,即使不一样也没事。 输入到000037位置时的画面 1 先动手操作 15 1 1 3 20 21 8 10 16 9 22 7 12 11 13 15 14 从000090开始后面全都是00,一直输入到最后168000这个地址。如果一直按着键盘上的“0”不放手的话,画面上的0就会不停地增加,但因为个数相当多,也还是挺花时间的。如果家里有只猫的话, 倒是可以考虑请它来帮忙按住这个键 (日本的谚语: 想让猫来搭把手, 形容人手不足,连猫爪子都想借用一下
27、) ,或者也可以干脆就用透明胶把这个键粘上。 168000附近的画面 因为一下子输入到最后实在是挺花时间的,大家也许想保存一下中间结果,这时可以从菜单上选择“文件” (File)“另存为” (Save As) ,画面上就会弹出保存文件的对话框。我们可以随便取个名字进行保存,笔者推荐使用“helloos.img” 。当想要打开保存过的文件时,首先要启动Bz.exe,从菜单上选择“文件” (File)“打开” (Open) ,然后选择目标文件,这样原来保存的内容就能显示出来了。可是这个时候不管我们怎么努力按键盘,它都一点反应也没有。这是怎么回事?难道必须要一次性输入到最后吗?这个大家不必担心,其实只要从菜单里选择“编辑”(Edit)“只读” (Read Only)就可以进入编辑状态啦。好了,我们继续输入。 如果家里的猫自由散漫惯了,不肯帮忙,而大家又不想用透明胶粘键盘这种土方法的话,不妨这样:用鼠标选择一部分0,然后从菜单选择“编辑” (Edit)“复制” (Copy) 。简简单单复制粘贴几次就可以大功告成了,这工具还真方便呀。 哦,对了,差点忘记一件重要的事在地址0001F0和00140
28、0附近还有些地方不全是00,要像下图那样把它们也改过来,然后整体检查一下,确认没有输入错误。 0001F0附近 16 第 1天:从计算机结构到汇编程序入门 001400附近 下面,我们把输入的内容保存下来就完成了软盘映像文件的制作,这时查看一下文件属性,应该能看到文件大小正好是1474560字节(=14401024字节) 。然后我们将这个文件写入软盘(具体后述) ,并用它来启动电脑。如下所示,画面上会显示出“hello, world”这个字符串。目前的程序虽然简单,但毕竟一打开电脑它就能够自动启动,还能在屏幕上显示出一句话来,已经小小成功了哦。不过,我们现在还没有结束这个程序的方法,所以想要结束的时候,只能把软盘取出来后切断电脑电源,或者重新启动。 至于最关键的往磁盘上写映像文件的方法,笔者已经预先准备好了一个程序。在介绍它的使用方法之前,我们先把笔者准备的工具全都安装进来吧,这样后面讲解起来比较省事。下面我们就来看怎么安装这些工具。 打开附带光盘,里面有一个名为tolset的文件夹,把这个文件夹复制到硬盘的任意一个位置上。现在里面的东西还不多,只有3MB左右,不过以后我们自己开发的软
29、件也都要放到这个文件夹里, 所以往后它会越来越大, 因此硬盘上最好留出100MB左右的剩余空间。 工具安装到此结束,我们既不用修改注册表,也不用设定路径参数,就这么简单。而且以后不管什么时候,都可以把这整个文件夹移动到任何其他地方。用这些工具,我们不仅可以开发操作系统,还可以开发简单的Windows应用程序或OSASK应用程序等。 tool set的缩写, “工具套件”的意思。 1 先动手操作 17 1 1 3 20 21 8 10 16 9 22 7 12 11 13 15 14 接下来我们打开刚才安装的tolset文件夹, 在文件夹的名字上单击鼠标右键, 从弹出的菜单上选择 “新建” (New) “文件夹” (Folder) 。 画面上会显示出缺省的文件夹名 “新建文件夹” (New Folder) ,我们要把它改为“helloos0” ,并把前面保存的映像文件helloos.img复制到这个文件夹里。另外,刚才安装的tolset文件夹下有个名为z_new_w的子文件夹,其中有!cons_9x.bat和!cons_nt.bat这两个文件,要把它们也复制粘贴到helloos0文件夹里
30、。 接着,在文件夹helloos0里单击鼠标右键,从弹出的菜单中选择“新建” (New)“文本文件” (Text Document) ,并将文件命名为“run.bat” ,回车后屏幕上会显示“如果改变文件扩展名,可能会导致文件不可用。确实要更改吗?”的对话框,我们选择“是” ,创建run.bat文件。然后在run.bat文件名上单击鼠标右键,在弹出的菜单上选择“编辑” (Edit) ,输入下面内容并保存。 run.bat copy helloos.img ./z_tools/qemu/fdimage0.bin ./z_tools/make.exe -C ./z_tools/qemu 然后按照同样的步骤,创建install.bat,并将下列内容输入进去。 install.bat . /z_tools/ w a: helloos.img 其实以上步骤创建的所有文件都已经给事先给大家准备好了,就放在附带光盘中名为projects01_dayhelloos0的子文件夹里。所以大家只要把光盘上的helloos0复制下来,粘帖到硬盘的tolset文件夹里,所有的准备工作就瞬间完成了。 好了,现在我
31、们就来把这个有点像操作系统的软件安装到软盘上吧。随便从附近的小店里买片新软盘来, 在Windows下格式化一下 (格式化方法: 把软盘插入磁盘驱动器后打开 “我的电脑” ,在“3.5吋软盘” (3.5inches Floppy)A:上单击鼠标右键,再选择“格式化” (Format)即可) 。对了, 这个时候不要选择 “快速格式化” 选项。 然后用鼠标左键双击helloos0文件夹里的 !cons_nt.bat文件(Windows95/98/Me的用户需要双击!cons_9x.bat) ,屏幕上就会出现一个命令行窗口(console) 。我们先仔细确认一下软盘是否已经插好,然后在命令行窗口上输入“install”并回车,这样安装操作就开始了。稍候片刻,等安装程序执行完毕,我们的操作系统启动盘也就做好了。完成安装之后,也可以关闭刚才的命令行窗口了。 现在我们就用这张操作系统启动软盘来启动一下电脑试试吧,肯定跟刚才一样,会显示出“hello, world”的字样来。 在这里要提醒大家几点:一是软盘虽然不要求必须用全新的,但如果太旧的话,在读写过程18 第 1天:从计算机结构到汇编程序入门 中
32、容易出问题,所以最好还是不要用太旧的软盘。另外,就算是新盘,如果太便宜的话有时也用不了, 若是发现有问题, 就需要再去买一张。 最后一点, 一旦格式化或者往软盘内安装操作系统,就会把里面原有的东西全部覆盖掉,所以大家千万不要用存有重要文件的软盘来尝试哦。 看到这里,大家可能会有各种问题: “这些我都明白,可是既要专门去买张软盘,又要重启电脑,实在太麻烦了,难道就没有什么更简单的方法吗?” 、 “我家的电脑根本就没有软驱呀” 、“我的电脑没有什么重启按钮,也没有关电源的开关,一旦启动了这个奇怪的操作系统,就没法终止啦” 。其实这些问题笔者已经考虑到了,所以特意准备了一个模拟器。我们有了这个模拟器,不用软盘,也不用终止Windows,就可以确认所开发的操作系统启动以后的动作,很方便呢。 使用模拟器的方法也非常简单,我们只需要在用!cons_nt.bat(或者是!cons_9x.bat)打开的命令行窗口中输入“run”指令就可以了。然后一个名叫QEMU的非常优秀的免费PC模拟器就会自动运行。QEMU不是笔者开发的,它是由国外的一些天才们开发出来的。感谢他们! “我按照你说的一步一步地做了一遍
33、,可是不行呀!怎么回事呢?”会遇到这种情况的人肯定是个非常认真的人,可能真的完全按照上面步骤用二进制编辑器自己做了一个helloos.img文件出来。出现这种问题,肯定是因为文件中有输入错误的地方,虽然笔者不知道具体错在哪儿,不过建议最好检查一下000000到000090,以及0001F0前后的数据。如果还是不行的话,那就干脆用附带光盘中笔者做的helloos.img好了。 可能有些人嫌麻烦,懒得自己输入,上来就直接使用光盘里的helloos.img文件,这当然也没什么不可以;但笔者认为这种体验(一点一点地输入,再千辛万苦地纠错,最终功夫不负有心人取得成功)本身更难能可贵,建议大家最好还是亲自尝试一下。 就这样, 我们没有去改造现成的操作系统, 而是从零开始开发了一个, 并让它运转了起来 (当然,如果别人承认这是个操作系统的话) 。这太了不起了!大家完全可以在朋友们面前炫耀一番了。仅学习了几个小时开发的一个初学者,就能从零开始做出一个操作系统,这本书不错吧(笑)?这次我们考虑到从键盘直接输入比较麻烦,所以就只让它显示了一条消息;如果能再多输入一些内容的话,那仅用这种方法就可以开发任意一
34、个操作系统(当然最大只能到1440KB) 。现在唯一的问题是,我们还不知道之前输入的那些“EB 4E 90 48 45”到底是什么意思(而这也正是我们所面临的最大问题) 。今天剩下的时间,以及以后的29天时间里,我们都会讲解这个问题。 2 究竟做了些什么 19 1 1 3 20 21 8 10 16 9 22 7 12 11 13 15 14 2 究竟做了些什么 为什么用这种方法就能开发出操作系统来呢?现在搞清楚这个问题, 会对我们今后的理解很有帮助,所以在这里要稍做说明。 首先我们要了解电脑的结构。电脑的处理中心是CPU,即“central process unit”的缩写,翻译成中文就是“中央处理单元” ,顾名思义,它就是处理中心。如果我们把别的元件当作中心来使用的话,那它就叫做CPU了,所以无论什么时候CPU都总是处理中心。不过这个CPU除了与别的电路进行电信号交换以外什么都不会,而且对于电信号,它也只能理解开(ON)和关(OFF)这两种状态,真是个没用的人呀(虽然它不是人吧,大家领会精神) 。 CPU 我们平时会用电脑写文章、听音乐、修照片以及做其他各种各样的事情,我们用电脑所
35、做的这些,其实本质上都不过是在与CPU交换电信号而已,而且电信号只有开(ON)和关(OFF)这两种状态。再说直白一点,CPU根本无法理解文章的内容,更不会鉴赏音乐、照片,它只会机械地进行电信号的转换。CPU有计算指令,所以它能够进行整数的加减乘除运算,也可以处理负数、计算小数以及10的100次方这样庞大的数值,它甚至能够处理我们初中才学到的平方根和高中才学到的对数、三角函数,而且所有这些计算仅通过一条指令就能简单实现。虽然CPU功能如此强大,但它其实根本不理解数的概念。CPU就是个集成电路板,它只是忠实地执行电信号给它的指令,输出相应的电信号。 这些概念可能不太容易理解,还是让我们来看个的具体例子吧。比如说,让我们用1来表示开 (ON) , 用0来表示关 (OFF) , 这样比较容易理解。 我们可以用3216=512个开 (ON) 和关 (OFF)的集合(电信号的集合) ,来显示出下面这个不甚好看的人头像。 2 20 第 1天:从计算机结构到汇编程序入门 我们也可以用0000 0000 0000 0000 0000 0100 1010 0010 这32个电信号的集合来表示1186这个整
36、数。 (注: 用二进制表示1186的话, 就是100 1010 0010) 。 我们还可以用0100 1011 0100 1111 0100 1111 0100 0010这32个电信号的集合来表示“BOOK”这个单词(注:这实际上就是电脑内部保存这个单词时的电信号集合) 。 CPU能看见的就只有这些开(ON)和关(OFF)的电信号。换句话说,假如我们给CPU发送这么一串电信号: 0000 0100 0011 1000 0000 1110 0001 0000 这信号可能是一幅画的部分数据,可能是个二进制整数,可能是一段音乐旋律,可能是文章中的一段文字, 也可能是保存了的游戏的一部分数据, 或者是程序中的一行代码, 不管它是什么,CPU都一窍不通。CPU不懂这些,也不在乎这些,它只是默默地、任劳任怨地按照程序的指令进行相应的处理。 看到这里,或许有人会认为是先有了这么多要做的事情,所以人类才发明了CPU,而实际上并不是这样。最早人们发明CPU只是为了处理电信号,那个时候没有人能想到它后来会成为这么有用的机器。不过后来人们发现,一旦把电信号的开(ON)/关(OFF)与数字0和1对应起来,就能
37、将二进制数转换为电信号,同时电信号也可以转换回二进制数。所以,虽然CPU依然只能处理电信号,但它从此摇身一变,成了神奇的二进制数计算机。 因为我们可以把十进制数转换成二进制数,也能把二进制数还原成十进制数,所以人们又发明了普通的计算机。后来,我们发现只要给每个文字都编上号(即文字编码) ,就可以建立一个文字与数字的对应关系,从而就可以把文字也转换成电信号,让CPU来处理文章(比如进行文字输入或者字词检索等) 。依此类推,人们接着又找到了将图像、音乐等等转换成电信号的方法,使CPU的应用范围越来越广。不过CPU还是一如既往,只能处理电信号。 而且我们能用CPU来处理的并不仅仅只有数据,我们还可以用电信号向CPU发出指令。其实我们所编写的程序最终都要转换成所谓的机器语言,这些机器语言就是以电信号的形式发送给CPU的。这些机器语言不过就是一连串的指令代码,实际上也就是一串0和1的组合而已。 软盘的原理也有异曲同工之妙,简单说来,就是把二进制的0和1转换为磁极的N极和S极而已,所以我们只用0和1就可以写出映像文件来。不仅是映像文件,计算机所能处理的各种文件最终都是用0和1写成的。因此可以说,不
38、能仅用0和1来表达的内容,都不能以电信号的形式传递给CPU,所以这种内容是计算机所无法处理的。 而“二进制编辑器”就是用来编辑二进制数的,我们可以很方便地用它来输入二进制数,并2 究竟做了些什么 21 1 1 3 20 21 8 10 16 9 22 7 12 11 13 15 14 保存成文件。所以它就是我们的秘密武器,也就是说只要有了二进制编辑器,随便什么文件我们都能做出来。 (厉害吧! )如果大家在商店里看到一个软件,很想要而又不想花那么多钱的话,那就干脆就回家用二进制编辑器自己做一个算啦! 用这个方法我们完全可以自己制作出一个与店里商品一模一样的东西来。看上一个500万像素的数码相机,但是太贵了买不起?那有什么关系?我们只要有二进制编辑器在手,就可以制作出毫不逊色于相机拍摄效果的图像,而且想做几张就可以做几张。要是C编译器太贵了买不起,也不用郁闷。即使没有C编译器,我们也可以用二进制编辑器做出一个与编译器生成文件完全一样的执行文件,而且就连C编译器本身都可以用二进制编辑器做出来。 有了这么强大的工具,制作操作系统就是小菜一碟。道理就是这么简单,所以我们这次不费吹灰之力就做了个操
39、作系统出来也是理所当然的。或许有人会想“就为了讲这么个小事,有必要长篇大论写这么多吗?”其实不然,如果我们对CPU的基础有了彻底的理解,以后的内容就好懂多了。 “喂,且慢,我明白了二进制编辑器就是编辑二进制数的软件,可是在你让我输入你的helloos.img的时候,除了0和1以外,不是还让我输入了很多别的东西吗?你看,第一个不就是E吗?这哪里是什么二进制数?分明是个英文字母嘛! ”噢,不好意思,这说得一点错都没有。 虽然二进制数与电信号有很好的一一对应关系,但它有一个缺点,那就是位数实在太多了,举个例子来说,如果我们把1234写成二进制数,就成了10011010010,居然长达11位。而写成十进制数,只用4位就够了。因为这样也太浪费纸张了,所以计算机业界普遍使用十六进制数。十进制数的1234写成十六进制数,就是4D2,只用3位就够了。 那为什么非要用十六进制数呢,用十进制数不是也挺好的吗?实际上,我们可以非常简便地把二进制数写成十六进制数。 二进制数和十六进制数对照表 0000 0 0100 4 1000 8 1100 C 0001 1 0101 5 1001 9 1101 D 001
40、0 2 0110 6 1010 A 1110 E 0011 3 0111 7 1011 B 1111 F 有了这个对照表,我们就能轻松进行二进制与十六进制之间的转换了。将二进制转换为十六进制时,只要从二进制数的最后一位开始,4位4位地替换过来就行了。如: 100 1101 0010 4D2 反之,把十六进制数的4D2转换为二进制数的100 1101 0010也很简单,只要用上面的对照表反过来变换一下就行了。而十进制数变换起来就没这么简单了。同理,八进制数是把3位一组的22 第 1天:从计算机结构到汇编程序入门 二进制数作为一个八进制位来变换的,这种计数法在计算机业界也偶有使用。 因此我们在输入EB的时候,实际上是在输入11101011,所以它其实是个十六进制编辑器,但笔者习惯称它为二进制编辑器,希望大家不要见怪。 虽然笔者对二进制编辑器如此地赞不绝口,但用它也解决不了什么实际问题。因为这就相当于“只要有了笔和纸,什么优秀的小说都能写出来”一样。笔和纸不过就是笔和纸而已,实际上对创作优秀的小说也帮不上多大的忙。所以大家在写程序时,用的都是文本编辑器和编译器,没有谁只用二进制编辑器来做程序
41、的。大家照相用的也都是数码照相机,没有谁只用二进制编辑器来做图像文件。因此,我们用二进制编辑器进行的开发就到此为止,接下来我们要调转方向,开始用编程语言来继续我们的开发工作。不过有了这次的经验,我们就知道了如果今后遇到什么特殊情况还可以使用二进制编辑器,它是非常有用的。而且后面章节中我们偶尔也会用到它。 3 初次体验汇编程序 好, 现在就让我们马上来写一个汇编程序, 用它来生成一个跟刚才完全一样的helloos.img吧。我们这次使用的汇编语言编译器是笔者自己开发的,名为“nask” ,其中的很多语法都模仿了自由软件里享有盛名的汇编器“NASM” ,不过在“NASM”的基础之上又提高了自动优化能力。 超长的源代码 DB 0xeb, 0x4e, 0x90, 0x48, 0x45, 0x4c, 0x4c, 0x4f DB 0x49, 0x50, 0x4c, 0x00, 0x02, 0x01, 0x01, 0x00 DB 0x02, 0xe0, 0x00, 0x40, 0x0b, 0xf0, 0x09, 0x00 DB 0x12, 0x00, 0x02, 0x00, 0x00, 0x00,
42、0x00, 0x00 DB 0x40, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x29, 0xff (为节省纸张,这里省略中间的18万4314行) DB 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 我们使用复制粘帖的方法, 就可以写出这样一个超长的源代码来, 将其命名为 “helloos.nas” ,并保存在helloos0中。仔细看一下就能发现这个文件内容与我们用二进制编辑器输入的内容是一模一样的。 接着,我们用“!cons_nt.bat”或是“!cons_9x.bat” (我们在前面已经说过,要根据Windows的版本决定用哪一个。 以后每次都这样解释一遍的话比较麻烦, 所以我们就将它简写为!cons好了) 打开一个命令行窗口(console) ,输入以下指令(提示符部分不用输入) : 提示符.z_toolsnask.exe helloos.nas helloos.img prompt,出现在命令行窗口中,提示用户进行输入的信息。 3 3 初次体验汇编程序 23 1 1 3 20 21 8 10 16 9 22
43、 7 12 11 13 15 14 这样我们就得到了映像文件helloos.img。 好,我们的第一个汇编语言程序就这样做成了!不过这么写程序也太麻烦了,要做个18万行的程序, 不但浪费时间, 还浪费硬盘空间。 与其这样还不如用二进制编辑器呢, 不用输入 “0x” 、“,”什么的,还能轻松一点。 其实要解决这个问题并不难,如果我们不只使用DB指令,而把RESB指令也用上的话,就可以一下将helloos.nas缩短了,而且还能保证输出的内容不变,具体我们来看下面。 正常长度的源程序 DB 0xeb, 0x4e, 0x90, 0x48, 0x45, 0x4c, 0x4c, 0x4f DB 0x49, 0x50, 0x4c, 0x00, 0x02, 0x01, 0x01, 0x00 DB 0x02, 0xe0, 0x00, 0x40, 0x0b, 0xf0, 0x09, 0x00 DB 0x12, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 DB 0x40, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x29, 0xff DB 0xff
44、, 0xff, 0xff, 0x48, 0x45, 0x4c, 0x4c, 0x4f DB 0x2d, 0x4f, 0x53, 0x20, 0x20, 0x20, 0x46, 0x41 DB 0x54, 0x31, 0x32, 0x20, 0x20, 0x20, 0x00, 0x00 RESB 16 DB 0xb8, 0x00, 0x00, 0x8e, 0xd0, 0xbc, 0x00, 0x7c DB 0x8e, 0xd8, 0x8e, 0xc0, 0xbe, 0x74, 0x7c, 0x8a DB 0x04, 0x83, 0xc6, 0x01, 0x3c, 0x00, 0x74, 0x09 DB 0xb4, 0x0e, 0xbb, 0x0f, 0x00, 0xcd, 0x10, 0xeb DB 0xee, 0xf4, 0xeb, 0xfd, 0x0a, 0x0a, 0x68, 0x65 DB 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x77, 0x6f, 0x72 DB 0x6c, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00
45、 RESB 368 DB 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa DB 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 RESB 4600 DB 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 RESB 1469432 我们自己动手输入这段源程序比较麻烦,所以笔者把它放在附带光盘的projects01_day helloos1目录下了。 大家只要把helloos1文件夹复制粘帖到tolset文件夹里就可以了。 之前的helloos0文件夹以后就不用了, 我们可以把它删除, 也可以放在那里留作纪念。 顺便说一下, 笔者将helloos0文件夹名改为了helloos1,删掉了其中没用的文件,新建并编辑了需要用到的文件,这样就做出了新的helloos1文件夹。操作系统就是这样一点一点地成长起来的。 每次进行汇编编译的时候,我们都要输入刚才的指令,这太麻烦了,所以笔者就做了一个批处理文件asm.bat。 有了这个批处理文件, 我们只要在用 “!con
46、s” 打开的命令行窗口里输入 “asm” , batch file,基本上只是将命令行窗口里输入的命令写入文本文件。虽然还有功能更强的处理,但本书中我们用不到。所谓批处理就是批量处理,即一次处理一连串的命令。 24 第 1天:从计算机结构到汇编程序入门 就可以生成helloos.img文件。在用“asm”作成img文件后,再执行“run”指令,就可以得到与刚才一样的结果。 DB指令是“data byte”的缩写,也就是往文件里直接写入1个字节的指令。笔者喜欢用大写字母来写汇编指令,但小写的“db”也是一样的。 在汇编语言的世界里,这个指令是程序员的杀手锏,也就是说只要有了DB指令,我们就可以用它做出任何数据(甚至是程序) 。所以可以说,没有用汇编语言做不出来的文件。文本文件也好,图像文件也好,只要能叫上名的文件,我们都能用汇编语言写出来。而其他的语言(比如C语言)就没有这么万能。 RESB指令是“reserve byte”的略写,如果想要从现在的地址开始空出10个字节来,就可以写成RESB 10,意思是我们预约了这10个字节(大家可以想象成在对号入座的火车里,预订了10个连号座位的情形
47、) 。而且nask不仅仅是把指定的地址空出来,它还会在空出来的地址上自动填入0x00,所以我们这次用这个指令就可以输出很多的0x00,省得我们自己去写18万行程序了,真是帮了个大忙。 这里还要说一下,数字的前面加上0x,就成了十六进制数,不加0x,就是十进制数。这一点跟C语言是一样的。 4 加工润色 刚才我们把程序变成了短短的22行,这成果令人欣喜。不过还有一点不足就是很难看出这些程序是干什么的,所以我们下面就来稍微改写一下,让别人也能看懂。改写后的源文件增加到了48行,它位于附带光盘的projects01_dayhelloos2目录下,大家可以直接把helloos2文件夹复制到tolset里。现在helloos1也可以删掉了(每个文件夹都是独立的,用完之后就可以删除,以后不再赘述。当然放在那里留作纪念也是可以的) 。 现在的程序有50行,也占不了多少地方,所以我们将它写在下面了。 有模有样的源代码 ; hello-os ; TAB=4 ; 以下这段是标准FAT12格式软盘专用的代码 DB 0xeb, 0x4e, 0x90 DB HELLOIPL ; 启动区的名称可以是任意的字符串(8
48、字节) DW 512 ; 每个扇区(sector)的大小(必须为512字节) DB 1 ; 簇(cluster)的大小(必须为1个扇区) 4 4 加工润色 25 1 1 3 20 21 8 10 16 9 22 7 12 11 13 15 14 DW 1 ; FAT的起始位置(一般从第一个扇区开始) DB 2 ; FAT的个数(必须为2) DW 224 ; 根目录的大小(一般设成224项) DW 2880 ; 该磁盘的大小(必须是2880扇区) DB 0xf0 ; 磁盘的种类(必须是0xf0) DW 9 ; FAT的长度(必须是9扇区) DW 18 ; 1个磁道(track)有几个扇区(必须是18) DW 2 ; 磁头数(必须是2) DD 0 ; 不使用分区,必须是0 DD 2880 ; 重写一次磁盘大小 DB 0,0,0x29 ; 意义不明,固定 DD 0xffffffff ;(可能是)卷标号码 DB HELLO-OS ; 磁盘的名称(11字节) DB FAT12 ; 磁盘格式名称(8字节) RESB 18 ; 先空出18字节 ; 程序主体 DB 0xb8, 0x00, 0x00,
49、0x8e, 0xd0, 0xbc, 0x00, 0x7c DB 0x8e, 0xd8, 0x8e, 0xc0, 0xbe, 0x74, 0x7c, 0x8a DB 0x04, 0x83, 0xc6, 0x01, 0x3c, 0x00, 0x74, 0x09 DB 0xb4, 0x0e, 0xbb, 0x0f, 0x00, 0xcd, 0x10, 0xeb DB 0xee, 0xf4, 0xeb, 0xfd ; 信息显示部分 DB 0x0a, 0x0a ; 2个换行 DB hello, world DB 0x0a ; 换行 DB 0 RESB 0x1fe-$ ; 填写0x00,直到 0x001fe DB 0x55, 0xaa ; 以下是启动区以外部分的输出 DB 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 RESB 4600 DB 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 RESB 1469432 这里有几点新内容,我们逐一来看一下。首先是“;”命令,这是个注释命令,相当于C语言或是C+
50、中的“/” 。正是因为有它,我们才可以在源代码里加入很多注释。 其次是DB指令的新用法。我们居然可以直接用它写字符串。在写字符串的时候,汇编语言会自动地查找字符串中每一个字符所对应的编码,然后把它们一个字节一个字节地排列起来。这个功能非常方便,也就是说,当我们想要变更输出信息的时候,就再也不用自己去查字符编码表了。 26 第 1天:从计算机结构到汇编程序入门 再有就是DW指令和DD指令,它们分别是“data word”和“data double-word”的缩写,是DB指令的“堂兄弟” 。word的本意是“单词” ,但在计算机汇编语言的世界里,word指的是“16位”的意思,也就是2个字节。 “double-word”是“32位”的意思,也就是4个字节。 对了,差点忘记说RESB 0x1fe-$了。这个美元符号的意思如果不讲,恐怕谁也搞不明白,它是一个变量,可以告诉我们这一行现在的字节数(如果严格来说,有时候它还会有别的意思,关于这一点我们明天再讲) 。 在这个程序里, 我们已经在前面输出了132字节, 所以这里的$就是132。因此nask先用0x1fe减去132,得出378这一结果,
51、然后连续输出378个字节的0x00。 那这里我们为什么不直接写378,而非要用$呢?这是因为如果将显示信息从“hello, world”变成“this is a pen.”的话,中间要输出0x00的字节数也会随之变化。换句话说,我们必须保证软盘的第510字节(即第0x1fe字节)开始的地方是55 AA。如果在程序里使用美元符号($)的话,汇编语言会自动计算需要输出多少个00,我们也就可以很轻松地改写输出信息了。 既然可以毫不费力地改写显示的信息,就一定要好好发挥这一功能,让我们的操作系统显示出自己喜欢的一句话,让它成为一个只属于我们自己的、世界上独一无二的操作系统。不过遗憾的是现在它还不能显示汉字。 当然大家也可以尝试一下, 但由于这个程序还没有显示汉字的功能,所以显示出来的都是乱码,因此大家先将就一下,用英语或拼音吧。 最后再给大家解释一下程序中出现的几个专门术语。时间不早了,我们今天就到这吧。其他的留待明天再说。 TAB=4.有的文本编辑器可以调整TAB键的宽度。请使用这种编辑器的人将TAB键的宽度设定成4,这样源程序更容易读。可能有人说,我这里只能用记事本(notepad) ,T
52、AB键宽度固定为8,想调都没法调。没关系,明天笔者来推荐一个好用的文本编辑器。 FAT12格式.(FAT12 Format)用Windows或MS-DOS格式化出来的软盘就是这种格式。我们的helloos也采用了这种格式,其中容纳了我们开发的操作系统。这个格式兼容性好,在Windows上也能用,而且剩余的磁盘空间还可以用来保存自己喜欢的文件。 启动区.(boot sector)软盘第一个的扇区称为启动区。那么什么是扇区呢?计算机读写软盘的时候,并不是一个字节一个字节地读写的,而是以512字节为一个单位进行读写。因此,软盘的512字节就称为一个扇区。一张软盘的空间共有1440KB,也就是1474560字节,除以512得2880,这也就是说一张软盘共有2880个扇区。那为什么第一个扇区称为启动区呢?那是因为计算机首先从最初一个扇区开始读软盘,然后去检查这个扇区最后2个字节的内容。 4 加工润色 27 1 1 3 20 21 8 10 16 9 22 7 12 11 13 15 14 如果这最后2个字节不是55 AA,计算机会认为这张盘上没有所需的启动程序,就会报一个不能启动的错误。(也许有
53、人会问为什么一定是55 AA呢?那是当初的设计者随便定的,笔者也没法解释)。如果计算机确认了第一个扇区的最后两个字节正好是55 AA,那它就认为这个扇区的开头是启动程序,并开始执行这个程序。 IPL.initial program loader的缩写。启动程序加载器。启动区只有区区512字节,实际的操作系统不像hello-os这么小,根本装不进去。所以几乎所有的操作系统,都是把加载操作系统本身的程序放在启动区里的。有鉴于此,有时也将启动区称为IPL。但hello-os没有加载程序的功能,所以HELLOIPL这个名字不太顺理成章。如果有人正义感特别强,觉得“这是撒谎造假,万万不能容忍!”,那也可以改成其他的名字。但是必须起一个8字节的名字,如果名字长度不到8字节的话,需要在最后补上空格。 启动.(boot)boot这个词本是长靴(boots)的单数形式。它与计算机的启动有什么关系呢?一般应该将启动称为start的。实际上,boot这个词是bootstrap的缩写,原指靴子上附带的便于拿取的靴带。但自从有了吹牛大王历险记(德国)这个故事以后,bootstrap这个词就有了“自力更生完成任务
54、”这种意思(大家如果对详情感兴趣,可以在Google上查找,也可以在帮助和支持网页http:/hrb.osask.jp上提问)。而且,磁盘上明明装有操作系统,还要说读入操作系统的程序(即IPL)也放在磁盘里,这就像打开宝物箱的钥匙就在宝物箱里一样,是一种矛盾的说法。这种矛盾的操作系统自动启动机制,被称为bootstrap方式。boot这个说法就来源于此。如果是笔者来命名的话,肯定不会用bootstrap 这么奇怪的名字,笔者大概会叫它“多级火箭式”吧。 多任务(1) 挑战任务切换(harib12a) 任务切换进阶(harib12b) 做个简单的多任务(1) (harib12c) 做个简单的多任务(2) (harib12d) 提高运行速度(harib12e) 测试运行速度(harib12f) 多任务进阶(harib12g) 1 挑战任务切换(harib12a) “话说,多任务到底是啥呢?”我们今天的内容,就从这个问题开始吧。 多任务, 在英语中叫做 “multitask” , 顾名思义就是 “多个任务” 的意思。 简单地说, 在Windows等操作系统中,多个应用程序同时运行的状态(也就
55、是同时打开好几个窗口的状态)就叫做多任务。 对于生活在现代社会的各位来说,这种多任务简直是理所当然的事情。比如你会一边用音乐播放软件听音乐一边写邮件,邮件写到一半忽然有点东西要查,便打开Web浏览器上网搜索。这对于大家来说这些都是家常便饭了吧。 可如果没有多任务的话会怎么样呢?想写邮件的时候就必须关掉正在播放的音乐,要查东西的时候就必须先保存写到一半的邮件,然后才能打开Web浏览器光想象一下就会觉得太不方便了。 然而在从前,没有多任务反倒是普遍的情形(那个时候大家不用电脑听音乐,也没有互联网) 。在那个年代,电脑一次只能运行一个程序,如果要同时运行多个程序的话,就得买好几台电脑才行。 就在那个时候,诞生了最初的多任务操作系统,大家都觉得太了不起了。从现在开始,我们也要准备给“纸娃娃系统”添加执行多任务的能力了。连这样一个小不点儿操作系统都能够实现多任务,真是让人不由地感叹它生逢其时呀。 第 15 天 1 1 挑战任务切换(harib12a) 283 1 2 3 4 5 8 10 15 9 6 7 12 11 13 14 14 稍稍思考一下我们就会发现,多任务这个东西还真是奇妙,它究竟是
56、怎样做到让多个程序同时运行的呢?如果我们的电脑里面装了好多个CPU的话,同时运行多个程序倒也顺理成章,但实际上就算我们只有一个CPU,照样可以实现多任务。 其实说穿了,这些程序根本没有在同时运行,只不过看上去好像是在同时运行一样:程序A运行一会儿,接下来程序B运行一会儿,再接下来轮到程序C,然后再回到程序A如此反复,有点像日本忍者的“分身术”呢(笑) 。 为了让这种分身术看上去更完美,需要让操作系统尽可能快地切换任务。如果10秒才切换一次,那就连人眼都能察觉出来了,同时运行多个程序的戏码也就穿帮了。再有,如果我们给程序C发出一个按键指令,正巧这个瞬间系统切换到了程序A的话,我们就不得不等上20秒,才能重新轮到程序C对按键指令作出反应。这实在是让人抓狂啊(哭) 。 在一般的操作系统中,这个切换的动作每0.010.03秒就会进行一次。当然,切换的速度越快,让人觉得程序是在同时运行的效果也就越好。不过,CPU进行程序切换(我们称为“任务切换” )这个动作本身就需要消耗一定的时间,这个时间大约为0.0001秒左右,不同的CPU及操作系统所需的时间也有所不同。如果CPU每0.0002秒切换一次任
《30天自制操作系统》由会员桔****分享,可在线阅读,更多相关《30天自制操作系统》请在金锄头文库上搜索。
2024-03-07 87页
2023-12-26 16页
2023-12-26 28页
2023-07-21 7页
2023-07-21 3页
2023-07-21 14页
2023-07-21 3页
2023-07-21 30页
2023-07-21 34页
2023-07-21 15页