操作系统学习 01.x86系统启动流程

在计算机系统加电时,执行BIOS启动固件,在CPU初始化完成之后,默认约定CS和EIP的初始值(CS:代码段寄存器;EIP:指令指针寄存器),
在这里插入图片描述
由开发者手册看出CS=F000H;EIP=0000FFF0,实际地址为Base
+EIP=FFFF0000H+0000FFF0H=FFFFFFF0H这是BIOS的EPROM所在地(Base是CS中的基址)通常第一条指令是一条长跳转指令,到BIOS代码中执行。

此时系统处于实模式,在实模式下地址计算为PC=16*CS+IP,这是当前访问的第一条指令地址。
实模式下地址总线并非32位,而是只有20位可用,可用的只有2^20,即1M空间。
为了访问磁盘设备,在BIOS中需要提供
1.基本输入输出的程序。(完成从磁盘上读数据,从键盘上读用户输入,显示相应输出)
2.系统设置信息。(从硬盘,软盘还是光驱启动)
3.开机后自检程序。
4.系统自启动程序等。
具体过程为:当BIOS初始化完成之后,会从磁盘上读引导扇区(512字节),将加载程序从引导扇区加载到0x7c00;接着跳转到CS:IP=0000:7c00,此时把控制权转到了从磁盘上读进来的程序,即加载程序。
加载程序会将操作系统的代码和数据从硬盘加载到内存中,然后跳转到操作系统的起始地址,将控制权交给操作系统

eg:为什么不从BIOS直接读取操作系统的内核映像?(1.磁盘上文件系统多种多样,而BIOS受限于能力,不可能认识所有的文件系统,则约定先读取加载程序,用加载程序识别磁盘上的文件系统,进而读到内核镜像并加载到内存中。2.BIOS受限于能力,无法用来加载多分区的复杂大容量OS)
在这里插入图片描述
而在实际应用中BIOS并不能直接读取BootLoader,在最早的时候系统中只有一个分区,可以直接找文件系统,但现在大多数计算机中都不止有一个分区,所以需在前面加一个主引导记录,确定从哪个文件系统中读加载程序,BIOS读取主引导扇区代码后读取活动分区的引导扇区代码,再读取文件系统的加载程序。
具体过程为:CPU加电稳定后从0XFFFF0读第一条指令,第一条指令为跳转指令(CPU初始状态为16位实模式,CS:IP为16位寄存器),进入BIOS。

BIOS初始化时需要进行:
1.硬件自检POST
2.检测系统中内存和显卡等关键部件的存在和工作状态。
3.查找并执行显卡等接口卡BIOS,进行设备初始化。
4.执行系统BIOS,进行系统检测,检测和配置系统中安装的即插即用设备
5.更新CMOS中的扩展系统配置数据ESCD(扩展系统配置数据)(知道当前系统中有哪些设备)
6.按指定顺序从软盘,硬盘或光驱启动

读进第一块扇区后,主引导记录有512字节,但启动代码只有446字节,用于检查分区表正确性,加载并跳转到磁盘上的引导程序;硬盘分区表占64字节,用于描述分区状态和位置,每个分区描述信息占据16字节(采用BIOS-MBR规范,现在大多数采用新的BIOS-GPT规范,可加载更多分区),主引导记录结束标志字2字节(55AA),是主引导记录的有效标志。

然后跳转到活动分区的引导扇区,其中包含用于跳转到启动代码的跳转指令(这部分是与平台相关的代码),文件卷头:文件系统描述信息;启动代码:跳转到加载程序;结束标志依然是55AA。
加载程序在加载时也不是首先去加载内核,而是从文件系统中先读一个启动配置文件,依据这个选择启动的参数,如正常启动或在安全模式启动,然后依据配置加载指定内核并跳转到内核执行。
BootLoader要做的事情有:
1.从实模式使能保护模式,从16位寻址空间切换到32位寻址空间,使能段机制。
2.从硬盘上读取kernel in ELF格式的kernel(跟在MBR后面的扇区)并放到内存中固定位置。
3.跳转到OS入口点执行,控制权交到OS。
段机制:
在这里插入图片描述
使能保护模式:
在这里插入图片描述
然后加载ELF格式的OS kernel(此处代码为Ucore os kernel)

struct elfhdr {
uint magic; // must equal ELF_MAGIC
uchar elf[12];
ushort type;
ushort machine;
uint version;
uint entry; // program entry point (in va)
uint phoff; // offset of the program header tables
uint shoff;
uint flags;
ushort ehsize;
ushort phentsize;
ushort phnum; // number of program header tables
ushort shentsize;
ushort shnum;
ushort shstrndx;
};
struct proghdr {
uint type; // segment type
uint offset; // beginning of the segment in the file
uint va; // where this segment should be placed at
uint pa;
uint filesz;
uint memsz; // size of the segment in byte
uint flags;
uint align;
};
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值