掘金 后端 ( ) • 2024-04-10 09:42

内核装载

0x7c00

固件程序 BIOS 会将硬盘中启动区的 512 字节的数据,原封不动复制到内存中的 0x7c00 这个位置,并跳转到这个位置进行执行

只要硬盘中的 0 盘 0 道 1 扇区的 512 个字节的最后两个字节分别是 0x55 和 0xaa,那么 BIOS 就会认为它是个启动区。

0x07c0

段基址向右移动四位,成为0x7c00, 即最开始存储内核程序的位置

写入到ds寄存器中,作为数据段基址

设置段寄存器值

0x90000

es附加段寄存器值,后序还需要复制给cs代码段寄存器、ds数据段寄存器、ss栈段寄存器

需要将存储在0x7c00中的内核程序移动个位置到0x90000

0xFF00

sp栈基址寄存器存储的值,此时实际栈顶位置为ss:sp也就是0x9FF00

加载内核代码

0x90200

加载setup程序部分,将硬盘的第 2 个扇区开始,把数据加载到内存 0x90200 处,共加载 4 个扇区

0x90200 + gdt

这里的gdt表示在setup.s中的偏移量,即全局描述符表是跟随着setup.s在最开始一起加载的,gdt就是用来获取各个段的段基址,然后和需要访问的内存的偏移地址计算出来得到物理地址

gdt中存储着代码段、数据段地址、LDT局部描述符地址

gdt的值存储在gdtr寄存器中

0x90200 + idt

同上,该内存地址中存储的是中断描述符表,地址值存储在idtr寄存器中

0x10000

加载system程序部分,从硬盘第 6 个扇区开始往后的 240 个扇区,加载到内存 0x10000

系统一些基本信息

内存地址 长度(字节) 名称 0x90000 2 光标位置 0x90002 2 扩展内存数 0x90004 2 显示页面 0x90006 1 显示模式 0x90007 1 字符列数 0x90008 2 未知 0x9000A 1 显示内存 0x9000B 1 显示状态 0x9000C 2 显卡特性参数 0x9000E 1 屏幕行数 0x9000F 1 屏幕列数 0x90080 16 硬盘1参数表 0x90090 16 硬盘2参数表 0x901FC 2 根设备号

最后一次复制

0x10000 - 0x90000 移动到 0x00000 - 0x80000

因为最开始的bootsect不需要了

进入保护模式后新的地址

重新设置gdt、idt从内存0开始而不是从0x90200开始

  • 0: 页目录表,存储在cr3寄存器,表示0地址处就是页目录表
  • 0x1000: 页表0
  • 0x2000: 页表1
  • 0x3000: 页表2
  • 0x4000: 页表3