学习这本书不代表我要亲自动手把这本书中的代码敲一遍哦,只是借机来学习一下操作系统。之前有段时间也在看操作系统的知识,怎么说呢之前的看的书都是偏讲理论多一些,对于我这个非科班出身的来说,由于之前的计算机知识基础不牢,像计算机组成及其接口技术也只是自学了一点,所以看那些讲理论的书有些阳春白雪了点,而且印象也只是停留在理论层面。《30天自制操作系统》这本书就不一样,一点一点的构建一个玩具操作系统,虽然没有多大的用处,但是对于操作系统的入门我想应该是够了的。
这里是总结一下我的看书心得体会,然后对其中提到或者扩展的知识点自己在消化一下,顺便总结成文。
1 先动手操作
在这一节作者把一个计算机的启动程序(什么叫启动程序后面再说),用二进制的编辑器把内容一个个都敲出来了,相当于把你编译的二进制文件中的字节一个个敲,可想而知......最后成了软盘映像文件,以.img结尾的,然后用工具将这个映像文件写入到软盘,最后作者用这个软盘启动了系统。
软盘的容量为1440x1024Byte=1474560Byte=1.44MB
也就是作者硬是敲了1474560下才把这个启动程序敲完了,刚开始啥也不懂只知道照着作者的来,结果没敲下去,反正到现在我也强烈不建议做这个部分,看下作者就好了。
然后这个程序可以启动程序,就这从零开始作者制作了一个软盘启动程序,成功点亮了。
2 究竟做了些什么
电脑的中心是CPU,CPU除了与别的电路进行电信号交换以外什么都不会,而且对于电信号,它也只能理解开(ON)和关(OFF)这两种状态。
CPU有指令因此可进行整数的加减乘除计算,也可以处理负数、计算小数。
虽然电脑可以写文章、听音乐、修照片和做其他各种各样的事情,但是这一切只不过是和CPU交换电信号而已。
作者这里是在科普计算机的基础知识呢,感觉讲得还是很朴实、很简单,这里的简单是将复杂的知识用简单的方式表述,而不是越讲越复杂。
然后就是二进制和电信号,计算机中所有的指令和数据在内部都是用二进制来表示的。
而软盘则是记录指令与数据的地方,所以在第一部分中,作者就纯粹用0和1写出了映像文件。
只要有二进制的编辑器,啥都可以做出来,反正作者是这样说的,制作和500万像素数码相机质量一样的图片,制作C编译器等。
二进制来表示数据显得有些繁琐,然后就是牵扯到了二进制和十六进制。
3 初次体验汇编程序
开始用汇编语言来写程序啦。
用和NASM类似的作者自己开发的编译器"nask"对汇编文件进行编译了。
然后用汇编又把第一部分的程序写了一遍,由于之前作者的程度中有很多连续的空白的字符串,这里作者用了一个叫做RESB的指令,来我们一起学一下。
这里不贴程序了,反正最后用的字节数一算还是1440KB。
汇编指令RESB
RESB指令是"reserve byte"的略写预约字节。
如果想要从当前位置向后空出10个字节来,并且填0,如果后面18万行全是0x00的话 使用本命令可以省去填写18万行0x00的时间。
例子:
RESB 10
DB 0
RESB 0x1f0-$ 填写从0x00到0x1f0的数据;
汇编中resb这样的指令是什么意思?
resb条伪指令,在NASM中文手册中查找一下:
"RESB", "RESW", "RESD", "RESQ" and "REST"被设计用在模块的 BSS 段中:它们声明 未初始化的存储空间。每一个带有单个操作数,用来表明字节数,字数,或双字数或其它的需要保留单位。就像在 2.2.7 中所描述的,NASM 不支持 MASM/TASM 的扣留未初始化空间的语法"DW ?"或类似的东西:现在我们所描述的正是 NASM 自己的方式。"RESB"类伪指令的操作数是有严格的语法。
DB指令
DB指令是"data byte"的缩写,也就是往文件里直接写入一个字节的指令。
4 加工润色
这一部分才是真正的汇编代码。
; hello-os ; TAB=4 ; 一下这段是标准FAT12格式软盘专用的代码 DB 0xeb, 0x4e, 0x90 DB "HELLOIPL" ; 启动扇区的名称可以是任意的字符串 (8字节) DW 512 ; 每个扇区(sector)的大小(必须是512字节) DB 1 ; 簇(cluster)的大小 (必须为512字节) 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, 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, 0x001fe=510 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
擦,程序主体部分和启动区以外的部分使用十六进制的数表示的呢?
";"以后的部分是汇编语言的注释方法
DB后面可以接字符串的部分,程序中已经有好几处了
DW,DD指令
DW和DD分别是"data word"和"data double-word"的缩写,和DB类似,只是占的字节数不一样,DW称为字,占2个字节;DD是双字,占4个字节。
$指令
在RESB 0x1fe-$中用到了指令"$",它是一个变量,可以告诉我们现在这个位置的字节数(其他的意思先不讲了),写成这样的好处是不用一个个计算我们前面已经写了多少个字节,可以看成$这个变量帮我们计算了。
RESB 0x1fe-$是为了保证在第510字节开始的地方是55AA,也就是代码中的"DB 0x55, 0xaa"。
其他的几个名词解释
TAB=4
为了程序美观、大方,一般都会有缩进,这个不用解释了。
FAT12格式
用Window或者MS-DOS格式化出来的软盘就是这种格式,这种格式的兼容性好,在Windows上也能用,而且剩余的磁盘空间还可以用来保存自己喜欢的文件。
启动区
启动区(boot sector)这个概念很重要。软盘的第一个扇区称为启动区。计算机在读写软盘的时候并不是一个一个字节来读取的,而是以512字节为一个单位进行读写的。软盘的512字节就是一个扇区。一张软盘一共有1440KB,也就是1474560字节,除以512得2880,所以一张软盘一共有2880个扇区。
那为什么第一个扇区称为启动区呢?
那是因为计算机首先从最初一个扇区开始读软盘,然后去检查这个扇区最后2个字节的内容。如果这最后2个字节不是55 AA,计算机会认为这张盘上没有所需的启动程序,就会报一个不能启动的错误。(也许有人会问为什么一定是55 AA呢?那是当初设计者随便决定的,作者也没法解释)。如果计算机确认了第一个扇区的最后2个字节正好是55 AA,那它就任务这个扇区的开始是启动程序,并开始执行这个程序。
十六进制的55或AA
不行,作者这个解释我不是很满意,然后上网搜了一下,还真有人给出了解释
许多串口通讯中测试或握手信号使用AA或55这两个特殊的十六进制数,在许多PIC内部的EEPROM改写也使用这两个数作为敲门砖,初学者可能不解何为,其实如果将这两个数展开成二进制就可明白为什么:AA展开为10101010,55展开为01010101,变成串行电平的话就是一个占空比为50%的方波,这种方波在电路中最容易被分辨是否受干扰或者畸变,在实际波形的观察中也最容易看出毛病所在,以异步串口通讯为例,通讯的每一个字节开始为一个数据位的低电平作为起始位,字节发送结束后是一个或两个数据位的高电平作为停止位,在测试程序阶段,我们可尝试发送0xAA,利用示波器来验证发送是否正确,以9600BPS的波特率计算,每个BIT的所用的时间大约是104.17μS,这里我们选择停止位占一个数据位,然后照此写一个反复连续发送AA的发送程序,那么在正确发送时在IO口看到的波形应该是一个大约4.8KHZ的方波,周期大约为208.34μS,占空比为50%。这样我们可以很快断定发送是否正确。由于这两个数值的特殊性,还被用到其他一些地方,比如PC机引导过程中,bios程序在加载完MBR后,还要对MBR的最后两个字节进行验证,必须为0x55和0xAA。
以下是软绵绵老村长的补充:
Flash的存储位,只能从1变成0,所以擦除完后,单元里是1的,此时可以直接写,当写成0后,再要写成1是不行的,一定要擦除,擦除后就变成1了。
每个字节先写成55,再写成AA,这样每个bit都写了一遍又擦了一遍,说明这个字节的位置是好用的。
IPL
IPL即initial program loader的缩写,启动程序加载器。启动区只有区区512字节,实际的操作系统不可能这么小,根本装不进去。所以几乎所有的操作系统,都是把加载操作系统本身的程序放在启动区里面。有鉴于此,有时也将启动区称为IPL。
启动(boot)
boot这个词的本意是长靴的单数形式。那它和计算机启动又有什么关系呢?原来boot这个词是bootstrap的缩写,在《吹牛大王历险记》之后,bootstrap这个词就有了"自己更生完成任务"的意思。