一个最简单引导扇区的编写

来源:互联网 发布:php面向对象实例 编辑:程序博客网 时间:2024/04/29 21:59
一.操作系统的启动过程
    具体的有关操作系统的启动过程可参考这篇文章http://jingyan.baidu.com/article/ce09321b3b59442bff858f22.html。在看本文之前,建议读者先把那篇文章看完。这里简单的对操作系统的启动过程做一个概括。
    从 按下 POWER键操作系统可与用户交互这中间发生了哪些事呢?
1.预引导阶段
2.引导阶段
3.加载内核阶段
4.初始化内核阶段
5.用户登录阶段
    其中第一步(预引导阶段)是BIOS自动完成的,我们不要做过多的关心。从第二步(引导阶段)开始才是我们可控的,也就是在这一步我们的代码得到了执行。

预引导阶段:
    这一阶段因为是BIOS自动完成的,我们编写代码不会涉及到这一块,而且刚才那个链接对这一部分介绍得也很详细,这里就不做过多介绍了,读者只要了解即可,下面简单的对预引导阶段做个总结,要想详细了解的可参考那个链接。
    1)进入系统BIOS
    我们按下了POWER键之后,电源就开始给设备供电。稳定供电后(读者应该猜得到前面还有一个不稳定供电的过程),CPU就会从地址0xffff0处开始执行代码,这个地址是在系统BIOS的范围内,在这里存放的是一条跳转指令,会跳转到系统BIOS中真正的启动代码处。

    2)POST

POWER ON SELF TEST。这一部分是从第1)步跳转过来的,主要完成加电自检的工作。主要检查一些关键设备(内存、显卡、CPU等)是否存在或能否正常工作。如果检测到异常(如内存不存在)则会立马死机。
    3)根据用户指定的启动顺序从软盘、硬盘或光驱启动内核
  
引导阶段:
    预引导阶段的最后一步是 根据用户指定的启动顺序从软盘、硬盘或光驱启动内核,注意这里是根据用户指定的顺序,那么用户如何指定启动顺序呢?在系统启动的时候进入BIOS,然后在BIOS里设置启动顺序。比如我这里是设置软盘优先,那么在启动时会先判断软盘上是否包含启动代码,如果有启动代码,则把软盘上的第一个扇区加载到内存0x7c00:0地址处,然后从该地址处开始执行;如果没有启动代码,则会检查下一个启动介质(硬盘、光驱等),直到找到了启动代码。那么问题来了,如何判断出软盘上有启动代码呢?检查软盘上的0号扇区,看该扇区的最后两个字节是否为0xaa55,如果是的话就认为该软盘上有启动代码。
    好了,说得比较罗嗦。这里总结一下,要想自己的启动扇区(512bytes)能够被自动识别,我们只要将这个扇区的最后两个字节设为0xaa55即可。
    了解到这个知识之后,我们就可以编写我们的引导扇区了。我们直接上代码:

将它保存为bootsect.asm
稍微学过x86汇编的人因该都看的懂代码,而且注释中也比较详细。这里最不好理解的就是绿色框中的那一句了。下面详细的对这一句进行剖析。 、
在分析之前我们先编译bootsect.asm
nasm bootsect.asm -o barras.img
我们用hexedit来看看barras.img的二进制是什么样子

我们可以看到,可以说整个barras.img文件由三个部分组成,第一个红线框里的数字,中间大部分的0以及第二个红线框里的数字0x55 0xaa。那么这些数据是怎么来的呢?
第一个红线框里的数字很明显是由红色框里的代码编译后产生的二进制数据,而绿色框里的代码就是将中间填充了0,目的就是用0来扩充使得barras.img刚好为一个扇区(512bytes)的大小,最后的两个字节55 aa很明显是黄色框代码编译后产生的效果,目的就是告诉BIOS我是启动扇区。
$就是当前行所在的地址,$$就是当前行 所在的段的起始地址。$-$$其实就表示的是红色框里的代码编译后的长度,为什么要用510而不是512减去这个长度呢?因为要保留最后两个字节给0x55,0xaa。

加载到内存中后如图所示:


 好了,代码讲解完了,下面我们用虚拟机来运行一下看下效果吧!
我们新建一个虚拟机,取名为barras,用软盘加载刚才生成的barras.img,如图

我们保存然后运行,看到的效果如下:

正如你所看到的,什么结果也没有,因为我们什么也没做啊!只是一直在jmp $。不过我们的启动扇区被BIOS正确识别了,是不是很兴奋呢,呵呵。

更详细的请参考视频教程:http://www.duobei.com/course/1574348473

0 0