中转站,不是终点
收工了,咱们把本站攒下的东西归置归置。
本站最值钱的家当,就是三项的扁平 GDT:base 记的是全零、限长开的是 4GB,选择子就是条目的偏移。咱们用 C++ 的 packed 结构体和 constexpr 工厂把它落了地,每一个数字都有断言守着的,人读的讲解和机器读的检查,出自的是同一份代码。
CR0 的第 0 位,咱们是读出来、改了一位、写回去,只动得了它一个。拨了过去,CPU 名义上就换了世界,配上紧跟着的远跳,名义才成了事实。
工程那头立的界线,这回长进了构建系统里:ljmp $0x08, $PmEntry 的两边住着两个编译世界,16 位的一侧有 stage2 全部的起居代码,32 位的一侧有跨过门槛之后的头一份产业。界线靠的是一个 OBJECT 库加一套 cinux_boot32,固定在了 CMake 里,咱们谁打开都看得见。
至于跨过去之后的日子,咱们已经过了一小段了:地址自己就是线性地址,1MB 的天花板没了,段上的权限立起来了,栈安在了 0x90000,输出通道整行整行地工作着。BIOS 也正式成了路人——咱们没再叫过它,它也叫不应咱们了。
这里得跟您把期望摆正:32 位保护模式,对咱们来说是个中转站。x86_64 的故事在 64 位,咱们真正要去的也是那儿。可从实模式到 64 位没有直达的车,保护模式就绕不开了——长模式是从它身上接着发育起来的。下一站要办的事,咱们预告过:分页得建起来,0x1000 起的三张表地界一直空到了今天,也该住进去了。CR4.PAE、EFER.LME、CR0.PG,几位开关咱们要挨个地拨,末了还得再来一次远跳,带着一个 64 位的代码段选择子、再跨一回门槛。您在本站练下的手感,拨开关只动一位、四步的次序一步不能乱、远跳之后世界才算换过,这些到了下一站全都用得上,而且是翻着倍地用。
考古箱里翻出一件对得上的,咱们看一眼就走。当年第一遍的时候,保护模式的切换跟 VESA 复盘、E820 的收尾,挤在同一个晚上一起干完了,那天的笔记写得密密麻麻,一个 PM 切换的复盘就抵得上半天的活。这一遍咱们把它单拎了出来、一节只消化一个认知点,一步一步走完了。咱们现在知道了,这段路是值得单独慢慢走的。
本站的外部依据,咱们在这里一并归拢:Intel SDM Vol.3A 的 §3.4.4(GDTR 与 LGDT 的结构)、§9.9.1(切换到保护模式之前装载 GDTR)、§9.9.2(进入保护模式后必须远跳加载新的 CS)。社区视角在 OSDev 的 GDT 页和保护模式页。当年的调试现场,咱们在调试档案里另存了一份细目:实模式到保护模式切换的几个要害。