启动BIOS, 准备实模式下的中断向量表和中断服务程序
- 加电的瞬间,RAM中空空如也。什么程序也没有。硬盘中有操作系统程序,但CPU只能运行内存中的程序,没有能力直接从硬盘运行操作系统。要运行操作系统,必须将软盘中的操作加载到RAM。
- RAM中什么程序也没有的时候,谁来完成加载软盘中的OS任务?--- BIOS
BIOS的启动原理
-
BIOS程序自身是如何启动的。
- 用软件方法不可能执行BIOS,就只能靠硬件方法来实现了。
- 从硬件角度看,intel 80x86系列的CPU可以分别在16位实模式和32位保护模式下运行。为了兼容也为了解决最开始的启动问题,Intel将所有的80x86系列CPU,包括最新信号的CPU硬件都设计为加电即进入16位实模式状态运行。痛死,还有一点非常关键,将CPU硬件逻辑设计为加电瞬间强制将CS的值置为0xF000、IP的值置为0xFFF0, 这样CS:IP就指向0xFFFF0这个地址位置,0xFFFF0指向了BIOS的地址范围。
IP/EIP(Instruction Pointer): 指令指针寄存器,存在于CPU中,记录将要执行的指令在代码段内的偏移地址,和CS组合即为将要执行的指令的内存地址。实模式为绝对地址,指令指针为16位,即IP;保护模式下为线性地址,指令为32位,即EIP。
CS(Code Segment Register):代码段寄存器,存在于CPU中,指向CPU当前执行代码在内存中的区域(定义了存放代码的存储器的起始地址)。- BIOS程序的入口地址就是0xFFFF0,BIOS程序的第一条指令就设计在这个位置
BIOS在内存中加载中断向量表和中断服务程序
- BIOS程序代码量不大,但非常精深,需要对整个计算机硬件体系结构非常熟悉才能看明白。
- BIOS程序被固化在计算机主板上的一块很小的ROM芯片里。通常不同的主机板所用的BIOS也有所不同。就启动部分而言,各类BIOS的基本原理大致类似。CS:IP指向0xFFFF0位置,意味着BIOS开始启动。BIOS启动过程中一项至关重要的工作:在内存中建立中断向量表和中断服务程序。
ROM(Read Only Memory):只读存储器,ROM有一个特性,就是断电之后仍然能保存信息。
- BIOS程序在内存最开始的位置(0x00000)用1KB的内存空间(0x00000 ~ 0x003FF)构建中断向量表,在紧挨着它的位置用256字节的内存空间构建BIOS数据区(0x00400 ~ 0x004FF),并在大约57KB以后的位置(0x0E05B)加载了8KB左右的与中断向量表相应的若干中断服务程序。
0x00100是256字节,0x00400就是4 * 256字节=1024字节=1KB,从0开始,所以1KB的高地址端是0x003FF。
- 中断向量表中有256个中断向量,每个中断向量占4字节,其中两个字节是CS的值,两个字节是IP的值。每个中断向量都指向一个具体的中断服务程序。
- 下面讲解后续程序如何利用这些中断服务程序把系统内核程序从硬盘加载至内存:
INT(INTerrupt):中断,中途打断一件正在进行中的事。
加载OS内核程序并为保护模式做准备
- boot操作:把软盘中的操作系统程序加载至内存。对linux而言,计算机分3批逐次加载OS的内核代码。
- 第1批,由BIOS中断int0x19把第一扇区bootsect的内容加载到内存
- 第2批,第3批在bootsect的指挥下,分别把其后的4个扇区和随后的240个扇区的内容加载至内存。
加载第一部分内核代码--引导程序(bootsect)
- 计算机硬件体系结构的设计与BIOS联手操作,会让CPU接收到一个int0x19中断向量。
- 中断向量把CPU指向0x0E6F2,这个位置是int0x19相对应的中断服务程序的入口地址。
- 这个中断服务程序的功能是BIOS事先设计好的,代码是固定的,与Linux操作系统无关。无论OS内核是如何设计的,这段代码的所做的事就是:找到硬盘,并加载第一个扇区。
中断向量表(Interrupt Vector Table):实模式中断机制的重要组成部分,记录所有中断号对应的中断服务程序的内存地址。
中断服务(Interrupt Service)程序:通过中断向量表的索引对中断进行响应服务的程序。
- int0x19中断向量所指向的中断服务程序,即启动加载服务程序,将硬盘0号磁头对一个盘面的0磁道1扇区的内容复制到内存0x07C00处。这个扇区里的内容就是linux的引导程序,就是bootsect,其作用就是陆续把硬盘中的OS程序载入内存。这样制作的第一扇区就称为启动扇区(bootSector)。第一扇区的载入,标志着linux中的代码即将发挥作用。
- 这是非常关键的动作,从此计算机开始和软盘上的操作系统程序产生关联。第一扇区中的程序由
bootsect.s
中的汇编程序汇编而成(bootsect)。这就是计算机自开机以来,内存中第一次有了Linux操作系统自己的代码,虽然只是启动代码。
- 这是非常关键的动作,从此计算机开始和软盘上的操作系统程序产生关联。第一扇区中的程序由
- 至此,已经把第一批代码bootsect从硬盘载入计算机内存了,下面的工作就是执行bootsect把硬盘的第二批,第三批代码载入内存。
BIOS程序固化在主机板上的ROM中,是根据具体的主机板而不是根据操作系统设计的。
- 理论上,计算机可以安装任何适合其安装的OS。每个OS设计者都可以设计出一套自己的OS启动方案,而OS和BIOS通过是由不同团队设计的,为能协同工作,必须建立OS与BIOS之间的协调机制。
两头约定和定位识别:- 对OS而言,约定:OS必须把最开始执行的程序定位在启动扇区,其余程序可以依照OS的设计顺序加载在后续扇区中。
- 对BIOS而言,约定:接到启动OS的命令,定位识别,只从启动扇区把代码加载到0x07C00(BOOTSEG)这个位置(Boot.c boot_disk)。至于这个扇区中是否是启动程序,是否是OS,则不闻不问、一视同仁。若不是启动代码,只会提示错误,其余是用户的责任,与BIOS无关。
《Linux内核设计的艺术第2版》学习笔记