您的位置:首页 > 其它

桌面电脑操作系统开发笔记(4)——进入32位保护模式

2014-05-16 14:13 357 查看
桌面电脑操作系统开发笔记(4)——进入32位保护模式



要获得32位的内存寻址能力和将内核层和应用层隔离开,就需要进入32位保护模式。要进入64位保护模式,也要先进入32位保护模式。

要进入32位保护模式,首先要解决一个历史遗留问题,就是A20地址线的问题。这个问题产生的原因在这篇文章中有详细的说明:/article/10507978.html

通常有三种方法打开A20地址线:通过BIOS中断服务int 15h,AX=2401h、通过8042键盘控制器、通过端口92h。

OSdev Wiki中对这三种方法有详细的说明:http://wiki.osdev.org/A20_Line

我认为,BIOS开启A20的中断服务应该已经普遍可用而且比较可靠,是优先选择的方法。其次比较可靠的方法是通过8042,但对8042编程比较复杂。Linux内核也是依次选择BIOS中断服务、8042和端口92h三种方法,参见https://github.com/torvalds/linux/blob/master/arch/x86/boot/a20.c

而MenuetOS(一个用汇编语言编写的小操作系统,参考http://en.wikipedia.org/wiki/MenuetOS)直接使用了通过端口92h打开A20的快速方法,参考其官方网站http://www.menuetos.net

打开A20地址线后,还要禁止所有中断,包括不可屏蔽中断(non-maskable interrupt,缩写NMI),在Linux和MenuetOS中还有协处理器复位(发送0到端口0xF0和0xF1)。

要屏蔽中断控制器PIC(8259)上的所有中断,发送0xFF到从PIC的端口0xA1,发送0xFB到主PIC的端口0x21。关于8259PIC的编程,可参考http://stanislavs.org/helppc/8259.htmlhttp://wiki.osdev.org/8259_PIC

cli指令并不能禁止不可屏蔽中断NMI。而在模式切换时发生中断会使处理器出错复位。要屏蔽NMI,发送位7设1的值到实时时钟(real time clock,RTC)的控制端口70h。最后执行中断屏蔽指令cli。关于实时时钟的编程,可参考http://stanislavs.org/helppc/cmos_ram.html

在进入32位保护模式之前,必须至少准备好全局描述符表(global descriptor table,GDT)和中断描述符表(interrupt descriptor table,IDT)并将其基础地址和段界限分别加载到全局描述符表寄存器(GDTR)和中断描述符表寄存器(IDTR)中。

接下来可以将控制寄存器CR0的保护模式开启位PE(位0)设1,然后通过一个远跳转跳转到一个32位代码段中(在远跳转完成之前CS寄存器还没有改变,还在执行实模式的16位代码),这样就进入了32位保护模式。

进入32位保护模式后,必须先设置SS、DS、ES、FS、GS这些数据段寄存器为32位的数据段,否则访问数据时可能会导致段访问异常。

接下来要重新初始化中断控制器8259,重新映射其中断号,否则其中断号会跟IA32使用的保护模式异常重叠。

如果中断描述符表和相应的中断处理程序已经准备好的话,现在可以打开中断(包括NMI)。

有关32位保护模式初始化、切换、段描述符和描述符表等的内容,请见Intel的处理器架构手册卷3的第2、3、5、6、9章,和AMD的处理器架构手册卷2的第4、8、14章。我也翻译过Intel手册第2、3章中关于分段的数据结构的图表:/article/10151274.html

Intel 64和IA-32架构软件开发者手册可从Intel的网页下载:http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html

AMD架构手册可从AMD的网页下载:http://developer.amd.com/resources/documentation-articles/developer-guides-manuals/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: