保护模式下的跳转

主要是两类:

不改变特权、改变特权

1. 不改变特权级可以用段间、段内的call或者jmp。段间不做判断。段间会看目的段是什么代码段。

如果是非一致代码段,则必须CPL=DPL,并且RPL<=DPL。跳转后CPL不变。
如果是一致代码段,对RPL不做判断,则必须CPL>=DPL,即外环可以跳入内环,但CPL不变。

2. 改变特权级,必须通过门(调用门、任务门、中断门、陷阱门)。通过门由外环跳入内环,通过ret、lret、inet跳回外环。


段间转移:用48位地址(选择子+偏移量)描述要跳转的地址。
直接段间转移:直接用48位地址
间接段间转移:用指向48位地址的调用门、人物们、TSS描述符。这时只有描述子有用,偏移量无作用。具体地址是看门对应的地址。

JMP不管是直接还是间接,都只能是同特权级之间跳转。


当段间转移指令JMP和段间调用指令CALL所含指针的选择子指示调用门描述符时,就可以实现通过调用门的转移。但只有CALL指令能变换到内层的特权级,JMP指令只能转移到同级的代码。

调用门描述符转移的入口点包含目标地址的段及偏移量的48位全指针。在执行通过任务门的段间转移指令JMP或段间调用指令CALL时,指令所含指针内的选择子用于确定调用门,而偏移被丢弃;把调用门内的48位全指针作为目标地址指针进行转移。

处理器采用与访问数据段相同的特权级规则控制对门描述符的访问。调用门描述符的DPL规定了访问该门的最外层特权级,在取出调用门内的48位全指针,把它作为目标地址指针向目标代码段转移之前,要进行特权级检查。只有在相同级或者更内层特权级的程序才可访问调用门,即CPL<=调用门的DPL。同时,还要求指示门的选择子的RPL必须满足RPL<=调用门的DPL的条件。检测通过后,才开始向目标代码段转移的步骤。其中还要检测目标描述符是否为代码段描述符,调用门内的选择子指示的描述符必须是代码段描述符。此外,在装载代码段描述符高速缓冲寄存器之前调整代码段选择子的RPL=0,也即调用门中代码段选择子的RPL被忽略。

在装载CS高速缓冲寄存器时,还要对目标代码段描述符进行保护检测。检测过程中的DPL不再是调用门的DPL,而是调用门内选择子所指示的目标代码段描述符的DPL。段间调用指令CALL和段间转移指令JMP所做的检测不一样。

对于使用调用门的段间转移指令JMP,检测条件与段间直接转移相同。由于已置RPL=0,所以可认为 RPL<=DPL的条件总能满足。所以,对于普通的非一致代码段,当CPL=DPL时,发生无特权级变换的转移;对于一致代码段,在满足CPL>=DPL时也发生无特权级变换的转移;其它情形就引起异常。

对于使用调用门的段间调用指令CALL,情形就不同了。由于已置RPL=0,所以可认为RPL<=DPL的条件总能满足。对于一致代码段,在满足CPL>=DPL时发生无特权级变换的转移。对于非一致代码段,当CPL=DPL时,仍发生无特权级变换的转移;当CPL>DPL时,就发生向内层特权级变换的转移,将调用门中的选择子和偏移装入CS和指令指针EIP中,并使CPL保持等于DPL,同时切换到内层堆栈。

综上所述,使用段间调用指令CALL,通过调用门可以实现从外层程序调用进入内层程序(JMP指令只能实现无特权级变换的转移);通过调用门也可实现无特权级变换的转移。需要注意的是,JMP指令和CALL指令都不能实现向外层特权级的转移否则会引起异常。

当然,CALL指令在最后把目标代码段的指针装入CS和EIP之前,要把原CS和EIP,即返回地址保存到堆栈。如无特权级变换,堆栈保持不变,返回地址就保存在原堆栈中;否则,返回地址保存在内层堆栈中。

转载于:https://www.cnblogs.com/fanzi2009/archive/2009/05/29/1491886.html

猜你喜欢

转载自blog.csdn.net/weixin_33997389/article/details/94192654
今日推荐