x86架构的基本运行环境

从CPU的角度来看,程序不过是一组指令并按编译时生成的顺序执行。执行的过程中会从内存中取值并在寄存器中操作,以得到期望的结果。此外还有一些特殊的寄存器对CPU的状态和行为进行控制。下面介绍一下x86架构的基本运行环境。

三种基本模式

实际上x86有4种运行模式:实模式、保护模式、SMM模式和虚拟8086模式。除SMM模式外,其他三种模式常见于各种教科书,对理解x86CPU工作极为重要,在此也对他们进行简要介绍。

实模式:当CPU加电并经历最初的混沌状态后首先进入的就是实模式,它是早期Intel8086 处理器的工作模式。在该模式下,逻辑地址转换后即为物理地址,CPU可以访问1MB的物理地址空间(1MB+64KB)。操作系统或者BIOS通常在该模式下准备必要的数据结构和初始化关键的寄存器,然后切入保护模式。

保护模式:操作系统运行最常用的模式。在该模式下,CPU的所有功能几乎都能得到使用,可以访问架构允许的所有物理地址空间。本章的讲解,如无特殊说明,都是基于保护模式进行的。

虚拟8086模式:为了使早期的8086程序能在保护模式下运行,x86提供了虚拟8086模式。该模式可以让CPU在保护模式下为8086程序虚拟实模式的运行环境,使这些程序在执行时无须真正的从保护模式切换到实模式。

基本寄存器组

寄存器是软件操作CPU的最基本部件,X86架构的寄存器可以粗略的分为以下几类。

1通用寄存器:共有8个32位的寄存器,例如常见的EAX、EDX等,用来保存程序运行时的临时变量、栈指针等数据。

2、内存管理寄存器:包括段寄存器和描述符表寄存器。

3、EFLAGS寄存器:32位的寄存器,用来保存程序运行中的一些标志信息,如溢出、开启中断与否、分支跳转等信息。

4、EIP寄存器:32位寄存器,用来保存指向当前指令的地址。通常教科书中称该寄存器为PC指针。

5、浮点运算寄存器:对于浮点运算,x86会通过一个浮点运算协处理器来处理。协处理器中包括8个80位的浮点数据寄存器,1个16位的控制寄存器,1个16位的状态寄存器,1个16位的标志寄存器,1个11位的指令码寄存器,1个48位的浮点指令指针寄存器和1个48位的浮点数据寄存器。这些浮点运算寄存器为浮点运算提供一个基本的运行环境。

6、控制寄存器:x86提供了5个控制寄存器,分别是CR0~CR4寄存器。这些控制寄存器决定了CPU运行的模式和特征等。

7、其他寄存器:x86还提供了其他一些寄存器,包括了8个调试寄存器DR0~DR7、内存区域类型寄存器、机器检查寄存器以及性能监控寄存器。

权限控制

权限控制是指CPU对资源进行分类,使不同权限的程序只能访问自身权限所允许访问的资源。操作系统的用户态和内核态之分就是最常见的权限控制,内核态程序具有最高权限,用户态程序具有最低权限。x86架构提供两种权限控制机制-----段保护和页保护。这两种机制对应内存管理中的段机制和分页机制,下面分别进行介绍。

1、段保护

段保护引入了如下三种属性对权限控制进行控制。

(1)当前权限级别CPL:CPL表示当前运行的代码权限。通过CS的0、1位记录代码的CPL值,CPL可以有0~3共4个级别,这就是常说的ring级别。其中,Ring0对应CPL=0,具有最高权限,操作系统中的内核运行在该权限;Ring3对应CPL=3,用户程序运行在Ring3。CPL值越高权限越低。

描述符权限级别DPL:DPL表示段和门所具有的权限。它表示代码访问某个段或者通过某个门时所需要的最低权限。例如某个数据段描述符有DPL=2,则只有CPL=0、1、2的代码可以访问该数据段,CPL=3的不能访问。

所要求权限级别RPL:RPL比较特殊,它存在于段寄存器的0~1位,用于程序在访问段时间时增加一级检查。其用途见后面的例子。

程序访问一个段,要通过段寄存器得到段描述符,这样会产生2次检查,参与检查的3个属性分别是:程序本身的CPL、段寄存器的RPL、段描述符的DPL、CPL、DPL、RPL组合起来的情况有很多种,但只有当CPL<=DPL且RPL<=DPL时,访问才被允许,其余情况均被拒绝。通常可以把RPL设置成0来简化检查,此时,满足CPL<= DPL访问即被允许。

页保护

页保护的思想比段保护简单,它通过再页目录项、页表项中引入一个User/Supervisor位,将页面或整个页目录项分成User和Supervisor两个特权级。该位为0时表示Supervisor模式,对应CPL=0、1、2的情况;为1表示User模式,对应CPL=3的情况。当程序运行在CPL=0、1、2也就是SuperVisor模式下时,可以访问所有页面;运行在CPL=3下的程序处于User模式只能访问User页面。

段保护和页保护是可以混用的从面带来了更为灵活的保护机制。