操作系统的启动过程

这是我的第一篇博客,以后想要养成写博客记录自己学习过程的习惯,希望自己坚持!
言归正传,最近在学操作系统,看了一些书和视频资料,在这里写下我对操作系统启动过程的一些简单理解

启动BOIS

cpu加电
cpu加电瞬间,会强制将cs的值置为0xffff,ip的值置为0。cpu是取指执行的,根据16位模式下cpu取指执行原理知道,cpu是将cs寄存器中的段基址值左移4位,再加上ip中的表示偏移地址的数值来表示将要执行指令的内存地址,这样算来将要执行的指令的内存地址是0xffff0,这个地方是rom区域,存放着bios程序,于是顺理成章的,cpu开始从此处顺序的取指执行bios程序。

BIOS程序开始执行

  • 首先BIOS会检查硬件,如果硬件坏了,就不会再有后续的操作了。

  • 接着执行程序,BIOS会在系统的0x00000也就是内存刚开始的地方,初始化自己的中断向量表和中断处理程序,这点很关键,因为后序的很多地方,是发起BIOS的各种中断请求,才得以进行的。 接下来就是和操作系统有关系的部分了。

  • BIOS程序开始加载磁盘的0磁道0扇区的512个字节到内存的0x07c0:0000处,这512个字节就是操作系统的引导扇区–bootsect.s,此时BIOS的任务算完成了,要将舞台交给bootsect.s了,于是设置cs和ip指向bootsect.s代码块的起始位置即0x07c0:0000

bootsect模块的执行

  • bootsect.s首先将自己从0x07c00处移到0x90000处。
  • 接着通过BIOS的中断读入磁盘上setup.s这个4个扇区,依次放到它的代码区域后面即0x90200处,并且初始化一些寄存器的值
  • 接着读入system这240个扇区的代码,由于此时代码量相对于之前大了很多,怕用户以为启动出了问题,于是在这会在屏幕上打印logo”loading system”
  • 至此,操作系统的全部代码已经加载到了内存,于是将cs:ip指向setup.s代码的开始地址,即0x90200

    setup模块的执行

  • 现在开始算是操作系统开始干活了,首先setup.s会发起通过BIOS提供的中断信号,让cpu执行对应的BIOS的中断处理程序,来提取硬件信息,并存放到bootsct.s开始的位置,以便后面OS管理硬件的时候使用。这里可以看出操作系统设置的巧妙,刚执行完bootsect.s,就将硬件信息放到这里,来覆盖掉这些已经没用的代码,同时还要保证不符合后面正在执行的setup.s的代码,真可谓精打细算,实在是佩服!

  • 接下来,就要关中断了,大家会不会疑问为什么要关中断呢,后面会讲到。
  • 再然后setup程序就要将system这240个字节移到0x00000处。注意看这个地址,很熟悉有没有,对的,就是之前BIOS存放它的中断向量表以及中断处理程序的地方,这一移动就能解释为什么要先关中断了,此时BIOS的中断向量表以及中断处理程序已经被system模块覆盖了,cpu无法再响应中断了,如果这个时候,用户不小心触发了一个中断,系统是会崩溃的。
  • 接下来setup会在自己已经执行了的代码位置初始化IDT和GDT表,这是OS从16位实模式过渡到32位保护模式很重要的一个步骤
  • 接下来是标志性的一步打开A20,这就意味着CPU可以进行32位的寻址,最大寻址空间由16位实模式下的1MB变为像现在保护模式下的4GB!
  • 接下来setup.s程序会设置cpu跳到system模块执行

    system模块的执行

  • system模块由两部分组成,head模块和main也就是内核模块,head模块是有head.s汇编而成,而main模块是由main.c编译而成,可以看到OS代码是有bootsect.s、setup.s、heaad.s这三个汇编代码和main.c组成的

  • 首先执行head模块,它负责初始化IDT,GDT表,并且也是放在自己刚执行完的代码区域,处处可看到OS设置的精打细算!这里有什么疑问吗
    1.在setup模块执行时已经初始化好了, 为什么这里还要从新初始化了?
    因为在后面内存分页的时候,setup模块会被覆盖掉,当然里面存放的GDT表等也没有了。所以只有head模块是安全的,要将GDT等放到这个位置。
    2.为什么不直接将setup初始化好了的GDT等复制过来,而要在head模块中重新初始化?
    因为考虑,如果在system模块还未移动时,将GDT移到这里,必将被system模块移动过来时覆盖掉,而当system已经过来了,再复制GDT,那它又会将head模块覆盖掉,所以GDT只能重建
  • 接下来head模块需要根据之前存放在botsect模块处的硬件信息,来初始化页表等,真正开始接管硬件了

  • 最后将main函数地址压栈,head模块执行完,通过ret指令,直接进入main模块了

你可能感兴趣的:(操作系统)