启动
一、通电
由于内存是随机存储器(Random access memory,RAM),属于易失性存储器,未通电时,RAM中不会有任何内容,因此刚一通电,RAM不可能有任何实际信息。计算机硬件厂商在只读存储器(Read-only memory,ROM)中开辟了一块空间,固化了一段代码,这段ROM被称为BIOS(basic input/output system,基本输入输出系统),其中放置的代码是对基本硬件的测试代码,IBM PC中,这段代码的起始地址就在 0xFFFF0。
计算机刚一通电,CS的初始值就被设置成 0xFFFF,IP的初始值设置成 0x0000,计算机首先工作在实模式下,实模式下取出指令地址的方式是将CS中的值左移四位,再加上IP中的值:
P C = C S < < 4 + I P = 0 x F F F F 0 PC=CS<<4+IP=0xFFFF0 PC=CS<<4+IP=0xFFFF0
即执行ROM中固化的那段代码,测试各种硬件是否正常,如果出现异常,则停止启动,并控制喇叭发声报错。(平常内存条松动,电脑开不了机时,发出的滴滴声)
如果硬件测试正常,利用BIOS的输入功能,将启动磁盘中的第一个扇区的内容(bootsect.s)读入内存 0x7C00 地址处,并设置CS=0x07C0,IP=0x0000,即将PC指针指向bootsect.s 的第一条指令处,开始执行 bootsect.s 的内容。
二、bootsect.s
1、bootsect.s 代码整体移动位置
将内存中 0x7C00 处的 512 个字节(正好就是全部 bootsect.s)移动到内存地址 0x90000 开始的一段内存中
2、读入setup.s
执行指令 “int 0x13”,调用0x13号中断,这是BIOS中断中的读写磁盘的一个中断,从磁盘中,将后续4个扇区(bootsect.s 在第一个扇区)的内容读入内存 0x90200处。
0
x
90200
−
0
x
90000
=
0
x
200
0x90200-0x90000=0x200
0x90200−0x90000=0x200
差了0x200,十六进制下,正好是十进制的512,由于是内存地址,每1相当于一个字节,正好是512个字节
也就是说,读入的 setup.s 正好接在 bootsect.s 的末尾处
3、在屏幕上输出 “Loading System…”
调用BIOS中断 int 0x10,该中断的作用是在屏幕上输出信息
4、读入system
从启动磁盘中的第六个扇区开始,读入长度为 SYSSIZE 的操作系统 system 模块,放置在内存 0x10000 处
5、PC指针设置为 0x90200
bootsect.s 的最后,将PC指针设置成 0x90200,开始执行 setup.s 的第一条指令,bootsect.s 的任务结束
二、setup.s
1、获取初始化所需的基本参数
以内存为例,setup.s 调用 0x15号BIOS中断,获取扩展内存的大小,单位是KB,并将内存尺寸存放在地址 0x90000 处,将来系统初始化时,需要来到 0x90000 处读取这个值,用于初始化内存管理
2、将内存中的system模块,移动到0x0地址处
这一步会使得BIOS中断向量表(放置在0地址处)被覆盖,因此从这里开始,BIOS中断将无法使用
3、创建临时GDT表
创建并设置一个临时的GDT表,暂时只用于一步内存跳转 “jmpi 0,8” 使指令跳转到 0x0地址处
4、启动保护模式
在这之前,PC的寻址模式还是实模式,PC=CS<<4+IP
setup.s 将A20号地址线选通,并且将寄存器CR0最后一位设置为1,一旦完成这两项设置,内存寻址方式会切换到另外一套电路——保护模式
在保护模式下,PC指针通过段基址+段内偏移的方式完成寻址,而段基址通过CS寄存器内的值,查询GDT表(全局描述符)得到,保护模式下的PC寻址方式:
P C = G D T [ C S ] + E I P PC=GDT[CS]+EIP PC=GDT[CS]+EIP
5、jmpi 0,8
在保护模式下,执行 jmpi 0,8 ,PC=GDT[8]+0=0,PC指针跳转到 0x0地址处,setup.s 的任务完成,开始执行 system 模块中的第一段代码 head.s
三、system——head.s
1、设置中断表(interrupt descriptor table,IDT)
因为system被从0x10000处挪到0x0处,将原本放置在0x0处的BIOS中断向量表覆盖了,BIOS中断将不再能使用,操作系统需要接管中断。在这一步中,IDT表创建,但全部表项初始化成0,即所有的中断暂时不可用,要等到后面给每个模块(如时钟)初始化时,才会设置相应的中断处理程序的入口地址到各个表项中
2、设置GDT表
setup.s 中创建的GDT表是临时的,只是用于在保护模式下将PC指针跳转到0x0地址处,这里需要重新创建 GDT表
3、设置页表
保护模式下,GDT[CS]+EIP得到的是32位的虚拟地址,还需要根据段页内存管理,去页表中找到跟物理地址的映射,详情在《内存》中。
https://blog.csdn.net/weixin_44179561/article/details/127154863
4、head.s 的最后一段代码,使PC指针跳转到操作系统的初始化代码处
四、操作系统初始化
初始化内存mem_map,初始化一些重要的数据结构