《30天自制操作系统》(【日】川合秀实)读书笔记(第1天)

今后直接引用《30天自制操作系统》的内容就用紫色斜体来表示好了!

现在我们开始吧~~~~~

==============今天的内容================

第一部分:先动手操作

第二部分:究竟做了些什么

第三部分:初次体验汇编程序

第四部分:加工润色

==============第一部分:先动手操作========

原文有点杂乱,我把它重新整理一下,让大家能做得更流畅点 (注意:我这里只包括了使用QEMU模拟器操作的部分,若是想学习如何用软盘启动操作系统,请参考原文)

首先下载二进制编辑器 Bz1621

链接:https://pan.baidu.com/s/1a2r40lKlwhLfME0hNpDtrQ
提取码:p5hi
--来自百度网盘超级会员V3的分享

确保自己有下载“第0天”中附带的光盘文件,没下载的请回去“第0天”下载。

首先进入<光盘文件 第0天附带下载地址>\OS\projects\01_day\ 文件夹内,把helloos0复制一份到 <光盘文件 第0天附带下载地址>\OS\tolset\文件夹下。进入helloos0文件夹内,双击cons_nt.bat(或者

是!cons_9x.bat),在打开的命令行窗口中输入“run”指令就可以了。程序会启动模拟器QEMU运行helloos.img (一个只会打印hello world的操作系统)。运行截图如下:

helloos0文件夹下有五个文件,分别为!cons_9x.bat,!cons_nt.bat,helloos.img,install.bat,run.bat。

!cons_9x.bat 和 !cons_nt.bat是作者提供,可在 <光盘文件 第0天附带下载地址>\OS\tolset\z_new_w 文件夹找到,实际上这两个文件就是针对不同Windows版本的“调用命令行窗口”命令。

helloos.img就是我们的操作系统镜像。

install.bat是把helloos.img安装到软盘上的脚本,我们不用软盘,所以忽略。

run.bat是使用qemu启动helloos.img的脚本,qemu工具放在 <光盘文件 第0天附带下载地址>\OS\tolset\z_tools 文件夹下,这就是为什么helloos0文件夹必须放到 \OS\tolset\ 下才能用qemu启动helloos.img。

好了,现在我们已经成功启动了光盘中自带的helloos.img,如果我们要自制呢?

接下来是自制helloos.img方法,只要傻瓜式的照着做就行,不需要去理解原理,原理会在第二部分讲解。

双击启动Bz.exe程序,顺利启动的话屏幕上会出现如下画面。 

 

接下来照着书上引文和下面的截图,傻瓜式的做一个完全一样的二进制文件,这个二进制文件实际上就是一个能够打印hello world的软盘自启动程序。如果不想自己输入,也可以直接使用 <光盘文件 第0天附带下载地址>\OS\projects\01_day\helloos0\helloos.img。关于这个文件到底为什么能够自启动,到底在干什么,后边有说明。

好,让我们赶紧来输入吧,只要从键盘上直接输入EB4E904845……就可以了,简单吧。其中字符之间的空格是这个软件在显示时为方便阅读自动插入的,不用自己从键盘上输入。另外,右边的.N.HELLOIPL……部分,也不用从键盘输入,这是软件自动显示的。可能版本或者显示模式不一样的时候,右侧显示的内容会与下面的截图有所不同。不过不用往心里去,这些内容完全是锦上添花的东西,即使不一样也没事。

从000090开始后面全都是00,一直输入到最后168000这个地址。如果一直按着键盘上的“0”不放手的话,画面上的0就会不停地增加,但因为个数相当多,也还是挺花时间的。如果家里有只猫的话,倒是可以考虑请它来帮忙按住这个键(日本的谚语:想让猫来搭把手,形容人手不足,连猫爪子都想借用一下),或者也可以干脆就用透明胶把这个键粘上。

因为一下子输入到最后实在是挺花时间的,大家也许想保存一下中间结果,这时可以从菜单上选择“文件”(File)→“另存为”(Save As),画面上就会弹出保存文件的对话框。我们可以随便取个名字进行保存,笔者推荐使用“helloos.img”。当想要打开保存过的文件时,首先要启动Bz.exe,从菜单上选择“文件”(File)→“打开”(Open),然后选择目标文件,这样原来保存的内容就能显示出来了。可是这个时候不管我们怎么努力按键盘,它都一点反应也没有。这是怎么回事?难道必须要一次性输入到最后吗?这个大家不必担心,其实只要从菜单里选择“编辑”(Edit)→“只读”(Read Only)就可以进入编辑状态啦。好了,我们继续输入。

如果家里的猫自由散漫惯了,不肯帮忙,而大家又不想用透明胶粘键盘这种土方法的话,不妨这样:用鼠标选择一部分0,然后从菜单选择“编辑”(Edit)→“复制”(Copy)。简简单单复制粘贴几次就可以大功告成了,这工具还真方便呀。哦,对了,差点忘记一件重要的事——在地址0001F0和001400附近还有些地方不全是00,要像下图那样把它们也改过来,然后整体检查一下,确认没有输入错误。

