PaperTigerOS(第1天)

如果不理解自己所使用的语言是如何编译成机器语言的,就没法用这种语言来编写操作系统。

虽然操作系统是用C语言和汇编语言编写的,但并不是用C++编写的应用程序就无法在这个操作系统上运行。编写应用程序所用的语言,与开发操作系统所使用的语言是没有任何关系的。

在这里插入图片描述

1. 一开始首先要考虑怎么来写一个“只要一通电就能运行的程序”,用汇编语言来写。

首先下载“二进制编辑器”: http://www.vcraft.jp/soft/bz.html

在这里插入图片描述

从键盘上直接输入 EB4E904845…… 就可以了,从 000090 开始后面全都是 00,一直输入到最后 168000 这个地址。
在地址 0001F0001400 附近还有些地方不全是 00,要像下图那样把它们也改过来

在这里插入图片描述

保存文件命名为 helloos.img,这样就完成了软盘映像文件的制作。能看到文件大小正好是1474560 Byte(=1440 KB)。

往磁盘上写映像文件的方法,已经预先备好了一个程序。
先把准备工具全都安装了吧:

链接: https://pan.baidu.com/s/1iM3z7ItGA9RRaU5hCPM6qw?pwd=zmih 提取码: zmih

里面有一个名为 tolset 的文件夹,把这个文件夹拷贝到硬盘的任意位置。硬盘最好留出100MB左右的剩余空间。(以后不管什么时候,都可以把这整个文件夹移动到任何其他地方。用这些工具,不仅可以开发操作系统,还可以开发简单的Windows应用程序或OSASK应用程序等)

在拷贝的 tolset 文件夹下,新建名为 helloos0 的文件夹,并把前面保存的映像文件 helloos.img 复制到这个文件夹里。另外,刚才安装的 tolset\z_new_w 文件夹,其中有 !cons_9x.bat!cons_nt.bat 这两个文件,拷贝到 helloos0 文件夹里。

在helloos0文件夹里,新建 run.bat 文件:

copy helloos.img ..\z_tools\qemu\fdimage0.bin
..\z_tools\make.exe -C ../z_tools/qemu

再创建 install.bat 文件:

..\z_tools\imgtol.com w a: helloos.img

【 买片新软盘来,在Windows下格式化一下(不要选择“快速格式化”选项)。
鼠标左键 双击 helloos0 文件夹里的 !cons_nt.bat 文件(Windows95/98/Me 的用户需要双击 !cons_9x.bat),屏幕上会出现一个命令行窗口。
在命令行窗口输入 install 并回车,这样安装就开始了。】

电脑上没有软驱,使用VMware创建一个空的虚拟机,再在设置里添加一个软驱,选择你写好的img镜像文件。

在这里插入图片描述

启动此虚拟机就可以看见以下效果。

在这里插入图片描述

考虑到从键盘直接输入比较麻烦,所以就只让它显示了一条消息;如果能再多输入一些内容的话,那仅 用这种方法就可以开发任意一个操作系统 (当然最大只能到1440KB)。

我们还不知道之前输入的那些 EB 4E 90 48 45…… 到底是什么意思(而这也正是我们所面临的最大问题)。今天剩下的时间,以及以后的29天时间里,我们都会讲解这个问题。


没有谁只用二进制编辑器来做程序的。因此,我们用二进制编辑器进行的开发就到此为止,接下来我们要调转方向,开始用编程语言来继续我们的开发工作。

这次使用的汇编语言编译器是川合开发的“nask”,其中的很多语法都模仿了开源软件里享有盛名的汇编器“NASM”,不过在“NASM”的基础之上又提高了自动优化能力。
在这里插入图片描述

我们使用复制粘帖的方法,就可以写出这样一个超长的源代码来,将其命名为“helloos.nas”,并保存在helloos0中。仔细看一下就能发现这个文件内容与我们用二进制编辑器输入的内容是一模一样的。

接着,我们用“! cons_nt.bat”或是“! cons_9x.bat”(简写为!cons好了)打开一个命令行console窗口,输入以下指令:
..\z_tools\nask.exe helloos.nas helloos.img
这样我们就得到了映像文件helloos.img。

不过这么写程序也太麻烦了,要做个18万行的程序,不但浪费时间,还浪费硬盘空间。
解决这个问题并不难,如果我们不只使用DB指令,而把RESB指令也用上的话,就可以一下将helloos.nas缩短了,而且还能保证输出的内容不变,具体我们来看下面。

DB 指令是“define byte”的缩写,也就是往文件里直接写入1个字节的指令。笔者喜欢用大写字母来写汇编指令,但小写的“db”也是一样的。
在汇编语言的世界里,这个指令是程序员的杀手锏,也就是说只要有了DB指令,我们就可以用它做出任何数据(甚至是程序)。所以可以说,没有用汇编语言做不出来的文件。文本文件也好,图像文件也好,只要能叫上名的文件,我们都能用汇编语言写出来。而其他的语言(比如C语言)就没有这么万能。
RESB 指令是“reserve byte”的略写,如果想要从现在的地址开始空出10个字节来,就可以写成RESB 10,意思是我们预约了这10个字节(大家可以想象成在对号入座的火车里,预订了10个连号座位的情形)。而且nask不仅仅是把指定的地址空出来,它还会在空出来的地址上自动填入0x00,所以我们这次用这个指令就可以输出很多的0x00,省得我们自己去写18万行程序了,真是帮了个大忙。】

