【0】README

text description from orange’s implemention of a os and for complete code ,please visit https://github.com/pacosonTang/Orange-s-OS/blob/master/p62.asm.


【1】 回忆——关于堆栈

通过调用门进行有特权级变换的转移——理论篇

  • (1)出现的问题: call 指令 执行前后的堆栈已经不再是同一个堆栈 了,那么我们在堆栈A中压入参数和返回地址, 需要出栈(ret or retf)时,堆栈却变成了堆栈B, 这该怎么办呢?
  • (2)解决方法: Intel提供一种机制, 将堆栈A的内容复制到 堆栈B中, 如下图;



  • (3)TSS闪亮登场(task-state segment -任务状态段)

    (不同特权级的代码段间的转移,会发生堆栈切换,使得调用者的入栈的堆栈是针对调用者本身的堆栈, 而出栈操作是针对被调用者的堆栈,即入栈和出栈的堆栈不一致,使得特权级间跳转出错,故引入了 TSS)

  • 出现的问题: 由于每个任务可能在4个特权级间转移,故每个任务实际上需要4个堆栈;问题是:我们只有一个ss 和 esp, 那么当发生堆栈切换,我们该从哪里获取其他堆栈的ss 和 esp 呢?

  • 解决方法: 我们引入TSS, 它可以解决这个问题, TSS 数据结构 和 TSS段描述符的数据结构 如下;




【2】举个荔枝:

如,我们当前在ring3 , 当转移只ring1 时, 堆栈将被自动切换到由 ss1 和 esp1 指定的位置。由于只是在外层到内层(低特权级到高特权级)切换时,新堆栈才会从TSS中取得,所以TSS 并没有位于最外层 ring3 的堆栈信息;

(2.1)转移的过程中,CPU所做的工作:

  • 1) 根据目标代码段的DPL,从TSS中选择应该切换到哪个ss 和 esp;
  • 2) 从TSS 中读取新的ss 和 esp。在这个过程中,若发现ss、esp 或者 TSS 界限错误都会导致无效 TSS异常;
  • 3) 对ss 描述符进行检验,若发生错误,同样产生#TS异常;
  • 4) 暂时性保存当前ss 和 esp 的值;
  • 5) 加载新的 ss 和 esp;
  • 6) 将刚刚保存起来的ss 和 esp 的值压栈;
  • 7) 从调用者堆栈中将参数 复制到被调用者堆栈中(新堆栈中), 复制参数的数目由调用门中 Param Count一项来决定;
  • 8) 将当前的 cs 和 eip 压栈;
  • 9) 加载调用门中指定的新的cs 和 eip, 开始执行被调用者过程;

(2.2)从被调用者到调用者的返回过程中, 处理器的工作:

(实际上,ret这个指令不仅可以实现短返回和长返回, 而且可以实现带有特权级变换的长返回)

  • 1)检查保存的cs 中的RPL 以判断返回时是否要变换特权级;
  • 2)加载被调用者堆栈上的cs 和eip;
  • 3)如果ret 指令含有参数,则增加esp 跳过参数,然后esp 将指向被保存过的调用者ss 和 esp ;ret的参数个数对应 调用门中的 Param Count的值;
  • 4)加载ss 和 esp , 切换到调用者堆栈,被调用者的ss 和 esp 被丢弃;
  • 5)如果ret 指令含有参数, 增加esp 的值以跳过参数;
  • 6)检查ds、es、fs、gs的值,如果其中哪一个寄存器指向的段的DPL 小于CPL(此规则不适用于一致代码段),那么一个空描述符会被加载到该寄存器;

【3】总结:(使用调用门的过程实际上分为两部分)

  • (1)从低特权级到高特权级,通过调用门和call 指令来实现;
  • (2)从高特权级到低特权级, 通过ret 指令来实现;(即,ret 指令可以实现从高特权级到低特权级的转移)

(Attention):

  • A1)从调用者堆栈中将参数复制到被调用者堆栈(新堆栈)中, 复制参数的数目由 调用门中 Param Count 一项来决定,(调用门中 Param Count的作用);
  • A2) ret(retf)是call 的反过程, 只是带参数的ret 指令会同时释放事先被压栈的参数;

最新文章

  1. 转-基于NodeJS的14款Web框架
  2. ECMAScript5之Array
  3. ubuntu安装mysql--PC端
  4. reason: '*** Collection <__NSCFArray: 0x7ffa43528f70> was mutated while being enumerated.'
  5. 使用PushSharp进行IOS发布应用的消息推送
  6. iOS之 PJSIP静态库编译(二)
  7. 工作上的C/C++相关
  8. systemtap [主设备号,次设备好,inode]监控文件
  9. Python修改文件名
  10. Identity Card(水题)
  11. Android 实现环形进度按钮circular-progress-button
  12. 8.Eclipse中创建Maven Web项目
  13. Java 原始数据类型的计算:运算符重载(Operator Overload)和类型转换(Type Conversion)
  14. 利用Java随机,生成随机学生数据
  15. 一、OpenStack入门 之 初步认识
  16. 消息中间件系列三:使用RabbitMq原生Java客户端进行消息通信(消费者(接收方)自动确认模式、消费者(接收方)自行确认模式、生产者(发送方)确认模式)
  17. IntelliJ Idea 授权服务器使用
  18. eclipse中使用svn提交,更新代码。
  19. CodeForces 430A Points and Segments (easy)(构造)题解
  20. Winform选择目录路径与选择文件路径

热门文章

  1. 获取当前应用程序实例(instance:HINSTANCE)(转)
  2. locust参数关联及批量注册
  3. python commands 模块
  4. bytearray和file的后端上传方式
  5. 调用Thread.interrupt()方法到底会发生什么?
  6. 已知一个序列A1.A2….An,给你一个整数K,找到满足所有Ai+Aj>=k的数对(i,j)的个数
  7. Codeforces Round #324 (Div. 2) Olesya and Rodion 构造
  8. Hadoop1和Hadoop2的区别是什么?
  9. UVA 11389 The Bus Driver Problem 贪心水题
  10. Swagger2接口注释参数使用数组