上一篇文章学习了任务门的概念:任务门—任务切换。主要学习了以下内容:

  • 使用任务门进行任务切换的一般工作原理(和中断有关的任务切换)

本篇文章接着上一篇文章学习以下内容:

  • 利用jmp进行任务切换
  • 利用call进行任务切换
  • jmp、call与任务门的中断嵌套三者之间的区别与联系

注意:和中断有关的任务切换的详细原理是在后面的文章中会讲解。本文主要还是学习使用call、jmp和iret指令发起的任务切换。

1、回顾

在学习jmp、call与iret指令发起的任务切换之前,我们来回顾上一篇文章所学。

我们知道,当中断发生时,可以执行常规的中断处理过程,也可以进行任务切换。尽管性质不同,但它们都需要使用iret指令返回。只不过前者返回到同一任务的不同代码段;后者返回到被中断的那个任务。那么处理器是如何体现这两种截然不同的返回类型呢?

如下图是32位的标志寄存器EFLAGS。它有一个NT位。意思是嵌套任务标志。

每个任务的TSS中都有一个任务链接域(指向前一个任务的指针),可以填写为前一个任务的TSS描述符选择子。如果当前任务的EFLAGS的寄存器的NT位为1,则表示当前正在执行的任务是嵌套与其他任务,并且能够通过TSS的任务链接域的指针返回到前一个任务。

对于新任务的处理是,要把老任务的TSS描述符选择子填写到新任务的TSS中的任务链接域,同时,将新任务的EFLAGS寄存器的NT位置1,以允许返回到前一个任务机械厂执行。同时,还要把新任务的TSS描述符的B位置1(忙)。

无论何时,只要处理器碰到iret指令,它都会检查NT位,如果NT位是1,表明当前任务只需偶一能够执行时因为它中断了被的任务,因此应该返回到之前被中断的任务去执行。如果NT=0,表明是一般的中断过程。

2、CALL指令与JMP指令

除了使用中断引发任务切换,还可以使用远过程调用指令CALL或者远跳转指令JMP直接发起任务切换。在这两种情况下,CALL与JMP指令的操作数是任务的TSS描述符的选择子或者任务门。比如以下两条指令:

call 0x0010:0x00000000
jmp  0x0010:0x00000000

当处理器执行这两条指令的时候,首先用指令中给出的描述符选择子访问GDT,分析它的描述符类型。将会有如下几种情况发生:

  • 如果是一般的代码段描述符的话,就按普通的段间转移的规则执行
  • 如果是调用门,按调用门的规则来执行
  • 如果是TSS描述符或者任务门的话。则执行任务切换

注意,如果是进行任务切换的话,后面的32位偏移量将会被忽略。原因是执行任务切换时,所有处理器的状态都可以从TSS中获得。

任务门可以安装在中断向量表中,也可以安装在GDT中或者LDT中。

如果是用于发起任务切换,那么call指令与jmp指令有什么不同的呢?

  1. 使用call指令发起的任务切换,类似于中断发起的任务切换。这就是说由call指令发起的切换时嵌套的,当前任务(就任务)TSS描述符法人B位保持原来的1不变,EFLAGS寄存器的NT位也不发生变化;新任务的TSS描述符的B位置1,EFLAGS寄存器的NT位也置1,表示此类任务是嵌套于其他任务中。同时TSS任务链接域的内容改为旧任务的TSS描述符选择子。

如下图是嵌套任务切换的一个图示过程:

  • 当任务1开始执行时。其TSS描述符的B位是1,EFLAGS寄存器的NT位是0,不嵌套于其他任务
  • 当任务1转换到任务2后,任务1仍然为忙,EFLAGS寄存器的NT位不变(在其TSS中);任务2也变为忙,EFLAGS寄存器的NT位变为1,表示嵌套于任务1中,同时将任务1的TSS描述符选择子复制到任务2的TSS链接域
  • 最后将任务2切换到任务3,过程与任务1切换到任务2是一样的。
  • 用call指令发起的任务切换,可以通过iret指令返回到前一个任务。返回到前一个任务后,当前任务(旧任务的EFLAGS的NT位以及TSS的B位恢复为0)
  1. 和call指令不同,jmp指令发起的任务切换不会形成任务之间的嵌套关系。执行任务切换时,当前任务(旧任务)TSS的描述符的B位请0,变为非忙态,EFALGS寄存器的NT位不变。新任务的TSS的B位置1,EFLAGS寄存器的NT位保持从TSS中加载的状态不变。

3、任务的不可重入性

任务是不可重入的

任务的不可重入的意思是,执行任务切换时,将要切换到的新任务此时的状态不能为忙。已经在忙了,没法再让它忙。有以下两种典型情况:

  • 执行任务切换时,新任务不能是当前任务自己
  • 如上述嵌套任务切换的示意图此刻的状态,不能从任务3切换到任务1或者任务2

处理器是通过TSS的B位来检测重入的。因中断,iret,call,jmp指令发起的任务切换时,处理器固件会检测新任务的TSS的B位,如果该位为1,则处理器不允许这样的任务切换。

4、任务切换时的几种方法总结

处理器用以下四种方法将控制转移到其他任务

  • 当前程序、任务或者过程,执行jmp或者call指令,将控制转移到GDT内的某一个TSS描述符
  • 当前程序、任务或者过程,执行jmp或者call指令,将控制转移到GDT或者LDT内的某一个任务门
  • 一个异常或者中断发生时,中断号指向中断描述符表内的任务门
  • 在EFLAGS寄存器的NT位置1的情况下,当前任务执行了一个iret指令。

jmp、call、iret指令或者异常和中断是程序重定向的机制,它们所引用的TSS描述符或者任务门,以及EFLAGS寄存器NT标志位的状态,决定了任务切换是否,以及如何发生。

以下给出一个表格:不同任务切换方法对B位、NT位和任务链接域的影响

5、总结

本文主要学习关于任务切换的一些方法:jmp,call,以及中断切换,这三者之间的区别。很明显,call指令类似于中断引起的切换,jmp指令就不同。同时注意iret指令执行时处理器大概都需要执行哪些指令(视不同的状态而做出不同的反应)。

详细的内容还是要参考原书籍,这里只是做一个简单的总结。

学习探讨加个人:
qq:1126137994
微信:liu1126137994