系统启动之后,pc指针首先指向BIOS区,检测RAM,键盘,显示器,软硬磁盘是否正常运作,之后会把磁盘0磁道0扇区的256字节的引导启动代码放到内存0x7c00处,PC指该内存地址处开始运行,该引导代码用汇编而不是用C语言,因为C语言的代码编译之后,它的内存位置是人为不可控的(比如自动分配栈)而汇编可以。
引导启动步骤如下:
- 把256字节的代码从0x7c00处移动到0x9000处。然后从0x9000处开始运行。
- 运行一开始读磁盘0磁道0扇区后面的4个setup扇区,把这4个扇区读到0x90200地址处。
- 接下来的代码不读磁盘了,而是用13号中断在屏幕上显示加载系统的图片和文字。
- 最后再把磁盘前5个扇区之后的内容读到内存
- 程序跳到setup程序的地址去执行
- setup程序首先通过15号中断获得内存的大小等硬件参数。然后把从0x9000处所有的操作系统代码移到0地址处。(在物理内存中,操作系统就存放在低地址中)
- set up的最后代码是一条高级指令,它会把cr寄存器的最后一位置1,这样寻址方式从以前的模式转变为保护模式,寻址不再是cs左移4位加上ip地址,而是cs寄存器指向gdt表,找到基地址,然后加上ip寄存器的偏移地址来寻址,这样可以查找更大的空间,以前是寻址空间2的16次方,现在是2的32次方。
- 接下来跳到system模块去执行,也就是前5个扇区之后的代码处去执行。
注意,磁盘上的程序一次是boot–setup–system程序,最终转变到内存中也要是这样的顺序,boot将setup的程序拿到内存,setup将system的程序拿到内存。system程序的开始一定是是head.s文件。 - head.s文件会初始化idt和gdt表,这两个表格是寻址用的,以方便保护模式下使用,该模式下很多汇编指令改变,比如mov des sor 变成
mov sor des,32位汇编代码和16位汇编代码不同。整个启动过程用了16位汇编,32位汇编,内嵌汇编三种。 - 最后跳到main()函数去执行,在main函数里面进行各个模块的初始化工作。前面第6部获得的物理内存大小参数就可以传到一些初始化函数中进行使用。