8086/8088处理器20根地址线,内存的最大空间为1MB,开机时实模式下分配情况如下图所示。
0X00000H-0X0033FF | 256项X4B=1K 中断向量 |
0X00400H-0X004FF | 256B=0.25K,BIOS数据区 |
0X00500H-0X07BFFH | 29.75K自由内存区 |
0X07C00H-0X07DFFH | 0.5K引导程序加载区 |
0X07E00H-0X9FFFFH | 608.5K自由内存区 |
0XA0000H-0XBFFFFH | 2X64K=128K 显存使用 |
0XC0000H-0XC7FFFH | 32K 显卡BIOS |
0XC8000H-0XCBFFFH | 16K IDE BIOS |
0XCC000H-0XEFFFFH | 144K 保留BIOS |
0XF0000H-OXFFFFFH | 64K 系统BIOS |
计算机系统的启动过程
(一) 当我们按下电源开关时,电源就开始向主板和其他设备供电,此时电压还不太稳定,主板上的芯片组会向CPU发出并保持一个RESET信号,让CPU内部自动恢复到初始状态,但CPU在此刻不会马上执行指令。当芯片组检测到电源已经稳定供电时,它便撤去RESET信号,CPU马上就从0XFFFF0H开始执行指令。这个地址实际上在系统BIOS的地址范围内,放在这里的只是一条跳转指令,跳到系统BIOS中真正的启动代码处。
(二) 系统BIOS的启动代码首先要做的就是POST(POWER-ON SELF TEST,上电自检)。POST的主要任务是检测系统中一些关键设备是否存在以及能否正常工作。例如内存和显卡设备等。由于POST是最早进行检测的过程,此时显卡还没有初始化,如果系统BIOS在进行POST的过程中发现了一些致命的错误,例如没有找到内存或者内存有问题(此时只会检查640K的常规内存),那么系统BIOS就会直接控制喇叭发出声音来报告错误,声音的长短和次数代表了错误的类型。在正常情况下,POST过程进行得非常快,我们几乎无法感觉到它的存在,POST结束后就会调用其他代码来进行更加完整的硬件检测。
(三) 接下来,系统BIOS将查找显卡的BIOS。存放显卡BIOS的起始地址通常设置在0XC0000H处,系统BIOS在这个地方找到显卡的BIOS之后就将它初始化。然后就是查找其他设备的BIOS程序,找到以后同样要初始化。
(四) 这一步就是系统BIOS显示它自己的启动画面,包括版本等信息。
(五) 接着系统BIOS将检测和显示CPU的类型和工作频率,然后开始测试所有RAM,同时在屏幕上显示测试内存的进度。我们可以在CMOS中设置测试方式。
(六) 内存测试完以后,系统BIOS将开始检测系统中安装的一些标准硬件设备,包括硬盘、光驱、串口、并口、软驱等。
(七) 标准设备测试完成以后,开始检测和配置即插即用的设备,同时为该设备分配终端、DMA通道和I/O端口等资源。
(八) 所有的硬件都检测完以后,重新清屏,列出设备的资源和相关的参数。
(九) 更新ESCD(Extended System Configuration Data,扩展系统配置数据),用来与操作系统交换硬件的配置信息。
(十) 根据用户指定的启动顺序从软盘、硬盘或光驱启动。以C盘为例,系统BIOS将读取并执行硬盘上的主引导记录,主引导记录接着从分区表中找到第一个活动分区。然后读取并执行这个活动分区的分区引导记录。而分区引导记录将读取并执行IO.SYS,这是基本的系统文件。IO.SYS首先要初始化一些重要的系统数据,然后显示出我们所熟悉的蓝天白云。在这幅画面下,windows将继续进行DOS部分和GUI部分的引导和初始化工作。
上面介绍的是在打开电源开关进行冷启动时完成的工作,如果是热启动(Ctrl+Alt+Del或者重新启动计算机),那么POST过程将被跳过去,直接进行显卡的初始化工作。而且第五步中的CPU和内存的检测也不会再进行。
操作系统的引导
系统上电后,BIOS启动程序进行设备检测和初始化,然后就是操作系统的引导了。
首先系统的BIOS读取BIOS设置,得到引导驱动器(引导磁盘)的列表,然后依次检查,找到可以用来引导的驱动器(找到可用的引导磁盘),然后从引导磁盘中的引导扇区读取引导程序,引导程序中包含了操作系统的启动代码。
1 如何确定引导磁盘
引导磁盘的第一个扇区(0磁头,0磁道,1扇区,共512B)的最后两个字节是55 AA,BIOS只要能够找到这个磁盘,就说明它是一个可引导盘。通常这个512B的字节被称为引导程序(boot),存放于内存的0X07C00H-0X07DFFH中,也就是内存中的引导区。
2 通过BIOS读磁盘扇区
引导扇区需要将存于磁盘上的操作系统读入内存,但是由于操作系统非常大,512B不可能装入这么大的系统文件,因此我们必须在引导扇区里将存在磁盘上的操作系统的核心部分读入内存,然后再跳转到操作系统的核心部分区执行。
这就涉及到怎样不通过操作系统去读磁盘磁区(因为这时操作系统还没有读入到内存中去)。一般来说可以用两种方式实现,一种是直接读写磁盘的I/0端口,一种是通过中断实现。前一种方法是最底层的方法(后一种方法在它的基础上实现),具有极高的灵活性,可以将磁盘上的内容督导内存的任何地方,但编程复杂。第二种方法是前一种方法稍微高一点的实现,牺牲了一点灵活性。比如它不能把磁盘上的内容督导0X00000H-0X003FFH处。因为这里是存放中断向量的。如果从磁盘上读的内容覆盖了这一块地址的内容,那么中断向量被覆盖了,就会导致其他中断无法实现(BIOS在读的过程中自己会多次调用其他中断辅助完成)。
3 利用中断读取磁盘扇区
BIOS利用13号中断读取磁盘扇区。13号中断将几个寄存器的值作为其参数,在调用13号中断的时候,首先要设置寄存器。
在实际的调用过程中,会用到一下寄存器。
AH 存放功能号,为2的时候表示读取磁盘功能
DL 存驱动器号,表示欲读哪个驱动器
CH 存磁头号,表示欲读的磁头
CL 存扇区号,表示欲读的起始扇区
AL 存计数器值,表示欲读的扇区数量。
在设置了这几个寄存器后,我们就可以用INT 13这条指令调用BIOS 13号中断,读取指定的磁盘扇区,他将磁盘扇区读入ES:BX处。因此,在调用它之前,我们实际上还要设置ES和BS的寄存器,以便指出数据在内存中的位置。