TSS TR

来源:互联网 发布:网络校时原理 编辑:程序博客网 时间:2024/06/11 11:05

32位CPU寄存器简介以及TSS和TR


转载http://www.cnblogs.com/wanghj-dz/p/3979729.html
转载http://www.cnblogs.com/mumuliang/archive/2010/07/26/1873493.html

CPU的指令一般都是通过寄存器来实现的。 


其中有一个寄存器叫做EIP(Instruction Pointer,指令寄存器),程序的执行就是靠EIP的不断增加来完成的(跳转的话,EIP就变成了跳转到的地址)。在Windows系统下,进程并不拥有EIP,那么只有进程,一个程序就无法运行。而拥有这些寄存器的是线程,所以说进程是静态的。一个CPU下只有一个EIP,也就是说同一时刻只能有一个线程可以运行,那么所说的多线程又是什么呢?事实上同一时刻也只有一个线程在运行,每个线程运行一段时间后,它会把它拥有的EIP等寄存器让出来,其它线程占有这些寄存器后,继续运行。 


为了实现不同的线程之间的转换,CPU要求操作系统维护一份固定格式的数据(该数据存在于内存中),这份数据叫做Task-State Segment(TSS),在这份数据结构里,维护着线程的EAX,EIP,DS(Data Segment)等寄存器的内容。 


EAX—EDX可称为数据寄存器,你除了直接访问外,还可分别对其高十六位和低十六位进行访问。它们的低十六位就是把它们前边儿的E去掉,即EAX的低十六位就是AX。而且它们的低十六位又可以分别进行八位访问,也就是说,AX还可以再进行分解,即AX还可分为AH(高八位)AL(低八位)。 


在32位程序中,32位以内的函数返回值都通过eax寄存器来传递——这是__stdcall和__ccall的调用约定形成的结果。Win32API函数(wsprintf使用__cdecl调用规则,其余所有API函数都是用__stdcall调用规则)默认是是用eax返回值。高级语言特性+编译器,通常将函数的返回值放在EAX中(单一返回值直接放EAX,如果多个返回值,则EAX中存放指针)。
 00000000 00000000 00000000 00000000
│               EAX                    │
                  │       AX           │
                  │   AH   │    AL     │

 

 

而CPU还有一个寄存器叫做Task Register(TR),该寄存器指向当前正在执行的线程的TSS。而线程切换事实上就是TR指向不同的TSS,这样CPU就会自动保存当前的EAX,EBX的信息到相应的TSS中,并将新的线程的信息加载到寄存器。


32位CPU的寄存器包括

4个数据寄存器 : 

    EAX  (Accumulator) 

    EBX  (Base Register) 

    ECX  (Count Register)  

    EDX  (Data Register)

2个变址和指针寄存器(Index Register) :

    ESI   (Source Index Register)

    EDI   (Destination Index Register)

1个指令指针寄存器 :

    EIP    (Instruction Pointer)

2个指针寄存器(Pointer Register) :

    ESP   (Stack Pointer Register) 

    EBP   (Base Pointer Register)

6个段寄存器(Segment Register) 

    CS    (Code Segment Register)

    DS    (Data Segment Register)

    SS    (Stack Segment Register)

    ES    (Extra Segment Register)

    FS    (Extra Segment Register)

    GS    (Extra Segment Register)

1个标志寄存器 :

    EFlags 


 

tr寄存器

任务寄存器tr保存 16 位的段选择子、32 位基地址、16 位段界限和当前任务的 TSS属性。它引用 GDT 中的 TSS 描述符。基地址指明 TSS 的第一个字节(字节 0)的线性地址,段界限确定 TSS 的字节个数。TR寄存器包含了当前正在CPU运行的进程的TSSD(任务段描述符)选择符。也包含了两个隐藏的非编程域:TSSD的base 和limit域。通过这种方式处理器就能直接对TSS寻址,而不用从GDT中索引TSS的地址

TR寄存器---->GDT中的TSS描述符---->硬件上下文的具体数据。任务切换中

cpu会把当前寄存器的数据保存到当前(旧的)tr寄存器所指向的tss数据结构里,然后把新的tss数据复制到当前寄存器里。这些操作是通过cpu的硬件实现的

TSS 任务状态段
TSS(任务状态段)
1 什么是TSS  
 TSS 全称task state segment,是指在操作系统进程管理的过程中,任务(进程)切换时的任务现场信息。 




 
2 TSS工作细节  
 TSS在任务切换过程中起着重要作用,通过它实现任务的挂起和恢复。所谓任务切换是指,挂起当前正在执行的任务,恢复或启动另一任务的执行。在任务切换过程中,首先,处理器中各寄存器的当前值被自动保存到TR(任务寄存器)所指定的TSS中;然后,下一任务的TSS的选择子被装入TR;最后,从TR所指定的TSS中取出各寄存器的值送到处理器的各寄存器中。由此可见,通过在TSS中保存任务现场各寄存器状态的完整映象,实现任务的切换。   
