您的位置:首页 > 其它

《Orange’s 一个操作系统的实现》3.保护模式7-特权级转移(通过调用门转移目标段-有特权级转换-理论)

2013-05-25 12:38 405 查看
A.关于堆栈

jmp指令:不影响堆栈

call指令:影响堆栈,对于短调用来说,call指令执行时会将下一条指令的eip压栈,到ret指令时,这个eip会被从堆栈中弹出。

对于长转移;还会将cs压栈

B.call指令堆栈示意图

假设函数foo(param1,param2,param3)

1.短调用时堆栈示意图





2.短调用返回时堆栈示意图





3.长调用时堆栈示意图





4.长调用返回时堆栈示意图(通过带参数的ret指令)





5.有特权级变换的转移及返回时的堆栈变化

转移时示意图





返回时示意图





由于堆栈可能会发生变化,所以intel提供了将堆栈A的诸多内容复制到堆栈b中。这里我们只涉及到连个堆栈,而事实上,由于每个任务

最多在都可能在4个特权级之间转移,所以每个任务实际上需要4个堆栈。原有的ss和一个esp就不能满足我们的需要,这是就要使用到

TSS(Task-State Stack),一个数据结构,包含多个字段

6.32位TSS结构如下





TSS字段偏移4到27的3个ss和3个esp,当发生堆栈切换时,内层的ss和esp就是从TSS里面取得.

C.转移过程概述

call过程(低特权->高特权)

1.根据目标代码段的DPL(新的CPL)从TSS中选择应该切换至哪个ss和esp

2.从TSS中取得新的ss和esp.在这个过程中如果发现ss、esp或者TSS界限错误都会导致无效TSS异常(#TS)

3.对ss描述符进行检验,如果发生错误同样产生#TS异常

4.暂时性地保存当前ss和esp的值

5.加载新的ss和esp

6.将刚刚保存的ss和esp的值压入堆栈

7.从调用者堆栈中将参数复制到被调用者堆栈(新堆栈)中,复制参数的数目有调用门中Param Count(最多31个参数,大于31可以使用结构指针)

一项来决定。如果Param Count 为0的话,将不复制参数

8.将当前的cs和eip压栈

9.加载调用门中指定的新的cs和eip,开始执行被调用的过程

ret过程(高特权->低特权)

1.检查保存的cs中的RPL以判断返回时是否要交换特权等级

2.加载被调用者堆栈上的cs和eip(此时会进行代码段描述符和选择子类型和特权级检验)

3.如果ret指令含有参数,则增加esp的值以跳过参数,然后esp将指向被保存过的ss和esp.注意,ret的参数必须对应调用门中的param count

4.加载ss和esp,切换到调用者堆栈,被调用者的ss和esp被丢弃。这里会进行你个ss描述符、esp以及ss段描述的检验

5.如果ret指令含有参数,增加esp的值以跳过参数(此时已经在调用者堆栈中)

6.检查ds、es、fs、gs的值,如果其中哪一个寄存器指向的段的DPL小于CPL(此规则不使用与一致代码段),那么一个空描述符会被加载到该

寄存器
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