目录
本文谈计算机的启动过程,分为以下几个部分:
- 计算机执行的第一个程序是BIOS
- BIOS做了什么工作,BIOS会加载并执行bootloader
- bootloader是什么?又做了什么工作?
- 引导记录如何帮BIOS找到bootloader
计算机加电后执行的第一条指令
BIOS是一个程序,它存放在主板的ROM区域。ROM是只读的、且断电后数据不丢失。主板在出厂时厂商就已经在ROM中写入了内容(包括BIOS)。
计算机加电后执行的第一个程序是BIOS。
寄存器初始值
8086 CPU在加电后对寄存器做一系列初始化,其中CS和IP被初始化为:
寄存器 |
位数 |
初始值 |
CS
16位
F000H
IP
16位
FFF0H
第一条指令位于FFFF0H
CS和IP这两个寄存器共同决定了CPU要执行的下一条指令。加电后CS、IP的初值我们已经知道了,那么CS:IP所代表的地址就是FFFF0H(见8086分段寻址)。
因此CPU执行的第一条指令就是FFFF0H处的指令。F0000H~FFFFFH(共计64KB)是BIOS存放的区域,也就是说这64KB实际上被映射到ROM中。
很多人可能和我最开始的时候有同样的疑惑:20位的地址线可以表示1MB空间,难道这1MB空间并不是全部映射到内存中去?后来我明白了,其实地址有一部分对应到主板上的ROM、一部分映射到外设(如显示器)、剩下的才真正映射到内存。这也是为什么我以前在32位CPU上装了Windows系统后,明明插了4G的内存条,但在系统中看到只有3.8G的内存。
8086分段寻址
8086寄存器只有16位,为了能访问更大范围的内存,8086引入了分段寻址(段基址+偏移量)。
8086分段寻址的寻址空间只有20位,即1MB内存。1MB现在看来很小,但足以运行早期的DOS系统。
分段寻址的简单例子
CS和IP两个寄存器共同决定了地址,我们记CS和IP表示的地址为CS:IP。
考虑CS值为:F000H,IP值为:FFF0H。
CS左移四位得到:F0000H。那么F0000H就是段基址。
段基址+偏移量得到物理地址:F0000H + FFF0H = FFFF0H
这样就容易理解为何寻址空间是20位,因为16位的CS左移四位后可以表示的范围扩大到20位。
“回滚”机制
1MB的地址范围为:00000H ~ FFFFFH。
可能你也注意到了,CS:IP很容易超过1MB的空间产生溢出。
例如:
FF00:FFFF = FF000 + FFFF = 10EFFF
8086的做法是这样的:
当CS:IP的地址超过范围时,会发生“回卷”。就是舍弃溢出的位,10EFFF变成0EFFF。
有了“回卷”机制,即使寻址大于1MB的地址时也不会发生异常。
“回卷”机制给8086带来了很大的便利,但也给未来的80286、80386带来不小的麻烦(我们之后会谈到A20)。
BIOS
既然计算机加电后能顺利进入BIOS执行,那么BIOS又做什么事呢?
大家在重装系统的时候都进过BIOS,大概也知道BIOS程序有什么功能:系统设置、开机自检等等。
但这里要讲的重点是:
BIOS最后会将磁盘中的
引导扇区加载到内存中的
0x7c00处,然后跳转到
0x7c00处执行。
引导扇区:存放有bootloader程序。一个扇区只有512字节,所以bootloader程序要控制在512字节以内(在专门讲bootloader时会提到,其实是控制在446字节内)。
0x7c00:别问我为什么是
0x7c00。
Bootloader
主引导记录(MBR)
这里要解释为什么bootloader要控制在446字节内。
以后再补充
bootloader的主要工作
- 使能A20
- 使能保护模式、段机制
- 加载操作系统,跳转到操作系统的入口点执行
以后再补充