3.2.3节:特权级

来源:互联网 发布:英国大学 档次 知乎 编辑:程序博客网 时间:2024/06/08 17:42

原来看第3.2.3节的时候,感觉很难的。为什么会感觉难呢? 因为这一节谈到的特权级别关系比较复杂,不容易弄清楚。这次重看一次这一节后,进行了一点小结,这才感觉比较清楚了。
      这一节的主要内容可以用下面这个表格来描述。

目标代码段

Jmp指令

Call指令

直接调用

通过调用门

一致码段

CPL>=DPL,不检查RPL

可以跳转到相同或者更高特权级别执行

CPL<=DPL_G,RPL<=DPL_G

CPL>=DPL

访问调用门的规则同访问数据段,即调用门只能被特权级别不低于其DPL(DPL_G)的代码访问。可以跳转到相同或者更高特权级别执行。

非一致码段

RPL<=CPL=DPL

只能跳转到同特权级别的代码段

 

1.  三种特权级别

CPL:当前特权级别。当前正在运行的代码所处的特权级别,保存在CS和SS的低2位中。

DPL:描述符特权级别,即段描述符中DPL字段的值,是与描述符相关的特权级别。

RPL:请求特权级别,即用于访问代码、数据或者堆栈的段选择子低2位的值。

注意特权级别的表示:有0至3这4个特权级别,0级最高,3级最低,即数字大则特权级别低。表中CPL、RPL、DPL等都是代表数字的。

2. 一致码段和非一致码段

(1)一致码段:无论采用哪种方式跳转到一致码段,CPL都不改变(不变化为目标代码段的DPL),也即在加载目标代码段选择子时,只加载高14位,表示CPL的低2位保持不变。

(2)非一致码段:无论采用哪种方式跳转到非一致码段,CPL都发生改变,也即在加载目标代码段选择子时,将整个选择子放入到CS中。

“一致”的意思就是:代码段被调用执行时不使用自己的描述符的DPL,而采用调用者特权级别,CS的低2位保持不变,与调用者特权级别保持一致。

是不是一致码段由描述符中的相应位标志确定(参看47到49页的表格)。

3. Jmp与Call

Jmp指令仅仅进行执行流程的跳转,不会保存返回地址。

Call指令在进行流程跳转前会保存返回地址,以便在跳转目标代码中可以使用ret指令返回到call指令的下一条指令处继续执行。执行段内跳转时,只保存EIP;如果是段间跳转,还保存CS。

对于使用Call指令(无论是直接调用还是通过调用门)进行的跳转,如果跳转后特权级别将发生改变(总是从低到高,从上述第2点知道,只有跳转到非一致码段时才会发生特权级别变化),则执行call指令前必须准备好任务状态段TSS。跳转过程是:(1)保存调用者的SS和ESP到被调用者堆栈中(2)调用参数先保存在调用者堆栈中,然后被复制到被调用者堆栈中(3)当前CS和EIP被保存到被调用者堆栈中。在通过call进行的有特权级别变化的跳转中,堆栈会发生切换,这时要保存当前堆栈指针(SS:ESP),而当前指令指针(CS:EIP)保存到新的堆栈(被调用者堆栈)中,这是与没有特权级别变化的跳转不同的。没有特权级别变化时,不需要保存SS:ESP,不存在调用参数的复制,不存在堆栈切换。

4. ret和retf

这两个指令的功能都是调用返回。

(1) ret在返回时只从堆栈中取得EIP;retf中的字母f表示far,即段间转移返回,要从堆栈中取得EIP和CS。

(2)两个指令都可以带参数,表示发生过程调用时参数的个数,返回时需要从堆栈中退出相应个数的参数

(3)恢复CS时,如果发现将发生特权级别变化(当前CS的低2位不等于从堆栈中取得的新的CS值的低2位。从上述第2点知道,只有跳转到非一致码段时才会发生特权级别变化,那么,也只有从非一致码段返回时才会发生特权级别返回),则还要从调用者堆栈中取得ESP和SS恢复到相应寄存器中,也即恢复调用者堆栈。

5. 任务状态段TSS

为避免相互干扰,要求不同特权级别的代码运行时使用不同的堆栈,也就是在特权级别发生改变时必须切换堆栈段。0、1、2特权级别的堆栈指针保存在TSS中,在跳转到相应级别时从TSS中取出相应的堆栈指针进行堆栈切换。因为只有从低特权级别跳转到高特权级别时才需要从TSS中取得新的堆栈指针,所以TSS中不存在最低特权级别3的堆栈指针。

 

综上所述,所有的复杂只有一点:仅仅在通过调用门从低特权级别跳转到高特权级别的非一致码段时,才会发生CPL改变,才需要先准备好TSS,才会发生堆栈切换(在调用前从TSS中取得新的堆栈指针;调用返回时从被调用者堆栈中取得原堆栈指针进行恢复)。

CPL、RPL、DPL的区别


CPL(Current   Privilege   Level) 当前(代码)特权级。在保护模式下,CS寄存器、SS寄存器中分别存放着代码段、堆栈段的选择子。CPL在CS、SS的第0、1位(第0位到15位)中。CPL一般情下等于所装载的段的特权级。对于一致代码段来说,CPL不会随着所装载的段的特权级而改变。

DPL(Descriptor   Privilege   Level) 描述符特权级在每个存储段(数据段、代码段、堆栈段)描述符、门(调用门、任务门、中断门、陷阱门)描述符、任务状态段(TSS)描述符的第5个字节(第0字节到第7字节)的第5、6位(第0位到第7位)中。DPL主要用来与CPL比较,来确定当前代码是否能够访问相应的段。

RPL(Request   Privilege   Level) 选择子特权级,在每个选择子的第0、1位(第0位到15位)中。RPL主要用来改写CPL,当进行段访问的时候,取CPL和RPL中数值大的一个(即取权限小的一个)。如:CPL为0,要访问的调用门DPL为2,但是选择子的RPL为3,此时不可以访问调用门。

0 0
原创粉丝点击