3 TSS的格式   任务状态段TSS的基本格式如下图所示。       
TSS的基本格式由104字节组成。这104字节的基本格式是不可改变的,但在此之外系统软件还可定义若干附加信息。基本的104字节可分为链接字段区域、内层堆栈指针区域、地址映射寄存器区域、寄存器保存区域和其它字段等五个区域。   
(1). 寄存器保存区域   寄存器保存区域位于TSS内偏移20H至5FH处,用于保存通用寄存器、段寄存器、指令指针和标志寄存器。当TSS对应的任务正在执行时,保存区域是未定义的;在当前任务被切换出时,这些寄存器的当前值就保存在该区域。当下次切换回原任务时,再从保存区域恢复出这些寄存器的值,从而,使处理器恢复成该任务换出前的状态,最终使任务能够恢复执行。   从上图可见,各通用寄存器对应一个32位的双字,指令指针和标志寄存器各对应一个32位的双字;各段寄存器也对应一个32位的双字,段寄存器中的选择子只有16位,安排再双字的低16位,高16位未用,一般应填为0。   
(2). 内层堆栈指针区域   为了有效地实现保护,同一个任务在不同的特权级下使用不同的堆栈。例如,当从外层特权级3变换到内层特权级0时,任务使用的堆栈也同时从3级变换到0级堆栈;当从内层特权级0变换到外层特权级3时,任务使用的堆栈也同时从0级堆栈变换到3级堆栈。所以,一个任务可能具有四个堆栈,对应四个特权级。四个堆栈需要四个堆栈指针。   TSS的内层堆栈指针区域中有三个堆栈指针,它们都是48位的全指针(16位的选择子和32位的偏移),分别指向0级、1级和2级堆栈的栈顶,依次存放在TSS中偏移为4、12及20开始的位置。当发生向内层转移时,把适当的堆栈指针装入SS及ESP寄存器以变换到内层堆栈,外层堆栈的指针保存在内层堆栈中。没有指向3级堆栈的指针,因为3级是最外层,所以任何一个向内层的转移都不可能转移到3级。   但是,当特权级由内层向外层变换时,并不把内层堆栈的指针保存到TSS的内层堆栈指针区域。实际上,处理器从不向该区域进行写入,除非程序设计者认为改变该区域的值。这表明向内层转移时,总是把内层堆栈认为是一个空栈。因此,不允许发生同级内层转移的递归,一旦发生向某级内层的转移,那么返回到外层的正常途径是相匹配的向外层返回。   
(3). 地址映射寄存器区域   从虚拟地址空间到线性地址空间的映射由GDT和LDT确定,与特定任务相关的部分由LDT确定,而LDT又由LDTR确定。如果采用分页机制,那么由线性地址空间到物理地址空间的映射由包含页目录表起始物理地址的控制寄存器CR3确定。所以,与特定任务相关的虚拟地址空间到物理地址空间的映射由LDTR和CR3确定。显然,随着任务的切换,地址映射关系也要切换。 [Page]   TSS的地址映射寄存器区域由位于偏移1CH处的双字字段(CR3)和位于偏移60H处的字字段(LDTR)组成。在任务切换时,处理器自动从要执行任务的TSS中取出这两个字段,分别装入到寄存器CR3和LDTR。这样就改变了虚拟地址空间到物理地址空间的映射。   但是,在任务切换时,处理器并不把换出任务但是的寄存器CR3和LDTR的内容保存到TSS中的地址映射寄存器区域。事实上,处理器也从来不向该区域自动写入。因此,如果程序改变了LDTR或CR3,那么必须把新值人为地保存到TSS中的地址映射寄存器区域相应字段中。可以通过别名技术实现此功能。   
(4). 链接字段   链接字段安排在TSS内偏移0开始的双字中,其高16位未用。在起链接作用时,地16位保存前一任务的TSS描述符的选择子。   如果当前的任务由段间调用指令CALL或中断/异常而激活,那么链接字段保存被挂起任务的 TSS的选择子,并且标志寄存器EFLAGS中的NT位被置1,使链接字段有效。在返回时,由于NT标志位为1,返回指令RET或中断返回指令IRET将使得控制沿链接字段所指恢复到链上的前一个任务。   
(5). 其它字段   为了实现输入/输出保护,要使用I/O许可位图。任务使用的I/O许可位图也存放在TSS中,作为TSS的扩展部分。在TSS内偏移66H处的字用于存放I/O许可位图在TSS内的偏移(从TSS开头开始计算)。关于I/O许可位图的作用,以后的文章中将会详细介绍。   在TSS内偏移64H处的字是为任务提供的特别属性。在80386中,只定义了一种属性,即调试陷阱。该属性是字的最低位,用T表示。该字的其它位置被保留,必须被置为0。在发生任务切换时,如果进入任务的T位为1,那么在任务切换完成之后,新任务的第一条指令执行之前产生调试陷阱。
-----------------------------------------------------------------------------------------------------------


我看了你说的两段了,是P393的吧
第一段是这样理解:
  当从外层转移到内层时系统会把返回地址和外层堆栈的指针保留到内层堆栈中,比如:从R3调用R0的服务,CPU会把R3的堆栈、返回地址都压入R0的堆栈中,以备返回时使用。


第二段:
  所谓“一旦发生向某级内层转移,那么返回到外层的正常途径是相匹配的向外层返回”。意思是说,从外层到内层,可以通过CALL/JMP来直接转移,但从内层到外层,不能直接通过CALL/JMP,只能通过远程RET,这样做的原因是为了确保内层的堆栈不被外层代码得知,而不是“这表明向内层转移时,总是把内层堆栈认为是一个空栈”。
至于递归调用那个说法,我也不是很明白


 


http://bbs.csdn.net/topics/90016769

0 0
原创粉丝点击