从实模式进入保护模式的步骤

从实模式进入保护模式的步骤

Content #

为了保证代码在不同种Intel处理器中的前后兼容性,建议遵循以下步骤执行模式切换操作(请参考Intel官方白皮书Volume 3的9.9.1节)。 (1) 执行CLI汇编指令禁止可屏蔽硬件中断,对于不可屏蔽中断NMI只能借助外部电路才能禁止。(模式切换程序必须保证在切换过程中不能产生异常和中断。) (2) 执行LGDT汇编指令将GDT的基地址和长度加载到GDTR寄存器。 (3) 执行MOV CR0汇编指令位置CR0控制寄存器的PE标志位。(可同时置位CR0控制寄存器的PG标志位。) (4) 一旦MOV CR0汇编指令执行结束,紧随其后必须执行一条远跳转(far JMP)或远调用(far CALL)指令,以切换到保护模式的代码段去执行。(这是一个典型的保护模式切换方法。) (5) 通过执行JMP或CALL指令,可改变处理器的执行流水线,进而使处理器加载执行保护模式的代码段。 (6) 如果开启分页机制,那么MOV CR0指令和JMP/CALL(跳转/调用)指令必须位于同一性地址映射的页面内。(因为保护模式和分页机制使能后的物理地址,与执行JMP/CALL指令前的线性地址相同。)至于JMP或CALL指令的目标地址,则无需进行同一性地址映射(线性地址与物理地址重合)。 (7) 如需使用LDT,则必须借助LLDT汇编指令将GDT内的LDT段选择子加载到LDTR 寄存器中。 (8) 执行LTR汇编指令将一个TSS段描述符的段选择子加载到TR任务寄存器。处理器对TSS段结构无特殊要求,凡是可写的内存空间均可。 (9) 进入保护模式后,数据段寄存器仍旧保留着实模式的段数据,必须重新加载数据段选择子或使用JMP/CALL指令执行新任务,便可将其更新为保护模式。(执行步骤(4)的JMP或CALL指令已将代码段寄存器更新为保护模式。)对于不使用的数据段寄存器(DS和SS寄存器除外),可将NULL段选择子加载到其中。 (10) 执行LIDT指令,将保护模式下的IDT表的基地址和长度加载到IDTR寄存器。 (11) 执行STI指令使能可屏蔽硬件中断,并执行必要的硬件操作使能NMI不可屏蔽中断。

From #

一个64位操作系统的设计与实现