要写一个操作系统,我们首先要有一个储存系统的介质,原版书似乎是06年出版的,可惜那时候没有电脑,没想到作者用的还是软盘,现在的电脑谁有软驱?不得已我使用一张128M的SD卡来代替,而事实上你用的是U盘还是软盘对我们的操作系统没有影响,缺点是你的U盘刷入系统后容量只能是1440 MB,即当年流行的3.5英寸软盘的大小,当然不用担心,再格式化一次(用DiskGeniu),就可以恢复。
我做事情的话,总是怕自己的努力的结果白费了,害怕辛辛苦苦看完这本书但是发现做出来的东西现在根本没法用,比如你花了大力气造了一辆火车,发现轮子的间距和现行标准不符,没轨道可以跑,被标准抛弃的感觉太恐怖,所以我决定试试,作者的系统能不能真正地跑起来。
我选择了源码中projects\30_day\harib27f中的haribote.img文件,用ImgWriter写入到我的储存卡,
写入后的大小和预期相符,1.x MB;
重新启动,开机时狂按Delete,修改启动项;
F10保存后重启,心中有些忐忑不安;
… …
但是结果还是如我所愿,看,It works!
这是就是我们要完成的东西了,偷窥胜利果实的快感不言而喻,系统甚至支持USB键盘,但不支持USB鼠标确实是不能用。我试着输入了几个命令:
Bad command. 我也不知道什么是作者指定的command,已知的是,exit能用。
频繁地开关电脑来调试我们的系统是不理想的,我们需要Virtual Box来搭把手。
打开VB的控制台,新建虚拟机,操作系统的类型选Other,版本选择Other\Unknown,
一直点下一步直到虚拟硬盘,选择不添加虚拟硬盘,我们的虚拟硬盘文件就是img。
选择虚拟电脑的设置——储存——储存树,添加一个软盘控制器,原来的IDE控制器可以删掉了,在软盘控制器里新增软盘到控制器,当然选择刚才的haribote.img,然后大功告成,启动系统。
启动系统后一切都显得那么完美,鼠标能用,键盘也是,而且非常方便,输入的蹩脚英文或许有错,见笑了。
PS: 这里需要注意的是本来有另一种方案,使用VB安装目录下的VBoxManage.exe 执行 VBoxManage convertdd file.img file.vdi
但不知为何,没办法转换上述的haribote.img,只能转换下面要写的hello, world。
电脑启动的步骤是简要部分步骤是:加电——读取BIOS——自检——控制权移交操作系统(或者说引导),如此看来,我们的任务就是编写一段符合规范的代码,在第四步的时候代码会被执行。
首先我们需要一个标准的FAT12的启动扇区(Boot sector)的代码,我很希望有FAT32 的,无奈这本书给的就是FAT12的,代码如下:
但是这段完全由数据组成的代码只是符合了一个软盘启动扇区的标准,还没有任何可执行的代码:
1 ; OS 0.01 2 ; 标准FAT12软盘专用代码 3 4 DB 0xeb, 0x4e,0x90 5 DB "HELLOIPL" ; 启动扇区(boot sector)的名字 6 DW 512 ; 每个扇区(sector)的大小:512B 7 DB 1 ; 簇(cluster)的大小:一个扇区 8 DW 1 ; FAT的起始位置 9 DB 2 ; FAT的个数 10 DW 224 ; 根目录大小 11 DW 2880 ; 磁盘大小 2880扇区 12 DB 0xf0 ; 磁盘种类 13 DW 9 ; FAT长度 14 DW 18 ; 一个磁道(track)有18个扇区 15 DW 2 ; 磁头数 16 DD 0 ; 不使用分区 17 DD 2880 ; 重写磁盘大小 18 DB 0,0,,0x29 ; 固定 19 DD 0xffffffff ; 意义不明 20 DB "HELLP_OS " ; 磁盘名称11字节 21 DB "FAT12 " ; 磁盘的格式名称8字节 22 RESB 18 ; 空出18 Bit
下面添加了可执行的代码,可以称作是IPL了。
1 ; hello-os 2 ; TAB=4 3 4 ORG 0x7c00 ;为什么这两句可以代替前面的 0xeb 0x4e? 5 JMP entry 6 DB 0x90 7 DB "HELLOIPL" 8 DW 512 9 DB 1 10 DW 1 11 DB 2 12 DW 224 13 DW 2880 14 DB 0xf0 15 DW 9 16 DW 18 17 DW 2 18 DD 0 19 DD 2880 20 DB 0,0,0x29 21 DD 0xffffffff 22 DB "HELLO-OS " 23 DB "FAT12 " 24 RESB 18 25 26 entry: 27 MOV AX,0 28 MOV SS,AX ;这里改为 SS,0会出错 29 MOV SP,0x7c00 30 MOV DS,AX 31 MOV ES,AX 32 MOV SI,msg ;储存字符串的首地址 33 putloop: 34 35 MOV AL,[SI] 36 ADD SI,1 37 CMP AL,0 38 JE fin 39 MOV AH,0x0e ; int 0x10 的 0x0e号功能 40 MOV BX,0x15 41 INT 0x10 42 JMP putloop 43 fin: 44 HLT 45 JMP fin 46 47 msg: 48 DB 0x0a, 0x0a ; '\n' = #13 = 0x0a 49 DB "LastAvengers's OS" 50 DB 0x0a 51 DB 0 ; 结束标志 52 53 RESB 0x7dfe-$ ; 0x01fe+0x7c00 = 0x7dfe 54 DB 0x55, 0xaa 55 DB 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 56 RESB 4600 57 DB 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 58 RESB 1469432
使用作者提供的nask.exe,执行 nask.exe IPL.asm a.img 可以得到镜像文件,可以利用VB来启动了。
一开始作者为我们提供了install.bat,!cons_nt.bat,run.bat来安装和运行系统,后
来又介绍了make.exe,实在是神器,(之前还不解为什么在Linux下编译包需要make install,现在终于知道了),只需要构造一个不带扩展名的MakeFile文件,就可以集编译写入运行于一身,MakeFile 的基本格式如下:
宏定义 源文件之间的相互依赖关系
任意可执行的Shell命令
作者在这里贸贸然地给出了
1 helloos.img : ipl.bin Makefile 2 ../z_tools/edimg.exe imgin:../z_tools/fdimg0at.tek \ 3 wbinimg src:ipl.bin len:512 from:0 to:0 imgout:helloos.img
先通过nask 生成bin文件再用edimg.exe 转为img文件,我不知道为什么要这么做,而且生成 .lst 文件的时候也失败了。
作者给出的makefile中地址都是斜杠,而系统用的是反斜杠,虽然效果一样,但是看着不爽,vim ":1,$/\//\\/g"可以将所有斜杠转化为反斜杠,注意这里的\有的是用来做转义的。
于是我没有照着他那样,我的MakeFile改写如下,同样正常工作:
1 # nask.exe ipl.asm a.img ipl.lst ::fail NASK: LSTBUF is no enough 2 3 default : 4 tolset\z_tools\make.exe install 5 tolset\z_tools\make.exe run 6 del *.*~ >nul ::删除临时文件 7 del *~ >nul 8 9 10 a.img : ipl.asm Makefile 11 tolset\z_tools\nask.exe ipl.asm a.img::直接编译成img,不知作者的用意是什么 12 13 install : 14 tolset\z_tools\make.exe -r a.img 15 16 run : 17 echo Running... 18 "D:\Program Files\Oracle\VirtualBox\VirtualBox.exe" --comment "OS1" --startvm "a5c4b0e6-e142-4720-98ee-056911204b29" ::虚拟机的快捷方式 19 echo Finished.
另外改写了!cons_nt.bat,增加了环境变量。
1 @echo off 2 color 0b 3 set PATH=%PATH%;tolset\z_tools\ 4 cmd.exe
之后打开!cons_nt.bat, 输入make,效果如图:
FAT12启动区的标准:第511个字节开始填充55AA,软盘大小是2880*512/1024 = 1440 KB;
启动区的加载地址是 0x7c00—0x7dff;
各种寄存器,只有SI,DI,BX为数不多的几个寄存器才能放地址;
MakeFile 的用法;
Vim的替换命令;
int 0x10中断重点是AH=0EH:http://blog.csdn.net/thimin/article/details/2313390。
唉,我真是话唠。