从计算机结构到汇编程序入门

先动手操作

先介绍一款软件“二进制编辑器”,它是一种能够直接对二进制数进行编辑的软件:下载

汉化后,顺利启动的话会出现如下画面。

下面新建一个二进制文件,然后拷贝二进制文件内容到新文件中去(当然你可以自己敲进去),保存新文件。

下面将这个img文件,通过虚拟机进行启动:

然后一直下一步,完成,之后编辑虚拟机:

移除不必要的设备,然后添加软盘驱动器:

确定,然后开启虚拟机,就可以看到下面的结果了,要注意几点是,使用软盘镜像,img文件没有被打开,勾选只读,这几个原因都可能会导致无法发现操作系统

就这样,我们没有去改造现成的操作系统,而是从零开始开发了一个,并让它运转起来(当然,如果别人承认这是个操作系统的话)。现在唯一的问题是,我们还不知道之前输入的那些“EB 4E 90 48 45......”到底是什么意思(而这也正是我们所面临的最大问题)。

究竟做了些什么

为什么用这种方法就能开发出操作系统来呢?首先我们要了解电脑的结构,电脑的处理中心是CPU,它可以与别的电路进行电信号交换,而对于电信号,它只能理解开(ON)和关(OFF)这两种状态。

我们平时会用电脑写文章、听音乐、修改照片以及做其他各种各样的事情,我们用电脑所做的这些,其实本质上都不过是在与CPU交换电信号而已,而且电信号只有开和关两种状态。再说直白一点,CPU根本无法理解文章的内容,更不会鉴赏音乐、照片,它只会机械地进行电信号的转换。

CPU有计算指令,所以它能够进行整数的加减乘除运算,也可以处理负数、计算小数以及10的100次方这样庞大的数值,它甚至能够处理平方根、对数、三角函数,而且所有这些计算仅通过一条指令就能简单实现。CPU就是个集成电路板,它只是忠实地执行电信号给它的指令,输出相应的电信号。

假如我们给CPU发送这么一串电信号:

0000 0100 0011 1000 0000 1110 0001 0000

这信号可能是一副画的部分数据,可能是个二进制整数,可能是一段音乐旋律,可能是文章中的一段文字,也可能是保存了的游戏的一部分数据,或者是程序中的一行代码,不管它是什么,CPU都一窍不通。CPU只会按照程序的指令进行相应的处理。

 一旦把电信号的开/关与数字0和1对应起来,就能将二进制数转换成为电信号,同时电信号也可以转换回二进制数。所以,虽然CPU依然只能处理电信号,但通过转换,他就可以变成二进制数的计算机。

因为我们可以把十进制数转换成二进制数,也能把二进制数还原成十进制数,所以人们又发明了普通的计算机。后来,我们发现只要给每个文字都编上号(即文字编码),就可以建立一个文字与数字的对应关系,从而就可以把文字也转换成电信号,让CPU来处理文章了。依次类推,人们接着又找到了将图像、音乐等等转换成电信号的方法。不过CPU还是一如既往,只能处理电信号。

而且我们能用CPU来处理的并不仅仅只有数据,我们还可以用电信号向CPU发送出指令。其实我们所编写的程序最终都要转换成所谓的机器语言,这些机器语言(0和1的组合)就是以电信号形式发送给CPU的。因此可以说,不能仅用0和1来表达的内容,都不能以电信号的形式传递给CPU,因为这种内容时计算机是无法处理的。

而“二进制编辑器”就是用来编辑二进制数的,我们可以很方便地用它来输入二进制数,并保存成文件。

虽然二进制数与电信号有很好的一一对应关系,但它有一个缺点,那就是位数实在太多了。举个例子来说,如果我们把1234写成二进制数,就成了10011010010,居然长达11位。而写成十进制数,只用4位就够了。所以计算机业界普遍使用十六进制数。

有了这个对照表,我们就能轻松进行二进制与十六进制之间的转换了。将二进制转换为十六进制是,只要二进制的最后一位开始,4位4位地替换过来就行了。

初次体验汇编程序

 下面通过汇编生成上面的abc.img文件,这里要用到书中的一个汇编语言编译器:nask.exe,下面的是汇编指令,理解它可以参考上面的二进制文件:

