x86 保护模式浅析 (2)

走进保护模式

A20 地址线

在本文中,要完全解释 A20 地址线的作用以及原理是不太现实的。对于我们程序员而言,我们只需要了解一些大致的概念。简单来说,因为考虑到向下兼容性,A20 地址线在默认情况下是禁用的。于是,我们得启用它,这样我们就可以访问全部内存,这对于 CPU 在保护模式下正常工作是十分重要的

至于如何启用 A20 地址线,OSDev 上面列举了很多方法,可以参考链接:
https://wiki.osdev.org/A20
这里,我们列举比较简单的一种方法,在大多数情况下是可正常使用的 (对于一些老主板,需要主板CMOS设置中启用快速 A20 支持)

  • 快速 A20 门 (Fast A20 Gate)
in al, 92h    ; 从 92h 端口读一字节
or al, 2      ; 置字节的第 2 位为 1
out 92h, al   ; 写回 92h 端口

上述的 Fast A20 Gate 方式只需要 3 条指令就可以启用 A20 地址线,当执行完这 3 条指令后,CPU 就有能力访问全部内存了

关闭中断 (包括 NMI 在内)

保护模式下,CPU 的中断机制与实模式是不相同的。BIOS 中断、中断向量表都不再适用于保护模式,在进入保护模式之前,需要先使用 CLI 指令以关闭中断

cli    ; 关闭中断

设置 GDTR 寄存器

在上一篇文章中,我们讲到 GDT、段选择子的概念,在进入保护模式前,首先要正确地设置 GDTR 寄存器,确保 GDT 的设置是有效的

lgdt m48    ; 48 位(6字节)向量,低字表示 GDT 界限(字节大小减1),高双字表示 GDT 头部的线性地址

设置控制寄存器的PE位

CPU 内部的 0 号控制寄存器(CR0)中的最低位即是PE(Protection Enable,保护生效)位,将其置为 1 时,CPU 将工作在保护模式下,汇编代码可以像下面这样写

mov eax, cr0
or al, 1      ; 置 PE 位为 1
mov cr0, eax

命运的跳转 (jmp dword 方式)

jmp dword 段选择子偏移:跳转到的地址

其中,段选择子偏移就是对应段选择子(一般是代码段选择子)相对于GDT头部的偏移字节数,而跳转到的地址,即是在段选择子的段界限内的地址。因为 PE 位的设置,现在 CPU 在保护模式下,所以得用段选择子和线性地址的方式去访问内存

至于为什么要 jmp dword,是因为现在 CPU 还在 16 位机器代码上执行跳转,但是跳转的地址却是用 32 位保护模式的方式寻址的。jmp dword 能够使 CPU 的流水线清空,并串行化执行跳转后的 32 位机器代码,这样 CPU 就能在保护模式下正常运行。

后续

光说不练假把式,也许你还是只有一些笼统的概念。下一篇文章,笔者将用整个实例来演示并穿插解释一段引导扇区程序是如何一步步进入保护模式的。感谢阅读本文!

📅 更新时间:2019/05/28 Tuesday 13:07

🖊️ 本文由 Alone Café 创作,如果您觉得本文让您有所收获,请随意赞赏 🥺
⚖️ 本文以 CC BY-NC-SA 4.0,即《署名-非商业性使用-相同方式共享 4.0 国际许可协议》进行许可
👨‍⚖️ 本站所发表的文章除注明转载或出处外,均为本站作者原创或翻译,转载前请务必署名并遵守上述协议
🔗 原文链接:https://alone.cafe/2019/05/x86保护模式浅析2
📅 最后更新:2019年05月28日 Tuesday 13:07

评论

Your browser is out of date!

Update your browser to view this website correctly. Update my browser now

×