4 Makefile入门

到helloos4为止,做出来的程序与笔者最初开发时所写的源程序是完全一样的。在开发的过程中,笔者使用了一个名为Makefile的东西,在这里给大家介绍一下。

Makefile就像是一个非常聪明的批处理文件。

■■■■■

Makefile的写法相当简单。首先生成一个不带扩展名的文件Makefile,然后再用文本编辑器写入以下内容。

#文件生成规则

ipl.bin : ipl.nas Makefile
    ../z_tools/nask.exe ipl.nas ipl.bin ipl.lst

helloos.img : ipl.bin Makefile
    ../z_tools/edimg.exe   imgin:../z_tools/fdimg0at.tek \

#号表示注释。下一行“ipl.bin : ipl.nas Makefile”的意思是,如果想要制作文件ipl.bin,就先检查一下ipl.nas和Makefile这两个文件是否都准备好了。如果这两个文件都有了,Make工具就会自动执行Makefile的下一行。

至于helloos.img, Makefile的写法也是完全一样的。其中的“\”是续行符号,表示这一行太长写不下,跳转到下一行继续写。

我们需要调用make.exe来让这个Makefile发挥作用。为了能更方便地从命令行窗口运行这个工具,我们来做个make.bat。make.bat就放在tolset的z_new_w文件夹中,可以直接把它复制过来用。

■■■■■

做好以上这些准备后,用!cons打开一个命令行窗口(console),然后输入“make -r ipl.bin”。这样make.exe就会启动了,它首先读取Makefile文件,寻找制作ipl.bin的方法。因为ipl.bin的做法就写在Makefile里,make.exe找到了这一行就去执行其中的命令,顺利生成ipl.bin。然后我们再输入“make -r helloos.img”看看,果然它还是会启动make.exe,并按照Makefile指定的方法来执行。

到此为止好像也没什么特别的,我们再尝试一下把helloos.img和ipl.bin都删除后,再输入“make -r helloos.img”命令。make首先很听话地试图生成helloos.img,但它会发现所需要的ipl.bin还不存在。于是就去Makefile里寻找ipl.bin的生成方法,找到后先生成ipl.bin,在确认ipl.bin顺利生成以后,就回来继续生成helloos.img。它很聪明吧。

