自己动手做OS——Day1
先简单说明一下,这里我就只做一些简单记录,不再像以前一样长篇大论写过程介绍了,我这里只写我原来不知道的。
1 先动手操作
run.bat
copy helloos.img ..\..\..\REF\tolset\z_tools\qemu\fdimage0.bin
..\..\..\REF\tolset\z_tools\make.exe -C ../../../REF/tolset/z_tools/qemu
我的目录结构和作者的不大一样,所以最后写出来的东西也和他的不大一样,这里需要理解,但是相比之下更重要的还是这两条语句都是在干啥的。
第一条copy
就是将helloos.img
拷贝到了qemu文件夹下面,然后将它重命名了一下,重命名后叫做fdimage0.bin
,但是变换过程中它的内容是不变的。
第二条就是执行了这个make.exe
,-C
是为了变换他的path,在make之前将path转换到这个qemu
的目录下。
install.bat
..\..\..\REF\tolset\z_tools\imgtol.com w a: helloos.img
这个我就不是很清楚了,不过由于我暂时没有烧录,所以暂时也没有用到这个。
运行run.bat
,我们跑出来了一个非常简陋的界面,并且输出了一段话。
个人理解,这个作者做的操作应该是写了一些汇编指令,然后同时将这个helloworld这段话存到了某块内存区域中,然后再通过汇编指令将其输出到了屏幕上。当然,具体发生了什么还需要继续看下去。
2 究竟做了些什么
作者在这里主要讲的是计算机是处理01串的机器,实质上这里的01串也就是汇编语言后面的机器码,结合我自己的理解来谈,不同的指令集架构,有不同的执行方式,实质上来说,cpu在执行一些指令的时候也就是将指令搬运到内存中,然后再通过cache对指令进行读取然后再逐条执行。在32位cpu的眼中,指令是32位的二进制数,它被分为几个部分,可以用于鉴别指令的功能与操作的目标等。我们之前用的二进制编辑器实质上就是再做一些比汇编更底层的事情,也就是写一些机器代码,或是直接将机器的初始状态定义出来。
3 初次体验汇编程序
无语的是,这里要用的汇编竟然不是x86
也不是mips
而是作者自己实现的汇编器,tql。我们同样要生成之前的那个.img
文件,让我们实现上电load指令后输出衣阿华那个helloworld,我们之前的方法是直接编辑二进制文件,现在我们的方法是使用作者提供的汇编来做这件事情(其实差不多),具体来讲就是使用DB
语句来做我们刚才做过的事情(应该和set差不多)。
这里我们还是直接用作者给出来的文件就好了(因为这里做的活动太单一了)
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
做的事情好像和之前基本一致
我们使用作者给出的编译器来做一个简单的编译(为了方便,我直接都用的绝对路径):
C:\Users\wangsy\Desktop\WSY-OS\REF\tolset\z_tools\nask.exe C:\Users\wangsy\Desktop\WSY-OS\REF\projects\01_day\helloos1\helloos.nas C:\Users\wangsy\Desktop\WSY-OS\REF\projects\01_day\helloos1\helloos.img
这样就可以让编译器通过.nas
文件生成一个二进制文件了。
为了方便我们,作者做了一个叫做asm.bat
的文件,我们点进去看了下,发现也是非常的简单:
..\z_tools\nask.exe helloos.nas helloos.img
说白了就是和我们上面的一样。
4 加工润色
这里作者给出了一个更加清晰地代码
; hello-os
; TAB=4
; 以下这段是标准FAT12格式软盘专用的代码
DB 0xeb, 0x4e, 0x90
DB "HELLOSON" ; 启动区的名称可以是任意的字符串(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 "wo shi ni die"
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
:define wordDD
:define double-wordRESB 0x1fe-$
:这个美元符号的意思就是一个变量,可以告诉我们这一行现在的字节数等等,在这个程序中,我们输出了132字节,这里的$就是132,所以我们用0xfe
减掉132得到378,于是输出了378个字节的0x00
。之所以这样实现,是因为可以根据前面的字符串来进行调节长度。换句话讲,我们必须保证这个二进制文件的510字节也就是0xfe
字节开始的地方是55 AA 。
相信大家和我一样,还是不懂,不过问题不大,接着看吧:
- 启动区:软盘的第一个扇区叫做启动区,扇区是计算机读写软盘的最小单位,假设以512字节为单位进行读写,那么软盘的512字节就被称为一个扇区,这个软盘是1440kb,那么就有2880个扇区。计算机每次都从第一个扇区进行读写,然后检查这个扇区最后的两个字节的内容是否是
0x55 AA
,如果不是,计算机会认为这张盘上面没有所需的启动程序,就会报一个不能启动的错误,如果计算机确定了第一个扇区符合要求,那么就认为这个扇区的开头就是启动程序,并且开始执行这个程序。 - IPL:就是程序加载器,启动区太小了,只有512字节,但是实际的操作系统不可能这么小,所以大多数操作系统都是把加载操作系统本身的程序放到启动区中的,所以有时也将启动区称作IPL。反应在程序里面,你可以修改一开始DB的一些东西,来更改这个扇区的名字,不过注意一定要八个字节
- 启动(boot):这里的boot是bootstarap的意思,也就是自启动机制,就是操作系统通过这个扇区进行引导并且自启动的过程。