正常长度的源程序

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, 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
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

每次进行汇编编译的时候,我们都要输入刚才的指令,这太麻烦了,所以笔者就做了一个批处理文件 asm.bat。有了这个批处理文件,我们只要在用“! cons”打开的命令行窗口里输入“asm”,就可以生成helloos.img文件。

刚才我们把程序变成了短短的22行,这成果令人欣喜。不过就是很难看出这些程序是干什么的,所以我们就来稍微改写一下,让别人能看懂。
源文件增加到了48行,它位于projects\01_day\helloos2目录下,大家可以直接把helloos2文件夹复制到tolset里。

有模有样的源代码:

; 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
        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指令,它们分别是“define word”和“define double-word”的缩写,是DB指令的“堂兄弟”。word指的是“16位”的意思,也就是2个字节。“double-word”是“32位”的意思,也就是4个字节。

对了,差点忘记说RESB 0x1fe-$了。这个美元符号的意思如果不讲,恐怕谁也搞不明白,它是一个变量,可以告诉我们这一行现在的字节数(如果严格来说,有时候它还会有别的意思,关于这一点我们明天再讲)。在这个程序里,我们已经在前面输出了132字节,所以这里的$就是132。因此nask先用0x1fe减去132,得出378这一结果,然后连续输出378个字节的0x00。
那这里我们为什么不直接写378,而非要用$呢?这是因为如果将显示信息从“hello, world”变成“this is a pen.”的话,中间要输出0x00的字节数也会随之变化。换句话说,我们必须保证软盘的第510字节(即第0x1fe字节)开始的地方是55 AA。如果在程序里使用美元符号($)的话,汇编语言会自动计算需要输出多少个00,我们也就可以很轻松地改写输出信息了。

最后再解释几个专门术语。今天就到这吧。其他的留待明天再说。

TAB=4…....... 有的文本编辑器可以调整TAB键的宽度。请使用这种编辑器的人将TAB键的宽度设定成4,这样源程序更容易读。可能有人说,我这里只能用记事本(notepad), TAB键宽度固定为8,想调都没法调。没关系,明天笔者来推荐一个好用的文本编辑器。
FAT12格式...(FAT12 Format) 用Windows或MS-DOS格式化出来的软盘就是这种格式。我们的helloos也采用了这种格式,其中容纳了我们开发的操作系统。这个格式兼容性好,在Windows上也能用,而且剩余的磁盘空间还可以用来保存自己喜欢的文件。启动区.…(boot sector)软盘第一个的扇区称为启动区。那么什么是扇区呢?计算机读写软盘的时候,并不是一个字节一个字节地读写的,而是以512字节为一个单位进行读写。因此,软盘的512字节就称为一个扇区。一张软盘的空间共有1440KB,也就是1474560字节,除以512得2880,这也就是说一张软盘共有2880个扇区。那为什么第一个扇区称为启动区呢?那是因为计算机首先从最初一个扇区开始读软盘,然后去检查这个扇区最后2个字节的内容。如果这最后2个字节不是0x55 AA,计算机会认为这张盘上没有所需的启动程序,就会报一个不能启动的错误。(也许有人会问为什么一定是0x55 AA呢?那是当初的设计者随便定的,笔者也没法解释)。如果计算机确认了第一个扇区的最后两个字节正好是0x55 AA,那它就认为这个扇区的开头是启动程序,并开始执行这个程序。
IPL.........….... initial program loader的缩写。启动程序加载器。启动区只有区区512字节,实际的操作系统不像hello-os这么小,根本装不进去。所以几乎所有的操作系统,都是把加载操作系统本身的程序放在启动区里的。有鉴于此,有时也将启动区称为IPL。但hello-os没有加载程序的功能,所以HELLOIPL这个名字不太顺理成章。如果有人正义感特别强,觉得“这是撒谎造假,万万不能容忍!”,那也可以改成其他的名字。但是必须起一个8字节的名字,如果名字长度不到8字节的话,需要在最后补上空格。
启动..........….(boot) boot这个词本是长靴(boots)的单数形式。它与计算机的启动有什么关系呢?一般应该将启动称为start的。实际上,boot这个词是bootstrap的缩写,原指靴子上附带的便于拿取的靴带。但自从有了《吹牛大王历险记》(德国)这个故事以后,bootstrap这个词就有了“自力更生完成任务”这种意思(大家如果对详情感兴趣,可以在Google上查找,也可以在帮助和支持网页http://hrb.osask.jp上提问)。而且,磁盘上明明装有操作系统,还要说读入操作系统的程序(即IPL)也放在磁盘里,这就像打开宝物箱的钥匙就在宝物箱里一样,是一种矛盾的说法。这种矛盾的操作系统自动启动机制,被称为bootstrap方式。boot这个说法就来源于此。如果是笔者来命名的话,肯定不会用bootstrap这么奇怪的名字,笔者大概会叫它“多级火箭式”吧。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值