下面,我们不删除文件,再输入命令“make -r helloos.img”执行一次的话,就会发现,仅仅输出一行“‘helloos.img’已是最新版本(‘helloos.img'is up to date)”的信息,什么命令都不执行。也就是说,make知道helloos.img已经存在,没必要特意重新再做一次了。它越来越聪明了吧。

让我们再考验考验make.exe。我们来编辑ipl.nas中的输出信息,把它改成“How are you? ”并保存起来。而ipl.bin和helloos.img保持刚才的样子不删除,在这种情况下我们再来执行一次“make-r helloos.img”。本以为这次它还会说没必要再生成一次呢,结果我们发现,make.exe又从ipl.bin开始重新生成输出文件。这也就是说,make.exe不仅仅判断输入文件是否存在,还会判断文件的更新日期,并据此来决定是否需要重新生成输出文件,真是太厉害了。

■■■■■

现在大家知道了Makefile比批处理文件高明,但每次都输入“make -r helloos.img”的话也很麻烦,其实有个可以省事的窍门。当然,可以将“make -r helloos.img”这个命令写成makeimg.bat,但这么做还是离不开批处理文件,所以我们换个别的方法,在Makefile里增加如下内容。

#命令
img :
    ../z_tools/make.exe -r helloos.img

修改之后,我们只要输入“make img”,就能达到与“make -r helloos.img”一样的效果。这样就省事多了。makeimg.bat已经没用了,把它删掉。另外顺便把下面内容也一并加进去吧。

asm :
    ../z_tools/make.exe -r ipl.bin

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

install :
    ../z_tools/make.exe img
    ../z_tools/imgtol.com w a: helloos.img

这样一来,“run.bat”、“install.bat”也都用不着了。不但用不着,现在还更方便了呢。比如只要输入“make run”,它会首先执行“make img”,然后再启动模拟器。

到目前为止,我们为了节约时间,避免每次都从汇编语言的编译开始重新生成已有的输出文件,特意把批处理文件分成了几个小块。而现在有了Makefile,它会自动跳过没有必要的命令,这样不管任何时候,我们都可以放心地去执行“make img”了。而且就算直接“make run”也可以顺利运行。“make install”也是一样,只要把磁盘装到驱动器里,这个命令就会自动作出判断,如果已经有了最新的helloos.img就直接安装,没有的话就先自动生成新的helloos.img,然后安装。

■■■■■

笔者把以上这些都总结在projects/02_day下的helloos5文件夹里了,顺便又另外添加了几个命令。一个命令是“make clean”,它可以删除掉最终成果(这里是helloos.img)以外的所有中间生成文件,把硬盘整理干净;还有一个命令是“make src_only”,它可以把源程序以外的文件全都删除干净。另外,笔者还增加了make命令的默认动作,当执行不带参数的make时,就相当于执行“make img”命令(默认动作写在Makefile的最前头)。

功能增加了这么多,而文件数量却减少到5个,看上去清爽多了吧。像源文件这种真的必不可少的文件,多几个倒也没什么不好,但像批处理文件这种可有可无的东西太多,堆在那里乱糟糟的就会让人很不舒服。

这样整理一下,我们以后的开发工作就会更加轻松愉快了。

■■■■■

啊,有一点忘了告诉大家,这个make.exe是GNU项目组的人开发的,公开供大家免费使用的一款软件。gcc的作者也是这个GNU项目组。真是太感谢了!

按照现在的速度真的能在一个月后开发出一个操作系统吗?笔者也有点担心。不过应该没问题,虽说现在的进展比当初的计划稍慢一些,不过刚开始的时候说明肯定会多一些,等到后面用C语言来开发的时候,速度就能上来了。嗯,就是这样……笔者满怀希望地自言自语中(苦笑)。那么我们明天见!

COLUMN-1 数据也能“执行”吗?机器语言也能“显示”吗?

在helloos5中,如果我们把最开始的JMP entry写成JMP msg,到底会怎样呢? ……

首先,可不可以这么写呢?完全可以!nask不会报错,别的汇编语言也不会报错。在汇编语言里,标号归根到底不过就是一个表示内存地址的数字而已,至于JMP跳转的地方是机器语言还是字符编码,汇编语言中不考虑这些问题。

那么如果执行这个程序,CPU会怎么样呢?首先最初的命令是0A 0A,意思是“OR CL, [BP+SI]”,也就是把CL寄存器的内容和BP+SI内存地址的内容做逻辑或(OR)运算(过几天会出现这个命令),结果放入CL寄存器。接着的命令是68 65 6C,也就是PUSH 0x6c65的意思(过几天这个命令也会出现),它将0x6c65储存进栈。……就这样,CPU执行的命令很混乱,但CPU只能按照电信号的指令来进行处理,所以即使不明其意,也会一板一眼地照单执行。

结果,要么画面上出现怪异的字符,要么软盘或硬盘上的数据突然被覆盖。虽然电脑并没有坏掉(因为CPU还在全速执行指令),但看上去却像坏了一样。所以大家一定不要尝试这样做。

不过人无完人,搞不好通宵写了一夜程序,稀里糊涂之下就将本应写entry的地方,错写成了msg,这也不是不可能发生。要是因为这而丢失了重要文件,可就损失惨重了,所以CPU具有预防这种事故的功能。但是这种功能只有在操作系统做了各种相应设置后才会起作用(几天后也会讲到)。所以,在开发操作系统的阶段,我们还不能指望这种保护功能。从某种程度上来说,我们操作系统开发者一直都是在提心吊胆地做开发。

那么反过来会怎样呢?也就是假设要把机器语言当作文字来显示,会出现什么结果呢?程序里有一句是“MOV SI, msg”,我们把它写成“MOV SI, entry”看看。首先画面上会显示一个编码是B8的字符(估计是个表情符号或者别的什么符号),下一个字符碰巧是00,所以显示就到此结束了。这种情况不会出现恶劣的后果,大家试一试也无妨。

通过以上的尝试,最终证明,不管是CPU还是内存,它们根本就不关心所处理的电信号到底代表什么意思。这么一来,说不定我们拿数码相机拍一幅风景照,把它作为磁盘映像文件保存到磁盘里,就能成为世界上最优秀的操作系统!这看似荒谬的情况也是有可能发生的。但从常识来看,这样做成的东西肯定会故障百出。反之,我们把做出的可执行文件作为一幅画来看,也没准能成为世界上最高水准的艺术品。不过可以想象的是,要么文件格式有错,要么显示出来的图是乱七八糟的。