下面说明代码段和数据段的访问:
一、代码段间跳转
1、普通(直接)跳转:
JMP Selector:0 或 CALL Selector:0
1)一致代码段(JMP&CALL)
要求:CPL>=DPL,RPL不作检查
特权变化:跳转后程序CPL=跳转前程序CPL
2)非一致代码段(JMP&CALL)
要求:CPL=DPL & RPL<=DPL
特权变化:跳转后程序CPL=目标代码段DPL
2、通过调用门跳转:
JMP 调用门Selector:0 或 CALL 调用门Selector:0 (注意:此时如果选择子后面跟着32位偏移量也不会被CPU使用,因为调用门描述符已经记录了目标代码的偏移)
step1: 要求:指示调用门的选择子的RPL<=门描述符DPL & 当前代码段的CPL<=门描述符的DPL。
只有满足以上条件时,CPU才会进一步从调用门描述符中读取代码段的选择子或地址偏移。而从调用门中读取代码选择子和地址偏移后,跟普通跳转又站在同一起跑线上了。
唯一不同的是CPU会将目标代码段RPL清0。此后需要分类讨论,如下:
step2:
1)一致代码段(JMP&CALL) <------------------------------------------------------------------------------------------------------
要求:CPL>=DPL,RPL不作检查(因为RPL总被清0) |
特权变化:跳转后程序CPL=跳转前程序CPL |
比较
2)非一致代码段(JMP) |
要求:CPL=DPL,RPL不作检查(因为RPL总被清0) |
特权变化:跳转后程序CPL=目标代码段DPL |
3)非一致代码段(CALL) <------------------------------------------------------------------------------------------------------------
要求:CPL>=DPL,RPL不作检查(因为RPL总被清0)
特权变化:跳转后程序CPL=目标代码段DPL(CPL>DPL的情况下,特权级发生跃迁)
二、访问数据段
数据段:特权级低->高:NO | 特权级高->低:YES | 特权级同级之间:YES
注意:
1、一致代码段:无论那种方式跳转到一致代码段,CPL都不会改变(不变化为目标代码段的DPL),也即加载目标代码段选择子时,只加载高14位,表示CPL的低2位保持不变。
因此,“一致”的意思就是——代码段被调用执行时,不使用自己描述符的DPL,而采用调用这特权级,CS的低2位保持不变(与“调用者保持一致”)
2、非一致代码段:无论采用哪种方式跳转到非一致代码段,CPL都发生变化,也即在加载目标代码段选择子时,将整个选择子放入到CS中。
3、为了访问调用门,调用者程序的特权级CPL必须小于或等于调用门的DPL。调用门段选择符的RPL也要同调用CPL一样遵守相同的规则,即RPL也必须小于或等于调用门的DPL。如图:
参考:
http://www.cnblogs.com/wanghj-dz/archive/2011/04/23/2025840.html