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

A.关于堆栈

   jmp指令:不影响堆栈

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

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

B.call指令堆栈示意图

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

   1.短调用时堆栈示意图

51B54}P2X59GTW5{BSL03G5[4]

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

[68GQMTTDB5Z6ZG6T59@]6Q

   3.长调用时堆栈示意图

OEPQLY~}AHH]}BMU5257O7U

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

JBS)`9(4T~9H%0[4N3O[@YF

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

       转移时示意图

[5)V4XR4))A3O`5C9~$3RNT

    返回时示意图

K]HT6P(V_B5DZVK{W1B~91S

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

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

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

6.32位TSS结构如下

   image 

   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(此规则不使用与一致代码段),那么一个空描述符会被加载到该

      寄存器

你可能感兴趣的:(操作系统)