目前为止,我一共买了2本电子书,第一本是在Ireader上花了2块钱买的《高效能人士的7个习惯》(虽然后面我又买了实体书,此书的书摘在这里),第二本是春节在家花了49.99买的这本《30天自制操作系统》(不过是我哥帮我付的款,^_^)。

花了49.99快买本电子书,我其实还是很心疼的,虽然用的不是我的钱,但毕竟是个虚拟的物品,我也知道电子书逐渐替代实体书是个趋势,可是对于用惯了免费软件或者看惯了免费电子书的我来说,这确实是个需要时间来逐渐接受,逐渐养成的观念。

好了,下面进入正题。《30天自制操作系统》确实在30天之后(当然看完此书我并没有花30天)得到了一个具有一些功能的操作系统。如果你还有一台具有软驱的电脑,并且你手头也有软盘的话,那么还可以将30天后的操作系统刻录到软盘上,选择从软盘启动电脑,在真机上体验自己的劳动成果。我家虽然有台含有软驱的古董级电脑(其实也还好,04年买的),但是已经不工作好几年了,我只能在虚拟机上体验了一把自己的操作系统。

os

看完这本书,我觉得对我的操作系统知识倒是没有什么很大的提高,倒是让我对c中的指针有了更加清楚的认识,书中用汇编知识来解释了为什么c中会有指针这个东西,并且通过几个小程序演示了c中的指针和汇编程序中对地址进行操作的一些相似性,使得c指针变得易懂易用。此书涉及的操作系统知识并不全面,只是将书中开发自制操作系统时涉及的相关知识引入了进来,这一方面便于读者理解知识及其作用,另一方面也使得整本书的阅读不会变得晦涩难懂,并且有一个很好的主干骨推动知识往前移动,使读者有一个良好的阅读节奏。

下面是此书的一些摘录。

1

因为这些原因,我们只能靠开发应用程序用的C编译器想方设法编写出一个操作系统来。这实际上是在硬来,所以当中就会有很多不方便的地方。就比如说printf( “hello\n ”); 吧,这个函数总是出现在C语言教科书的第一章,但我们现在就连它也无法使用。为什么呢?因为printf这个函数是以操作系统提供的功能为前提编写的,而我们最开始的操作系统可是什么功能都没有。因此,如果我们硬要执行这个函数的话,CPU 会发生一般保护性异常,直接罢工。刚开始的时候不仅是printf,几乎所有的函数都无法使用。

2

软盘的原理也有异曲同工之妙,简单说来,就是把二进制的0 和1 转换为磁极的N 极和S 极而已,所以我们只用0和1就可以写出映像文件来。

3

boot 这个词本是长靴(boots)的单数形式。它与计算机的启动有什么关系呢?一般应该将启动称为start 的。实际上,boot 这个词是bootstrap的缩写,原指靴子上附带的便于拿取的靴带。但自从有了《吹牛大王历险记》(德国)这个故事以后,bootstrap 这个词就有了“自力更生完成任务”这种意思。

4

AX、CX、 DX 、 BX 这几个寄存器的排列顺序,它并不遵循名称的字母顺序。没错,其实这是按照机器语言中寄存器的编号顺序排列的

5

柱面在英文中是cylinder,原意是圆筒。磁盘的柱面,尽管高度非常低,但我们可以把它看成是一个套一个的同心圆筒,它正是因此得名的。

6

可能会有人想,既然已经做成了机器语言,那只要把它写进映像文件里就万事大吉了。但很遗憾,这还不行,事实上这也正是使用C语言的不便之处。目标文件是一种特殊的机器语言文件,必须与其他文件链接(link )后才能变成真正可以执行的机器语言。链接是什么意思呢?实际上C语言的作者已经认识到,C语言有它的局限性,不可能只用C语言来编写所有的程序,所以其中有一部分必须用汇编来写,然后链接到C语言写的程序上。

7

C语言中,*(p + i )还可以改写成p[i]这种形式,所以以上片段也可以写成这样: 
p = (char *) 0xa0000; /*将地址赋值进去*/ 
for (i = 0; i <= 0xffff; i++) { 
    p[i] = i & 0x0f;或者i[p] = i & 0x0f 
} 

8

8“位”是一个字节,而1个字符是16个字节。

9

因此段上限只能使用20位。这样一来,段上限最大也只能指定到1MB为止。明明有4GB,却只能用其中的1MB,有种又回到了16位时代的错觉,太可悲了。在这里英特尔的叔叔们又想了一个办法,他们在段的属性里设了一个标志位,叫做Gbit。这个标志位是1的时候,limit的单位不解释成字节(byte),而解释成页(page)。页是什么呢?在电脑的CPU里,1页是指4KB。 这样一来,4KB × 1M = 4GB,所以可以指定4GB的段。总算能放心了。顺便说一句,Gbit的“G”,是“granularity”的缩写,是指单位的大小。

