在Windows系统以及有图形界面的其他操作系统中要想执行一个程序,必须在窗口中双击它,或者在命令行界面中输入相应的执行命令。从计算机底层机制上讲,这其实是在一个已经运行起来的操作系统的可视化界面或命令行界面中执行一个程序。感觉要进入先有鸡还是先有蛋的循环之中了。但是,在开机加电的一瞬间,内存中什么程序也没有,没有任何程序在运行,不可能有操作系统,更不可能有操作系统的用户界面。

既然软件方法不可能执行BIOS,那就只能靠硬件方法完成了。这让我想起了老式打字机,每打完一行字都要手动推一下滑杆,手动换位,挺麻烦的。
理解参考实模式,保护模式 Intel x86架构的CPU可以分别在16位实模式和32位保护模式下运行。为了兼容,也为了解决最开始的启动问题,Intel将所有x86架构CPU(包括最新型号的CPU)的硬件都设计为加电即进入16位实模式状态运行。同时,还有一点非常关键,即将CPU硬件逻辑设计为加电瞬间强行将代码段寄存器(cs)的值置为0xFFFF,偏移量(IP)的值置为0x0000,这样CS:IP就指向0xFFFF0这个地址位置。BIOS程序的第一条指令就设计在这个位置上。

以上是一个纯硬件完成的动作!如果此时这个位置没有可执行代码,那就什么也不做,计算机就此死机。反之,如果这个位置有可执行代码,计算机将从这里的代码开始,沿着后续程序一直执行下去。BIOS程序的入口地址恰恰就是0xFFFF0 !也就是说,BIOS程序的第一条指令就设计在这个位置上。上计算机组成原理可时,记得老师说BIOS病毒是杀不死的。例如CIH病毒,bmw病毒,等病毒。

BIOS程序被固化在计算机主机板上的一块很小的ROM芯片里。通常,不同的主机板所用的BIOS也有所不同,就启动部分而言,各种类型的BIOS的基本原理大致相似。随着BIOS程序的执行,屏幕上会显示显卡的信息、内存的信息……说明BIOS程序在检测显卡、内存……这期间,有一项对启动(boot)操作系统至关重要的工作,那就是BIOS在内存中建立中断向量表和中断服务程序。

中断向量是指早期的微机系统中将由硬件产生的中断标识码(中断源的识别标志,可用来形成相应的中断服务程序的入口地址或存放中断服务程序的首地址)。中断是指在计算机执行程序的过程中,当出现异常情况或者特殊请求时,计算机停止现行的程序的运行,转而对这些异常处理或者特殊请求的处理,处理结束后再返回到现行程序的中断处,继续执行原程序。

中断向量表中有256个中断向量,每个中断向量占4个字节,其中两个字节是代码段寄存器(CS)的值,两个字节是偏移量(IP)的值,每个中断向量都指向一个具体的中断服务程序。现在,可以先将中断理解为一种技术手段,在这一点上与C语言的函数调用有些类似。

从现在开始就要执行真正的boot操作了,即把硬盘中的操作系统程序加载至内存。对于Linux0.11操作系统而言,计算机将分三批逐次加载操作系统的内核代码。第一批由BIOS中断int0x19h把第一扇区bootsect的内容加载到内存;第二批和第三批在bootsect的指挥下,分别把其后的四个扇区和随后的240个扇区的内容加载至内存。

首先加载引导程序
1.BIOS自检
2.操作cpu使cpu接收到int 19h中断,类似于跳转,CPU接收到这个中断后,会立即在中断向量表中找到int 19h中断向量。接下来,中断向量把CPU指向0x0E6F2,这个位置就是int 0x 19h相对应的中断服务程序的入口地址,这个中断服务程序的作用就是把硬盘的第一个扇区中的程序(512B)加载到内存中的指定位置(这个扇区很重要,其实里面就是bootsect,即引导程序,这个扇区也叫bootsector,即引导扇区)。这个中断服务程序的功能是BIOS事先设计好的,代码是固定的,与Linux操作系统无关,无论Linux 0.11的内核是如何设计的,这段BIOS程序所要做到就是“找到硬盘”并“加载第一扇区”。其余的它什么都不知道,也不必知道。

这是非常关键的动作,从此计算机开始与软盘上的操作系统程序产生关联。第一扇区中的程序是由bootsect.s中的汇编程序汇编而成(以后简称bootsect),这是计算机自开机以来,内存中第一次有了Linux操作系统自己的代码,虽然只是启动代码。至此,已经把第一批代码bootsect从软盘载入到计算机的内存了。下面的工作就是执行bootsect把软盘的第二批和第三批代码载入内存。

理论上,计算机可以安装任何适合其安装的操作系统,既可以安装Windows,也可以安装Linux。不难想象每个操作系统的设计者都可以设计出一套自己的操作系统启动方案,而操作系统和BIOS通常是由不同的专业团队设计和开发的,为了能协同工作,必须建立操作系统和BIOS之间的协调机制。