从零写OS(二):跨过这道门,CPU 才算醒了

上一章我们让机器打出了第一行字。但那时候 CPU 还处于一种"出厂状态"——实模式,最多只能用 1MB 内存,没有任何权限隔离,任何代码想写哪块内存就写哪块。 这对一个操作系统来说是不可接受的。 所以这一章要做一件事:把 CPU 从实模式切换到保护模式(Protected Mode,32 位工作模式,支持内存保护和权限隔离)。 为什么叫"保护"模式 名字来源很直接——这个模式下,内存是被保护的。 实模式里,程序可以随意读写任何内存地址,一个 bug 就能把整个系统搞崩。保护模式引入了两个机制: 内存段的权限描述:每块内存都有自己的访问权限,越界访问直接触发异常 特权级别(Ring):内核跑在 Ring 0,用户程序跑在 Ring 3,用户程序没法直接碰内核内存 现代操作系统全都建立在保护模式之上。 切换的关键:GDT 切到保护模式之前,必须先准备好 GDT(Global Descriptor Table,全局描述符表,内存里的一张表,描述每个内存段的地址、大小和权限)。 可以把 GDT 理解成一个"内存段登记簿"。CPU 进入保护模式后,所有内存访问都要查这张表,看看你有没有权限。 GDT 最少需要三项: 索引 用途 0 空描述符(CPU 规定必须全零,不能用) 1 代码段(可执行,Ring 0) 2 数据段(可读写,Ring 0) GDT 写好之后,用 lgdt 指令告诉 CPU 表在哪里,CPU 才知道去哪查。 切换步骤 整个切换过程就四步,缺一不可: 关中断(cli)—— 切换过程不能被打断,否则 CPU 状态会乱 加载 GDT(lgdt)—— 告诉 CPU 描述符表在哪 设置 CR0 寄存器(CR0.PE=1)—— CR0(控制寄存器0,控制CPU工作模式的关键寄存器)第0位置1,CPU 正式进入保护模式 far jump 刷新流水线 —— 跳转的同时加载新的代码段选择子,清空 CPU 的指令预取缓存 最后这一步很容易漏掉。CPU 有指令流水线,切换模式后如果不强制刷新,可能还在用旧模式的指令译码方式,导致莫名其妙的错误。 ...

May 6, 2026 · 1 min · 大飞
京ICP备14031575号-3