; hello-os
; TAB=4

; 以下这段是标准FAT12格式软盘专用的代码

        DB    0xeb, 0x4e, 0x90
        DB    "HELLOIPL"        ; 启动区的名称可以是任意的字符串(8字节)
        DW    512            ; 每个扇区(sector)的大小(必须为512字节)
        DB    1            ; 簇(cluster)的大小(必须为1个扇区)
        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  1fe的十进制值为510

        DB    0x55, 0xaa  ;511和512字节的内容

; 以下是启动区以外部分的输出

        DB    0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00
        RESB    4600
        DB    0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00
        RESB    1469432

 

 

所以我们可以看出作者开发的汇编编译器,DB指令对于16进制的内容时直接写入二进制文件,DB对于引号的文本将通过ASCII转换成二进制写入。将上面的汇编程序保存为helloos.nas文件,和nask.exe放在相同的目录下面,生成上面手动输入的img文件。

然后将生成的img文件用虚拟机启动,就能显示hello,world。DB指令是"data byte"的缩写,也就是往文件里写入1个字节的指令。也就是说,只要有了DB指令,我们就可以用它做出任何数据(甚至程序)。

RESB指令是"reserve byte"的略写,如果想要从现在的地址开始空出10个字节来,就可写成RESB 10,意思是我们预约了这10个字节。而且不仅仅是把指定的地址空出来,它还会在空出来的地址上自动填入0x00。

再有就是DW指令和DD指令,它们分别是"data word"和"data double-word"。在计算机汇编语言的世界里,world指的是"16位"的意思,也就是2个字节。"double-word"是"32位"的意思,也就是4个字节。

RESB 0x1fe-$,美元符号是一个变量,可以告诉我们这一行现在的字节数。在这个程序里,我们已经在前面输出了132字节,所以这里的$就是132。因此0x1fe减去132,得出378这一结果,然后连续输出378个字节的0x00。

那这里我们为什么不直接写378,而非要用$呢?这是因为如果将显示信息从"hello,world"变成"this is a pen."的话,中间要输出0x00的字节数也会随之变化。换句话说,我们必须保证软盘的第510字节(即0x1fe字节)开始的地方是55AA。如果在程序里使用美元符号的话,汇编语言会自动计算需要输出多少个00,我们也就可以很轻松地改写输出信息了。 

说明

TAB=4           说明信息,表示记事本中TAB键的宽带设定

FAT12格式      用Windows或MS-DOS格式化出来的软盘就是这种格式。

启动区             软盘第一个的扇区称为启动区。计算机读写软盘的时候,并不是一个字节一个字节地读写的,而是以512字节位一个单位进行读写。因此,软盘的512字节就称为一个扇区。一张软盘的空间共有1440KB,也就是1474560字节,除以512得2880,这也就是说一张软盘共有2880个扇区。那么为什么第一个扇区称为启动区呢?因为计算机首先从最初一个扇区开始读取软盘,然后去检查这个扇区最后2个字节的内容。如果这最后2个字节不是55AA,计算机会认为这张盘上没有所需的启动程序,就会报一个不能启动的错误。如果计算机确认了第一个扇区的最后两个字节正好是55AA,那么它就认为这个扇区的开头是启动程序,并开始执行这个程序。

IPL                initial program loader的缩写。启动程序加载器。启动区只有区区512字节,实际的操作系统根本装不进去。所以几乎所有的操作系统,都是把加载操作系统本身的程序放在启动区里的。所以,有时也将启动区称为IPL。

启动               一般讲启动称为start。实际上,boot这个词是bootstrap的缩写,原指鞋子上附带的便于拿取的靴带。而且,磁盘上明明装有操作系统,还要说读入操作系统的程序(即IPL)也放在磁盘里。这就像打卡宝物箱的钥匙就在宝物箱里一样,是一种矛盾的说法。这种矛盾的操作系统自启动机制,被称为bootstrap方式,boot这个说法就来源于此。

 

posted on 2015-03-24 08:51  凡一二三  阅读(1236)  评论(0编辑  收藏  举报