10

由于加入了哨兵,settime的状况就变了。4种情况中有2种情况是绝对不会发生的。(下面的第1种和第4种) 
	1 处于运行中的定时器只有这1个的情况(因为有哨兵,所以最少应该有2个) 
	2 插入最前面的情况 
	3 插入s和t之间的情况 
	4 插入最后的情况(哨兵总是在最后)	

11

大家是不是很纳闷:“画面模式有新旧之分吗?”是的,实际上是有新旧之分的。就说显卡吧,每当有新显卡面世时,性能就会提高,反过来想,以前的显卡,声音性能差,颜色数又少,分辨率又低。刚开始的时候,电脑规格是以IBM公司为中心决定的,他们也规定了画面模式的相关规格。而且各家显卡公司也都迎合IBM的规格来制作显卡。可是过了一段时间,其他显卡公司的图像处理技术超越了IBM,在IBM制定规格前,就出现了具有各样画面模式的显卡。这造成了多家显卡公司的竞争,使得在各家公司之间,画面模式的设定方法和使用方法都各不相同。 这样的情况,我们这些普通程序员是难以应付的。显卡的种类太多,我们记不住那么多的设定方法,而且事实上,连参考资料都很难得到。这样一来,本应是高性能的显卡,却只能像老显卡一样,通过BIOS设定为320×200来使用。 
有鉴于此,多家显卡公司经过协商,成立了VESA协会(Video  Electronics  Standards Association,视频电子标准协会)。此后,这个协会制定了虽然不能说完全兼容、但几乎可以通用的设定方法,制作了专用的BIOS。这个追加的BIOS被称作“VESA BIOS extension”(VESA-BIOS扩展,简略为VBE)。利用它,就可以使用显卡的高分辨率功能了。
因此,切换到不使用VBE的画面模式时用“AH = 0;AL=画面模式号码;”,而切换到使用VBE的画面模式时用“AX = 0x4f02;BX = 画面模式号码;”。而这种必须使用VBE才能利用的画面模式就称作“新”画面模式。 
VBE的画面模式号码如下。 
	0x101……640× 480× 8bit 彩色 
	0x103……800× 600× 8bit 彩色 
	0x105……1024× 768× 8bit 彩色 
0x107……1280× 1024× 8bit 彩色 
还有其他一些画面模式,因为现在不需要,我们就省略了。另外,在QEMU中不能指定最下面的0x107。实际指定的时候,要像在asmhead.nas中所做的那样,将以上的画面模式号码值加上0x4000,再赋值到BX中去。不这样做就不能顺利运行。

12

对了,如果你在汇编语言里用MOV  EIP,0x1234这种写法是会出错的,还是不要尝试的好。在汇编语言中,应该使用JMP 0x1234来代替MOV EIP,0x1234

13

JMP指令分为两种,只改写EIP的称为near模式,同时改写EIP和CS的称为far模式

14

我们向TR寄存器存入3 * 8这个值,这是因为我们刚才把当前运行的任务定义为GDT的3号。TR寄存器以前没有提到过,它的作用是让CPU记住当前正在运行哪一个任务。当进行任务切换的时候,TR寄存器的值也会自动变化,它的名字也就是“task register”(任务寄存器)的缩写。我们每次给TR寄存器赋值的时候,必须把GDT的编号乘以8,因为英特尔公司就是这样规定的。

15

顺便说一下,换行符“\n”之所以用“n”,是因为它是“new line”的缩写。

16

 栈异常的中断号为0x0c:可能大家会问,除此之外还有什么异常呢?我们在这里补充讲解一下吧。根据CPU说明书,从0x00到0x1f都是异常所使用的中断,因此,IRQ的中断号都是从0x20之后开始的。其他一些比较有用的异常有0x00号除零异常(当试图除以0时产生)和0x06号非法指令异常(当试图执行CPU无法理解的机器语言指令,例如当试图执行一段数据时,有可能会产生)等。

17

在Linux中有一个很有名的游戏叫做nethack,如果喜欢那个游戏的话,把“*”改成“@”说不定会更好哦(笑)。	

18

GDT是“global (segment) descriptor table”的缩写,LDT则是“local (segment) descriptor table”的缩写。相对于global代表“全局”,local则代表“局部”的意思,即GDT中的段设置是供所有任务通用的,而LDT中的段设置则只对某个应用程序有效。


blog comments powered by Disqus

Published

27 March 2013

Category

book