0001F0附近

 001400附近

下面,我们把输入的内容保存下来就完成了软盘映像文件的制作,这时

查看一下文件属性,应该能看到文件大小正好是1474560字节
(=1440×1024字节)。

原文中介绍了如何把该文件写入软盘,并使用软盘启动这个程序,鉴于大家应该都不用软盘了,我直接skip这部分,仅粘贴使用QEMU模拟器启动程序的教程。

使用模拟器的方法也非常简单,我们只需要在用!cons_nt.bat(或者是!cons_9x.bat)打开的命令行窗口中输入“run”指令就可以了。然后一个名叫QEMU的非常优秀的免费PC模拟器就会自动运行。QEMU不是笔者开发的,它是由国外的一些天才们开发出来的。感谢他们!“我按照你说的一步一步地做了一遍,可是不行呀!怎么回事呢?”会遇到这种情况的人肯定是个非常认真的人,可能真的完全按照上面步骤用二进制编辑器自己做了一个helloos.img文件出来。出现这种问题,肯定是因为文件中有输入错误的地方,虽然笔者不知道具体错在哪儿,不过建议最好检查一下000000到000090,以及0001F0前后的数据。如果还是不行的话,那就干脆用附带光盘中笔者做的helloos.img好了。可能有些人嫌麻烦,懒得自己输入,上来就直接使用光盘里的helloos.img文件,这当然也没什么不可以;但笔者认为这种体验(一点一点地输入,再千辛万苦地纠错,最终功夫不负有心人取得成功)本身更难能可贵,建议大家最好还是亲自尝试一下。

 以上就是如何自制helloos.img,如果大家发现自制helloos.img无法启动,可以参考一下原文作者引文的蓝字,也可以跟光盘自带helloos.img对比哦!

==============第二部分:究竟做了些什么========

原文第二部分并没有解释那些十六进制数到底在干什么,只是介绍了二进制数、十六进制数,以及一些CPU的基础,对于有一定计算机基础的人来说都是很熟悉的内容,这里直接skip过去。

===========第三部分:初次体验汇编程序==========

好,现在就让我们马上来写一个汇编程序,用它来生成一个跟刚才完全一样的helloos.img吧。我们这次使用的汇编语言编译器是笔者自己开发的,名为“nask”,其中的很多语法都模仿了自由软件里享有盛名的汇编器“NASM”,不过在“NASM”的基础之上又提高了自动优化能力。

超长的源代码DB 0xeb, 0x4e, 0x90, 0x48, 0x45, 0x4c, 0x4c, 0x4fDB 0x49, 0x50, 0x4c, 0x00, 0x02, 0x01, 0x01, 0x00DB 0x02, 0xe0, 0x00, 0x40, 0x0b, 0xf0, 0x09, 0x00DB 0x12, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00DB 0x40, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x29, 0xff(为节省纸张,这里省略中间的18万4314行)DB 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00

注:这里给感到懵圈的朋友解释一下,汇编语言是支持直接写入十六进制数的,这些十六进制数也算作源码的一部分,DB指令是“define byte”的缩写,也就是往文件里直接写入1个字节的指令,也可以用小写的"db"。因此,从之前的二进制数转移到汇编代码最直接的方法就是把之前的二进制数复制过来,然后在每一行的开头加上DB,这样就是一个汇编源文件了,编译后就是之前的helloos.img。

我们使用复制粘帖的方法,就可以写出这样一个超长的源代码来,将其命名为“helloos.nas”,并保存在helloos0中。仔细看一下就能发现这个文件内容与我们用二进制编辑器输入的内容是一模一样的。接着,我们用“!cons_nt.bat”或是“!cons_9x.bat”(我们在前面已经说过,要根据Windows的版本决定用哪一个。以后每次都这样解释一遍的话比较麻烦,所以我们就将它简写为!cons好了) 打开一个命令行窗口(console),输入以下指令(提示符部分不用输入):

提示符1>..\z_tools\nask.exe helloos.nas helloos.img

这样我们就得到了映像文件helloos.img。

好,我们的第一个汇编语言程序就这样做成了!……不过这么写程序也太麻烦了,要做个18万行的程序,不但浪费时间,还浪费硬盘空间。与其这样还不如用二进制编辑器呢,不用输入“0x”、“,”什么的,还能轻松一点。

其实要解决这个问题并不难,如果我们不只使用DB指令,而把RESB指令也用上的话,就可以一下将helloos.nas缩短了,而且还能保证输出的内容不变,具体我们来看下面。

DB指令是“define byte”的缩写,也就是往文件里直接写入1个字节的指令。

