BIOS 按照“启动顺序”,把控制权转交给排在第一位的存储设备:硬盘。然后在硬盘里寻找主引导记录的分区,这个分区告诉电脑操作系统在哪里,并把操作系统被加载到内存中,然后你就能看到经典的启动界面了,这个开机过程也就完成了。
我们需要明确3点:
CPU 地址总线的宽度决定了可访问的内存空间的大小。比如 16 位的 CPU 地址总线宽度为 20 位,地址范围是 1M。32 位的 CPU 地址总线宽度为 32 位,地址范围是 4G。你可以算算我们现在的 64 位机的地址范围。
可是,可访问的内存空间这么大,并不等于说全都给内存使用,也就是说寻址的对象不只有内存,还有一些外设也要通过地址总线的方式去访问,那怎么去访问这些外设呢?就是在地址范围中划出一片片的区域,这块给显存使用,那块给硬盘控制器使用,等等 。
好了,现在我们知道 BIOS 里的信息被映射到了内存 0xC0000 - 0xFFFFF 位置,其中最为关键的系统 BIOS 被映射到了 0xF0000 - 0xFFFFF 位置。
通俗点简单点说就是,按下开机键,一定有硬件的办法使得PC寄存器设置成BIOS入口地址处的值0xFFFF0,显然只有16字节肯定不是BIOS程序的全部内容,一定是一个跳转指令。
jmp far f000:e05b
地址 0xfe05b 处开始,便是 BIOS 真正发挥作用的代码了,这块代码会检测一些外设信息,并初始化好硬件,建立中断向量表并填写中断例程。
为什么非要是 0x7c00 呢?找到一个比较浪漫的说法,具体是不是也不清楚
07在ASCII码中是bell的意思,这里代指Bell Labs(贝尔实验室),后面的C0你可以理解成C语言(1973年第四版的Unix用C语言重写了),也可理解为 Clear Zero,Current Zero…… 这也许就是……反正浪漫就完事儿了!
对于我们理解操作系统而言,此时的 BIOS 仅仅就是个代码搬运工,把 512 字节的二进制数据从硬盘搬运到了内存中而已。所以作为操作系统的开发人员,仅仅需要把操作系统最开始的那段代码,编译并存储在硬盘的 0 盘 0 道 1 扇区即可。之后 BIOS 会帮我们把它放到内存里,并且跳过去执行。
而 Linux-0.11 的最开始的代码,就是这个用汇编语言写的 bootsect.s,位于 boot 文件夹下。
通过编译,这个 bootsect.s 会被编译成二进制文件,存放在启动区的第一扇区。
mov ax,0x07c0
mov ds,ax
这里有两个疑问:
BIOS负责加载了启动区,而启动区又负责加载真正的操作系统内核。