通常搜索到的往往是
BIOS 按照“启动顺序”,把控制权转交给排在第一位的存储设备:硬盘。然后在硬盘里寻找主引导记录的分区,这个分区告诉电脑操作系统在哪里,并把操作系统被加载到内存中,然后你就能看到经典的启动界面了,这个开机过程也就完成了。
而这段话未知的东西太多了,在你了解
-
内存是存储数据的地方,给出一个地址信号,内存可以返回该地址所对应的数据。
-
CPU 的工作方式就是不断从内存中取出指令,并执行。
-
CPU 从内存的哪个地址取出指令,是由一个寄存器中的值决定的,这个值会不断进行 +1 操作,或者由某条跳转指令指定其值是多少。
三点知识后,就可以来解释启动过程了
一、为什么是 BIOS 主导?
CPU 的工作方式,就是不断从内存中取指令并执行,那为什么会说是执行 BIOS 里的程序呢?这就不得不说说内存映射了。
二、内存映射
CPU 地址总线的宽度决定了可访问的内存空间的大小。比如 16 位的 CPU 地址总线宽度为 20 位,地址范围是 1M。32 位的 CPU 地址总线宽度为 32 位,地址范围是 4G。你可以算算我们现在的 64 位机的地址范围。
可是,可访问的内存空间这么大,并不等于说全都给内存使用,也就是说寻址的对象不只有内存,还有一些外设也要通过地址总线的方式去访问,那怎么去访问这些外设呢?就是在地址范围中划出一片片的区域,这块给显存使用,那块给硬盘控制器使用,等等 。
这样说,其实就不符合我们的前置知识了,所以可以有一种不太正确的理解方式,那就是内存中的这块位置就是显存,那块位置就是硬盘控制器。我们在相应的位置上读取或者写入,就相当于在显存等外设的相应位置上读取或者写入,就好像这些外设的存储区域,被映射到了内存中的某一片区域一样。这样我们就不用管那些外设啦,关注点仍然是一个简简单单的内存。这就是所谓的内存映射。
三,实模式下的内存分布
四、怎么就从 BIOS 里的程序开始执行了
好了,现在我们知道 BIOS 里的信息被映射到了内存 0xC0000 - 0xFFFFF 位置,其中最为关键的系统 BIOS 被映射到了 0xF0000 - 0xFFFFF 位置。假如我现在说,CPU 开机就是执行了这块区域的代码,然后巴拉巴拉一顿操作就开机了,你肯定要喷我了,为什么就执行到这了呢,那咋不从头开始执行?
这就自然有了一种猜想,我们要用到另一个前置知识了,就是 CPU 从内存的哪个位置取出执行并执行呢?是 PC 寄存器中的地址值。BIOS 程序的入口地址也就是开始地址是 0xFFFF0(人家就那么写的),也就是开机键一按下,一定有一个神奇的力量,将 pc 寄存器中的值变成 0xFFFF0,然后 CPU 就开始马不停蹄地跑了起来。没错,接下来这句话,可能就是你找了很久的答案,请做好准备:
在你开机的一瞬间,CPU 的 PC 寄存器被强制初始化为 0xFFFF0。如果再说具体些,CPU 将段基址寄存器 cs 初始化为 0xF000,将偏移地址寄存器 IP 初始化为 0xFFF0,根据实模式下的最终地址计算规则,将段基址左移 4 位,加上偏移地址,得到最终的物理地址也就是抽象出来的 PC 寄存器地址为 0xFFFF0。
五、BIOS 里到底写了什么程序
好了,我们现在知道了 BIOS 被映射到了内存的某个位置,并且开机一瞬间 CPU 强制将自己的 pc 寄存器初始化为 BIOS 程序的入口地址,从这里开始 CPU 马不停蹄地向前跑了起来。那接下来的问题似乎也非常自然地就问出来了,那就是 BIOS 程序里到底写了啥?
把 BIOS 程序里的二进制信息全贴出来也不合适,我们分析一些主要的。我们首先还是来猜测,你看入口地址是 0xFFFF0,说明程序是从这执行的。实模式下内存的下边界就是 0xFFFFF,也就是只剩下 16 个字节的空间可以写代码了,这够干啥的呢?如果你有心的话应该能猜出,入口地址处可能是个跳转指令,跳到一个更大范围的空间去执行自己的任务。没错就是这样,0xFFFF0 处存储的机器指令,翻译成汇编语言是:
jmp far f000:e05b
意思是跳转到物理地址 0xfe05b 处开始执行(回忆下前面说的实模式下的地址计算方式)。
地址 0xfe05b 处开始,便是 BIOS 真正发挥作用的代码了,这块代码会检测一些外设信息,并初始化好硬件,建立中断向量表并填写中断例程。这里的部分不要展开,这只是一段写死的程序而已,而且对理解开机启动过程无帮助,我们看后面精彩的部分,也就是 BIOS 的最后一项工作:加载启动区。