TSS(Task-State Segment),它是一个数据结构,里面包含多个字段,32位TSS如下图所示 :
I/O位图基址 |
| T | 100 |
| LDT选择子 | 96 | |
| gs | 92 | |
| fs | 88 | |
| ds | 84 | |
| ss | 80 | |
| cs | 76 | |
| es | 72 | |
edi | 68 | ||
esi | 64 | ||
ebp | 60 | ||
esp | 56 | ||
ebx | 52 | ||
edx | 48 | ||
ecx | 44 | ||
eax | 40 | ||
efags | 36 | ||
eip | 32 | ||
gr3(pdbr) | 28 | ||
| ss2 | 24 | |
esp2 | 20 | ||
| ss1 | 16 | |
esp1 | 12 | ||
| ss0 | 8 | |
esp0 | 4 | ||
| 上一任务链接 | 0 |
|
保留位,被设为0
TSS的使用是为了解决调用门中特权级变换时堆栈发生的变化,每一个任务是最多可能在四个特权级间转移,所以每个任务实际上需要4个堆栈,从上图中可以看出,从偏移4到偏移27的3 个SS和3个ESP,当发生堆栈切换时,被调用者(内层,高特权级)的堆栈的SS和ESP就是从这里取得的。因为是从低特权级向高特权级转换,故TSS中没有最外层(最低特权级)的堆栈信息。
从上图可以看出,在TSS偏移102字节处有一个单字被称为“I/O位图基址”(它的值定义为当前地址-TSS基址+2),指向的便是I/O许可位图,之所以称之为位图,是因为它的每一位表示一个字节的端口地址是否可用。如果某一位为0,则表示此位对应的端口号可用,为1则不可用。每一个任务都可以有单独的TSS,故每一个任务可以有它单独的I/O许可位图。I/O许可位图必须以0FFh结尾。如果I/O位图基址大于或等于TSS段界限,就表示没有I/O许可位图,如果CPL>=IOPL(IO特权级,位于寄存器eflags的第13位),则所有I/O指令都会引起异常。I/O许可位图的使用使得即便在同一特权级下不同的任务也可以有不同的I/O访问权限。
关于I/O许可位图用法,可见下例:
[SECTION.TSS]
LABEL_TSS:
......
DD SelectorLDT ;LDT选择子
DW 0 ;调试陷阱位标志
DW $ - LABEL_TSS + 2 ;指向I/O许可位图
times 12 DB 0FFh ;端口00h - 5fh
DB 11111101b ;端口60h - 67h,只允许端口61h的操作
DB 0ffh ;I/O许可位图结束标志
TSS_Len EQU $ - LABEL_TSS
从程序段中可以看出在I/O许可位图开始处有12个字节的内容为1,即有12*8=96位被置为1,所以从端口00h到5fh 共96个端口地址对此任务不可用。同理,接下来的1字节只有第1位(从0开始数)是0,表示这一位对应的端口(61h)可用。最后以0FFH作为结束标志。
以下文章引自http://blog.chinaunix.net/u1/39231/showart_341161.html
任务门描述符
一个任务门描述符(简称任务门)正像一个门为一个任务的执行提供控制和保护,一个任务门描述符可以位于GDT、LDT或IDT中。
在一个任务门描述符中,TSS段选择子域要在装入TR后指向GDT中的一个TSS描述符,该段选择子中的RPL并没有被使用。在任务切换期间,任务门描述符的DPL控制着对TSS描述符的访问,当一个程序或过程通过一个任务门来调用或跳转到一个任务时,指向任务门选择子的CPL和RPL域值必须小于或等于任务门描述符的DPL域值。下图为
任务与程序的转换:
下图表示LDT、GDT和IDT中一个任务门是如何指向同一个任务:
任务连接
TSS的先前任务连接域和标志位EFLAGS·NT用于返回到先前任务执行,标志位EFLAGS·NT说明当前执行的任务是否嵌套于嵌套的任务中,如果处于嵌套状态,在当前任务TSS的先前任务连接域(反向链)中,保存有嵌套链中较高级别任务的TSS选择子,如下图:
当执行一条CALL指令、一次中断或一次异常产生一次任务切换时,处理器将当前TSS 的段选择子复制到新任务TSS的先前连接域中,然后设置标志位EFLAGS·NT,标志位EFLAGS·NT说明TSS的先前连接域通过一个被存储的TSS段选择子已经被保存。如果软件中通过执行指令IRET来恢复新任务(实际上就是过去被挂起的任务),处理器通过先前连接域中的值和标志位NT来返回到先前的任务,即如果标志位EFLAGS·NT设置,处理器执行一次任务切换,切换到先前连接域中所指定的任务。
与CALL指令不同的是:当执行一条JMP指令产生一次任务切换时,新任务是不允许嵌套的,即如果标志位NT清除,先前连接域没有用,一般采用指令JMP派遣一个新任务。
任务转换
处理器可以通过下列四种形式之一切换到其他任务执行:(可以参看任务与程序的转换图)
⑴在当前程序、任务或过程中执行一条JMP或CALL指令转到GDT中TSS描述符。(直接任务转换) (图例1)
⑵在当前程序、任务或过程中执行一条JMP或CALL指令转到GDT或当前LDT中一个任务门描述符。(间接任务转换)(图例2)
⑶通过一个中断或异常矢量指向IDT中的一个任务门描述符。(间接任务转换)(图例2)
⑷当标志位EFLAGS·NT设置时,当前任务执行指令IRET(或IRETD,用于32位程序转换。(直接任务转换)
对于指令JMP、CALL、IRET、中断和异常,它们都是程序执行时的一种重定向机制。 一个TSS描述符、一个任务门(调用或跳转到一个任务)或标志位NT(执行指令IRET时) 的状态共同决定了是否发生任务切换。