RESB指令是“reserve byte”的略写,如果想要从现在的地址开始空出10
个字节来,就可以写成RESB 10,意思是我们预约了这10个字节(大家
可以想象成在对号入座的火车里,预订了10个连号座位的情形)。而且
nask不仅仅是把指定的地址空出来,它还会在空出来的地址上自动填入
0x00,所以我们这次用这个指令就可以输出很多的0x00,省得我们自己
去写18万行程序了,真是帮了个大忙。

这里还要说一下,数字的前面加上0x,就成了十六进制数,不加0x,就
是十进制数。这一点跟C语言是一样的。

正常长度的源程序

DB 0xeb, 0x4e, 0x90, 0x48, 0x45, 0x4c, 0x4c, 0x4fDB 0x49, 0x50, 0x4c, 0x00, 0x02, 0x01, 0x01, 0x00DB 0x02, 0xe0, 0x00, 0x40, 0x0b, 0xf0, 0x09, 0x00DB 0x12, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00DB 0x40, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x29, 0xffDB 0xff, 0xff, 0xff, 0x48, 0x45, 0x4c, 0x4c, 0x4fDB 0x2d, 0x4f, 0x53, 0x20, 0x20, 0x20, 0x46, 0x41DB 0x54, 0x31, 0x32, 0x20, 0x20, 0x20, 0x00, 0x00RESB 16DB 0xb8, 0x00, 0x00, 0x8e, 0xd0, 0xbc, 0x00, 0x7cDB 0x8e, 0xd8, 0x8e, 0xc0, 0xbe, 0x74, 0x7c, 0x8aDB 0x04, 0x83, 0xc6, 0x01, 0x3c, 0x00, 0x74, 0x09DB 0xb4, 0x0e, 0xbb, 0x0f, 0x00, 0xcd, 0x10, 0xebDB 0xee, 0xf4, 0xeb, 0xfd, 0x0a, 0x0a, 0x68, 0x65DB 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x77, 0x6f, 0x72DB 0x6c, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00RESB 368DB 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaaDB 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00RESB 4600DB 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00RESB 1469432

我们自己动手输入这段源程序比较麻烦,所以笔者把它放在附带光盘的projects\01_day\ helloos1目录下了。大家只要把helloos1文件夹复制粘帖到tolset文件夹里就可以了。之前的helloos0文件夹以后就不用了,我们可以把它删除,也可以放在那里留作纪念。顺便说一下,笔者将helloos0文件夹名改为了helloos1,删掉了其中没用的文件,新建并编辑了需要用到的文件,这样就做出了新的helloos1文件夹。操作系统就是这样一点一点地成长起来的。每次进行汇编编译的时候,我们都要输入刚才的指令,这太麻烦了,所以笔者就做了一个批处理文件2asm.bat。有了这个批处理文件,我们只要在用“!cons”打开的命令行窗口里输入“asm”,就可以生成helloos.img文件。在用“asm”作成img文件后,再执行“run”指令,就可以得到与刚才一样的结果。

===========第四部分:加工润色==========

刚才我们把程序变成了短短的22行,这成果令人欣喜。不过还有一点不足就是很难看出这些程序是干什么的,所以我们下面就来稍微改写一下,让别人也能看懂。改写后的源文件增加到了48行,它位于附带光盘的projects\01_day\helloos2目录下,大家可以直接把helloos2文件夹复制到tolset里。现在helloos1也可以删掉了(每个文件夹都是独立的,用完之后就可以删除,以后不再赘述。当然放在那里留作纪念也是可以的)。现在的程序有50行,也占不了多少地方,所以我们将它写在下面了。

实际上就是之前代码的规范高级版,依然是十六进制数的填充,部分十六进制数被替换成了它们作为ASCII码所表示的字母和数字。有模有样的源代码; hello-os; TAB=4; 以下这段是标准FAT12格式软盘专用的代码DB 0xeb, 0x4e, 0x90DB "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 ; 不使用分区,必须是0DD 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, 0x7cDB 0x8e, 0xd8, 0x8e, 0xc0, 0xbe, 0x74, 0x7c, 0x8aDB 0x04, 0x83, 0xc6, 0x01, 0x3c, 0x00, 0x74, 0x09DB 0xb4, 0x0e, 0xbb, 0x0f, 0x00, 0xcd, 0x10, 0xebDB 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

这里有几点新内容,我们逐一来看一下。首先是“;”命令,这是个注释命令,相当于C语言或是C++中的“//”。正是因为有它,我们才可以在源代码里加入很多注释。其次是DB指令的新用法。我们居然可以直接用它写字符串。在写字符串的时候,汇编语言会自动地查找字符串中每一个字符所对应的编码,然后把它们一个字节一个字节地排列起来。这个功能非常方便,也就是说,当我们想要变更输出信息的时候,就再也不用自己去查字符编码表了。再有就是DW指令和DD指令,它们分别是“define word”和“ddefinedouble-word”的缩写,是DB指令的“堂兄弟”。word的本意是“单词”,但在计算机汇编语言的世界里,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、付费专栏及课程。

余额充值