现在的位置: 首页 > 综合 > 正文

保护模式及其编程——实模式与保护模式的切换

2017年05月25日 ⁄ 综合 ⁄ 共 1790字 ⁄ 字号 评论关闭

机器上电,CPU进入实模式,从物理地址0xFFFFFFFF0处开始执行初始化代码,设置基本系统功能操作必要的数据结构信息,例如处理中断和异常的IDT表。接下来,如果继续在保护模式工作,需要加载操作系统模块;如果要进入实模式,那么需要进行模式切换。

1.进入保护模式时的初始化操作

处理器能够进入到保护模式之前,需要操作系统加载和初始化软件必须在内存中设置好保护模式下使用的数据结构的基本信息。这些数据结构包括
1)保护模式中断描述符表IDT
2)GDT
3)任务状态段TSS
4)LDT
5)如果使用分页机制,起码要设置一个页目录和一个页表
6)处理器切换到保护模式下运行的代码段

能够切换到保护模式运行之前,需要设置以下系统寄存器
1)GDTR
2)中断描述符表基地址寄存器
3)控制寄存器CR1~CR3

初始化这些数据结构、代码模块和系统寄存器之后,通过设置CR0寄存器的保护模式标志位PE,处理器就可以切换到保护模式运行了。

1.1保护模式系统结构表


为了实现无分页的平坦内存模型,必须设置至少一个代码段和数据段到GDT。在GDT可以使用之前,必须要使用LGDT指令将GDT表的基地址和长度加载到GDTR之中。

多段模型需要操作系统的其他段,以及用于每个应用程序的段和LDT表段。

1.2保护模式异常和中断初始化


初始化代码必须设置一个保护模式IDT,其中至少包含有处理器可能产生的每个异常向量对应的门描述符。

在可以使用IDT之前,必须使用LIDT指令将IDT表基地址和长度加载到IDTR寄存器之中。

1.3分页机制初始化


分页寄存器由控制寄存器CR0中的PG标志设置,在设置PG标志之前,必须先初始化以下数据结构和寄存器:
1)软件必须在物理内存中建立至少一个页目录和一个页表
2)把页目录表的物理基地址加载到CR3寄存器中
3)处理器处在保护模式下

为了保持兼容性,设置PG标志时候必须遵从以下规则:
1)设置PG标志的指令应该立即跟随一条JMP指令
2)设置PG标志和JMP之间的代码必须来自对等映射(跳转之前的线性地址与开启分页之后的物理地址相同)的一个页面上。

1.4多任务初始化


如果需要使用多任务机制或者允许改变特权级,那么软件初始化代码需要设置一个TSS及相应的TSS段描述符(因为特权级0、1、2的各栈段指针都需要从TSS中取得)。

在处理器切换到保护模式以后,可以用LTR指令把TSS段描述符的选择符加载到任务寄存器TR中。在保护模式中,软件进行第一次任务切换之前必须首先加载在TSS段的选择符,因为任务切换会把当前任务状态复制到该TSS中。

在LTR指令执行之后,随后对任务寄存器的操作由任务切换进行。

2.模式切换


2.1切换到保护模式


切换到保护膜是之前,必须首先加载一些起码的系统数据结构和代码模块。切换操作的步骤:
1)使用cli指令禁止终端
2)执行LGDT命令,加载GDT
3)设置CR0(PE位)
4)mov cr0 之后立刻跟一个远程JMP或者远程call指令
5)选择性执行LLDT
6)执行LTR指令,用初始保护模式任务的段选择符或者可写内存区域的段描述符加载任务寄存器TR
7)进入保护模式后,段寄存器仍人含有在实地址模式时候的内容,需要进一步处理
8) LIDT
9)开中断 sti

2.2切换回来实模式


1)禁止终端
2)如果开启分页机制,那么需要执行:
把程序的控制转移到对等映射的线性地址处
确保GDT和LDT在对等映射的页面上
清楚CR0中的PG标志
设置CR3寄存器为0x00,用于刷新TLB缓冲
3)把程序的控制转移到长度为64KB(0xFFFF)的可读段中。这部操作使用实模式要求的段长度加载CS寄存器
4)使用含有一下设置值的描述符选择符来加载SS、DS、ES、FS、GS
段长=64kb
颗粒 G=0
向上扩展 E=0
可写 w=1
存在 p=1
5)执行LIDT指令来指向在1MB实模式地址范围内的实地址模式中断表
6)清楚cr0中的PE位
7)执行一个远跳转指令跳转到一个实模式程序中。这个操作会刷新指令队列,并且为CS寄存器加载何时的基地址和访问权限值
8)加载实地址模式程序代码会使用的SS、DS、ES、FS、GS

9)执行STI指令开启可屏蔽硬件中断,并且执行必要的硬件操作开启NMI中断

这里,我们特别留意其中的第4步和第8步,尤其是第4步中,设置SS等寄存器的目的是为了保证SS等寄存器的不可见部分,到了实模式之下,仍然有正确的属性值。

抱歉!评论已关闭.