十一、计算机的启动过程
一、加电和复位(计算机开机初始化)
在处理器众多的引脚中,有一个是 RESET
,用于接受复位信号。
每当处理器加电,或者RESET
引脚的电平由低变高时 ,处理器都会执行一个硬件初始化,
以及一个可选的内部自测试(Build-in Self-Test,BIST),然后将内部所有寄存器的内容初始到一个预置的状态。
对于 Intel 8086 来说,复位将使代码段寄存器(CS)的内容为 0xFFFF
,其他所有寄存器的内容都为0x0000
,包括指令指针寄存器(IP)。
8086 之后的处理器并未延续这种设计,但毫无疑问,无论怎么设计,都是有目的的。
处理器的主要功能是取指令和执行指令,加电或者复位之后,它就会立刻尝试去做这样的工作。
不过,在这个时候,内存中还没有任何有意义的指令和数据,它该怎么办呢?
二、内存特点
为了节约成本,并提高容量和集成度,
在内存中,每个比特的存储都是靠一个极其微小的晶体管,外加一个同样极其微小的电容来完成的。
这样微小的电容,其泄漏电荷的速度当然也非常快。
所以,个人计算机中使用的内存需要定期补充电荷,这称为刷新,
所以这种存储器也称为动态随机访问存储器(Dynamic Random Access Memory,DRAM)。
随机访问的意思是,访问任何一个内存单元的速度和它的位置(地址)无关。
读写地址为 0x00001 的内存单元,和读写地址为 0xFFFF0 的内存单元,所需要的时间是一样的。
在内存刷新期间,处理器将无法访问它。
这还不是最麻烦的,最麻烦的是,在它断电之后,所有保存的内容都会统统消失。
所以,每当处理器加电之后,它无法从内存中取得任何指令。
三、基本输入输出系统(Base Input & Output System,BIOS)
Intel 8086 可以访问 1MB
的内存空间,地址范围为 0x00000 ~ 0xFFFFF
。
出于各方面的考虑,计算机系统的设计者将这 1MB 的内存空间从物理上分为几个部分。
8086 有 20 根地址线,但并非全都用来访问 DRAM,也就是内存条。
事实上,这些地址线经过分配,大部分用于访问 DRAM,剩余的部分给了只读存储器 ROM 和外围的板卡。
与 DRAM 不同,只读存储器(Read Only Memory,ROM)不需要刷新,它的内容是预先写入的,即使掉电也不会消失,但也很难改变。
这个特点很有用,比如,可以将一些程序指令 固化在 ROM 中,使处理器在每次加电时都自动执行。
Intel 8086 处理器的系统中,ROM 占据着整个内存空间顶端的 64KB
,物理地址范围是 0xF0000~0xFFFFF
,里面固化了开机时要执行的指令;
DRAM 占据着较低端的 640KB,地址范围是 0x00000~0x9FFFF;
中间还有一部分,分给了其他外围设备,这个以后再说。
因为 8086 加电或者复位时,CS=0xFFFF
,IP=0x0000
,所以,它取的第一条指令位于物理地址0xFFFF0
,正好位于 ROM 中,那里固化了开机时需要执行的指令。
处理器取指令执行的自然顺序是从内存的低地址往高低地址推进。
如果从 0xFFFF0
开始执行,这个位置离 1MB
内存的顶端(物理地址 0xFFFFF
)只有 16
个字节的长度,一旦 IP 寄存器的值超过 0x000F
,比如 IP=0x0011
,那么,它与 CS 一起形成的物理地址将因为溢出而变成 0x00001
,这将回绕到 1MB
内存的最低端。
所以,ROM 中位于物理地址0xFFFF0
的地方,通常是一个跳转指令,它通过改变 CS 和 IP 的内容,使处理器从 ROM 中的较低地址处开始取指令执行。
在 NASM 汇编语言里,一个典型的跳转指令像这样:
jmp 0xf000:0xe05b
这块 ROM 芯片中的内容包括很多部分,主要是进行硬件的诊断、检测和初始化。所谓初始化,就是让硬件处于一个正常的、默认的工作状态。
最后,它还负责提供一套软件例程,让人们在不必了解硬件细节的情况下从外围设备(比如键盘)获取输入数据,或者向外围设备(比如显示器)输出数据。
设备当然是很多的,所以这块 ROM 芯片只针对那些最基本的、对于使用计算机而言最重要的设备,而它所提供的软件例程,也只包含最基本、最常规的功能。
正因为如此,这块芯片又叫基本输入输出系统(Base Input & Output System,BIOS)ROM。
在读者缺乏基础知识的情况下讲述 ROM-BIOS 的工作只会越讲越糊涂,所以这些知识将会分散在各个章节里予以讲解。
ROM-BIOS 的容量是有限的,当它完成自己的使命后,最后所要做的,就是从辅助存储设备读取指令数据,然后转到那里开始执行。
基本上,这相当于接力赛中的交接棒。
起始地址 | 结束地址 | 大小 | 作用 |
---|---|---|---|
0x00000 | 0x003FF | 1KB | 中断向量表 |
0x00400 | 0x004FF | 256B | BIOS数据区 |
0x00500 | 0x07BFF | 30464B约30KB | 可用区域 |
0x07C00 | 0x07DFF | 512B | MBR被BIOS加载到此处,共512个字节 |
0x07E00 | 0x9FBFF | 622080B约608KB | 可用区域 |
0x9FC00 | 0x9FFFF | 1KB | 拓展BIOS数据区 |
0xA0000 | 0xAFFFF | 64KB | 用于彩色显示适配器 |
0xB0000 | 0xB7FFF | 32KB | 用于黑白显示适配器 |
0xB8000 | 0xBFFFF | 32KB | 用于文本模式显示适配器 |
0xC0000 | 0xC7FFF | 32KB | 显示适配器BIOS |
0xC8000 | 0xEFFFF | 160KB | 映射硬件适配器的ROM或内存映射式I/O |
0xF0000 | 0xFFFEF | 64KB-16B | 系统BIOS范围是0xF0000~0xFFFFF共64KB,为了说明入口地址,将最上面的16个字节从此处去掉了,所以此处终止地址为0xFFFEF |
0xFFFF0 | 0xFFFFF | 16B | BIOS入口地址。 此处16个字节的内容是跳转指令:jmp0xF000:E05B |
四、硬盘
软盘、光盘、硬盘、U 盘等,相对于内存,它们就是人们常说的“外存”,即外存储器(设备)。
硬盘可以只有一个盘片(这称为单碟),也可能有好几个盘片。但无论如何,它们都串在同一个轴上,由电动机带动着一起高速旋转。
一般来说,转速可以达到每分钟 3600 转或者 7200 转,有的能达到一万多转,这个参数就是我们常说的“转/分钟”(Round Per Minute,RPM)。
1.磁头
每个盘片都有两个磁头(Head),上面一个,下面一个,所以经常用磁头来指代盘面。
磁头都有编号,第 1 个盘片,上面的磁头编号为 0,下面的磁头编号为 1;
第 2 个盘片,上面的磁头编号为 2,下面的磁头编号为 3,依次类推。
每个磁头不是单独移动的。相反,它们都通过磁头臂固定在同一个支架上,由步进电动机带动着一起在盘片的中心和边缘之间来回移动。
也就是说,它们是同进退的。步进电动机由脉冲驱动,每次可以旋转一个固定的角度,即可以步进一次。
2.磁道
可以想象,当盘片高速旋转时,磁头每步进一次,都会从它所在的位置开始,绕着圆心“画” 出一个看不见的圆圈,这就是磁道(Track)。
磁道是数据记录的轨迹。
3.柱面
因为所有磁头都是联动的,故每个盘面上的同一条磁道又可以形成一个虚拟的圆柱,称为柱面(Cylinder)。
磁道,或者柱面,也要编号。编号是从盘面最边缘的那条磁道开始,向着圆心的方向,从 0 开始编号。
4.扇区
实际上,磁道还不是硬盘数据读写的最小单位,磁道还要进一步划分为扇区(Sector)。
磁道很窄,也看不见,但在想象中,它仍呈带状,占有一定的宽度。
将它划分许多分段之后,每一部分都呈扇形,这就是扇区的由来。
每条磁道能够划分为几个扇区,取决于磁盘的制造者,但通常为 63
个。
而且,每个扇区都有一个编号,与磁头和磁道不同,扇区的编号是从 1
开始的。
扇区与扇区之间以间隙(空白)间隔开来,每个扇区以扇区头开始,然后是 512
个字节的数据区。
扇区头包含了每个扇区自己的信息,主要有本扇区的磁道号、磁头号和扇区号,用来供硬盘定位机构使用。
现代的硬盘还会在扇区头部包括一个指示扇区是否健康的标志,以及用来替换该扇区的扇区地址。用于替换扇区的,是一些保留和隐藏的磁道。
五、主引导扇区
前面说到,当 ROM-BIOS 完成自己的使命之前,最后要做的一件事是从外存储设备读取更多的指令来交给处理器执行。
现实的情况是,绝大多数时候,对于 ROM-BIOS 来说,硬盘都是首选的外存储设备。
硬盘的第一个扇区是 0
面 0
道 1
扇区,或者说是 0
头 0
柱 1
扇区,这个扇区称为主引导扇区。
如果计算机的设置是从硬盘启动,那么,ROM-BIOS 将读取硬盘主引导扇区的内容,将它加载到内存地址 0x0000:0x7c00
处(也就是物理地址 0x07C00),
然后用一个 jmp
指令跳到那里接着执行:
jmp 0x0000:0x7c00
通常,主引导扇区的功能是继续从硬盘的其他部分读取更多的内容加以执行。
像 Windows 这样的操作系统,就是采用这种接力的方法一步一步把自己运行起来的。
我们可以想象,如果我们把自己编译好的程序写到主引导扇区,也是能够让处理器执行的。
如果给你一台没有操作系统的8086CPU计算机,你写了一段汇编语言程序,并且使用汇编器转换成了机器指令。
那就得想办法把这段机器指令存放到硬盘主引导扇区,这样子当CPU自检完成之后,就会开始加载主引导扇区,执行我们写好的指令。
如果你在一个有操作系统的计算机上,如果把自己编好的程序写到主引导扇区,虽然CPU也会执行我们的程序。
可是操作系统就没办法启动了,会直接瘫痪。
为了解决这个问题,我们就得使用一种叫做“虚拟机”的技术了,用软件模拟一台“8086cpu的计算机”。
直到今天,虽然有很多计算机CPU已经是64位了,但在开机启动的过程中,CPU还是以16位的兼容模式启动,也就是在启动的时候,内存只能访问:0x00000- 0xFFFFF
即1MB
的大小。