前言
作为计算机科班出身的学生,相信大家都学习过或者将要学习《操作系统》这样一门课,但是很不幸,课本中往往都是一些形而上的理论,学完之后对于“操作系统究竟是如何运行的”这个问题可能还是给不出一个很好地解答。直到我看到了《一个操作系统的实现》这本书,真的是相见恨晚。
本系列博客主要是以该书的学习为主线,记录我在探索过程中的体会和实践与大家分享。对操作系统的原理和实现感兴趣的同学们一定要看看这本书,真的值得一看哦。
我所用的工具可以在如下链接下载:
http://pan.baidu.com/s/1hsG3RNm
环境配置
先声明,我的实验都是在Windows环境下进行的,Linux下会有所不同。
想一下我们在装系统的时候需要什么?一台计算机,一个系统盘,对吗。那么我们在自己实践的时候当然也会需要这两样东西,不同的是我们用的都是虚拟的(当然有条件的也可以用物理的,但是我比较穷)。
1.需要一个Bochs用于虚拟计算机
2.NASM用来编译汇编语言
3.dd for windows作为写软盘(虚拟)的工具
上面提到的3个工具都可以在我给出的链接中获得。
这里的主要工作就是配置Bochs(安装就不说了,Windows下的安装相信大家都会的),先找到该软件的安装目录,大致是下面这个情形(不同的版本和安装时的不同选项设置可能会有所不同,但是一般都不会影响最终效果)。
上面用红色方框框出来的就是下一步要用到的软盘虚拟工具。双击该工具会出现如下界面:
按照提示操作如下:
只有第一个红框处是我们自己设置的值,其他地方都是用的默认值,也就是直接回车就行了。第二个红框处是一个提示,用于配置文件的,后面将会用到。完成这些操作后可以看到在当前目录下多了一个a.img文件,该文件就是我们拿来虚拟软盘的。
到现在为止,我们需要的计算机和系统盘都有了(虽然是虚拟的),也就是在“硬件”上我们已经具备了条件。下面就要具体来使用我们手上的“硬件”工具了。
首先,配置我们的计算机。在安装目录下建一个bochsrc.bxrc文件,该文件就是告诉虚拟器我们的计算机究竟是什么样子的。例如硬盘多大,CPU频率参数之类的。下面给出一个具体的例子:
# how much memory the emulated machine will have内存大小
megs: 32
# filename of ROM images指定安装目录下相应文件即可(BIOS-bochs-latest和VGABIOS-lgpl-latest)
romimage: file=BIOS-bochs-latest
vgaromimage: file=VGABIOS-lgpl-latest
# what disk images will be used 上面建立的软盘用于此处
floppya: 1_44=a.img, status=inserted
# choose the boot disk.选择启动盘
boot: floppy
# default config interface is textconfig.
#config_interface: textconfig
#config_interface: wx
#display_library: x
# other choices: win32 sdl wx carbon amigaos beos macintosh nogui rfb term svga
# where do we send log messages?设置日志文件
log: bochsout.txt
# disable the mouse, since DLX is text only设置鼠标
mouse: enabled=0
# set up IPS value and clock sync。CPU和时钟
cpu: ips=15000000
clock: sync=both
# enable key mapping, using US layout as default.设置键盘
#
# NOTE: In Bochs 1.4, keyboard mapping is only 100% implemented on X windows.
# However, the key mapping tables are used in the paste function, so
# in the DLX Linux example I'm enabling keyboard_mapping so that paste
# will work. Cut&Paste is currently implemented on win32 and X windows only.
keyboard: keymap=keymaps/x11-pc-us.map
上面看起来好像是长篇大论,但其实去掉那些注释的话真正有用的并没有多少(#开头的都是注释哦)。好了,到现在为止,我们已经把计算机配置好了,接下来就是实现我们自己的“操作系统”了。
系统实现
实现的汇编代码如下:
org 07c00h ;告诉编译器程序加载到7c00处
mov ax, cs
mov ds, ax
mov es, ax
call DispStr ;调用显示字符串例程
jmp $ ;无限循环
DispStr:
mov ax, BootMessage
mov bp, ax ;ES:BP = 串地址
mov cx, 16 ;CX = 串长度
mov ax, 01301h ;AH = 13h, AL = 01h
mov bx, 000ch ;页号为0(BH= 0)黑底红字(BL = 0Ch,高亮)
mov dl, 0
int 10h ;10h号中断
ret
BootMessage: db "Hello, OS world!"
times 510-($-$$) db 0 ;填充剩下的空间,使生成的二进制代码恰好为512字节
dw 0xaa55 ;结束标志
在这里称之为操作系统还是有点过了,其实就是一个简单的引导扇区。不过不管怎样我们还是有了一个很好地开端,不是吗。
可能有些同学会有疑问——为什么第一句要用org指令将我们的代码定位到7C00H处。这是因为,当计算机电源被打开时,它会先进行加电自检(POST),然后寻找启动盘,如果是选择从软盘启动(我们的设置就是从软盘启动),计算机就会检查软盘的0面0磁道1扇区,如果它以0xAA55结束(正是我们上面代码的结束标志),则BIOS认为它是一个引导扇区。一旦BIOS发现了引导扇区,就会将这512字节的内容装载到内存地址0000:7C00处,然后跳转到0000:7C00处将控制权彻底交给这段引导代码(这就是原因)。到此,计算机不再由BIOS中固有的程序来控制,而变成有操作系统的一部分来控制。
下面使用使用NASM来编译这段代码。将上面的.asm文件拷到对应的目录下(当然也可以在编译时指定相关路径,但我觉得对于初学者的话,这样更方便),然后打开命令提示界面(在运行中输入cmd并回车即可)。
在命令提示符界面中先转到NASM安装目录,然后使用命令进行编译。我这里的安装目录是在D:\NASM,其中编译命令是:nasm boot.asm -o boot.bin 完成后对应的目录下会产生一个boot.bin文件。
现在我们的系统代码就编译完成了,下一步是将编译后的代码写入到我们之前准备的虚拟软盘之中去,因为只有这样我们才能让“计算机”使用我们的代码。
将编译后的代码写入“软盘”我们需要用到dd for windows这一工具,该工具在我的“软件大礼包”中也已经提供了。我将它放在了E:\rawrite下,先将boot.bin和a.img这两个文件拷到该目录下,相关的命令行操作步骤如下:
首先还是进入相应的目录,然后输入写软盘指令:dd if=boot.bin of=a.img bs=512 。完成后a.img中就写入了相应的指令,接下来我们把a.img拷回Bochs的安装目录中准备使用我们自己写的代码来启动“计算机”。
启动系统
经过前面的一番努力,现在我们的目录大致如下,最重要的是一个已写入系统代码的a.img文件和一个已配置的bochsrc.bxrc文件。
下面就是最令人期待的时刻了,启动我们的计算机!
首先通过命令提示符界面进入Bochs安装目录,然后输入命令bochs -f bochsrc.bxrc
后面会出现一个提示框,我们点击“Start”按钮即可。
最后,在弹出的系统界面中输出了红色的”Hello, OS world!”,是的这就是我们让它输出的字符串,想想还有点小激动呢!
这样就完成了最简单的操作系统,虽然现在看上去没什么用,但是起码这个过程我觉得很有意义。