如何用启动扇区启动电脑?
如何用启动扇区启动电脑?
当我们启动一台计算机的时候,计算机在做什么呢?计算机加电启动后执行ROM(BIOS)的POST(Power-On Self-Test)程序测试机器硬件是否正常工作,并且初始化系统设置包括CPU的寄存器到设备控制器,然后调用BIOS的19h中断将指定的启动设备(硬盘或软盘或光驱)的合法的启动扇区读入到内存线性地址为07c00开始的一段空间,并跳转到该地址开始执行启动扇区的代码。
启动扇区在哪里?假如我们用1.44M软盘(这是个双面软盘)启动的话,启动扇区就是0面0道的第1扇区512字节的内容;那么什么是“合法的启动扇区”呢?BIOS采用了很简单的判别方法,就是给扇区512字节的最后两个字节是不是0xAA55,如果是的话,那就是合法的启动扇区;BIOS就将这512字节的数据读入内存线性地址为0x7C00(不同的BIOS的逻辑地址可以是:0x7C0:0000或者0x0:7C00)的地方。
写入启动扇区的512字节(实际上只有510字节,因为0xAA55是固定的),实际上是我们编写的一个程序,但是这个程序和其他的我们所熟知的程序不一样,平常我们写程序都是建立在某种操作系统平台上的,比方说windows, 比方说linux, 我们总是使用很多系统函数或这库函数来方便我们实现程序功能。然而,在计算机刚启动的时候,我们的启动扇区是计算机接触的第一个用户程序,操作系统还等待着我们的启动扇区的程序载入呢,因此,这个程序必须是纯粹的十六进制代码,除了BIOS的中断是可以调用的之外,不能使用别的库函数。以后,我们都叫这个程序为bootsect。同时,编译这个程序的过程也就不太一样了,为了避免什么版权纠纷,我们需要下载一个汇编编译器NASM(NASM是一个GNU软件)。
一个完整的启动扇区的开发过程是:
步骤一:编写我们的bootsect代码,保存为纯文本的文件,建议以”.asm”作为后缀名。
步骤二:使用“nasm –f bin bootsect.asm -o bootsect”编译,得到的bootsect文件就是我们需要的纯十六进制代码文件。
步骤三:确保编译完成的文件是512字节,然后将这个512字节写到软盘0面0道的第1扇区。
步骤四:将写好的软盘插入软驱,设置好从软盘启动,就可以测试或调试启动扇区了。
观察一个能工作的bootsect极小例子:
Image1
我们把这个bootsect编译后写到软盘的0面0道1扇区后,使用该软盘启动机器,机器就被我们在bootsect的无限循环挂起了。
注意:times 510-($-$$) db 0
这条语句的意思是: 用若干个0x00重复填充 510-(本指令开始地址 – 本程序开始地址)。
$ 代表当前指令开始地址。 $$ 代表本程序的指令开始地址。
我们已经知道,BIOS将启动扇区载入线性地址为0x07C00的时候,我们不知道BIOS给了我们哪一个逻辑地址, 那么我们如何确定我们的数据段或者附加段在哪里呢?事实上,不论如何,当BIOS载入启动扇区的时候,CS是会有一个确定的值的,而且我们说了,整个bootsect都是十六进制的代码,所以我们的数据段啊附加段啊都和代码段在一起,因此,我们在写bootsect的时候常常使用下面例子的段寄存器初始化方法:
Image2
这个例子不光演示了如何初始化段寄存器,还在计算机屏幕上显示4个”*”号,然后挂起机器
bootsect是机器启动执行的第一个用户程序,可是这个程序只有510个字节的代码单元,能做的事情非常有有限,到底我们怎么样用bootsect启动我们的计算机,进入我们的操作系统,装载美轮美奂的GUI界面比方说WINDOWS呢?通常,bootsect被载入内存并取得CPU的控制权开始运行后,主要的工作就是做一些准备工作,然后将真正的操作系统内核从软盘或硬盘上读入内存后将CPU的控制权交给内核。那么我们怎么样才能通过bootsect实现这个步骤呢?请看下面的例子:
Bootsect程序文件:bootsect.asm
Image3
操作系统内核文件:kernel.asm 这个文件的大小是不限定的。
Image4
把kernel.asm同样的编译编译后的文件紧跟在bootsect的后面写到软盘中去,就可以了。
上面这个例子,bootsect开始运行后,做了相关的初始化准备后,从软盘上除启动扇区以外地方读了5个扇区到内存地址为1000:0000的地方,也就是把我们的内核文件kernel.asm的编译后的代码读入到了该地址,然后bootsect跳转到这个地址执行,也就是将CPU的控制权交给了我们的内核模块了,这以后,才真正的开始了操作系统的载入。
在windows下可以利用winimg直接写盘,MS-DOS下可以利用hdcopy直接写盘。通过对MS-DOS操作系统启动扇区代码的反汇编以及对window早期版本的启动扇区的反汇编,使用启动扇区载入操作系统的完整内核可以从根本上简化到本文的例子。当然,要载入完整内核并且能在保护模式下运行内核还需要做很多初始化的工作,但是,从根本上来说,操作系统的内核部分只有启动扇区部分必须使用汇编语言来编写,其他部分都可以使用C语言来写。所以掌握好启动扇区的写法是我们研究操作系统的实现的一个重要开端。