80x86保护模式(描述符,选择符,任务切换)


不知道什么时候下载的在哪里下载的文档,整理电脑时候发现,仅作分享,侵删

基本运行流程

在这里插入图片描述
上图描述的是一个保护模式下基本的运行要点,其中包括了地址转换,任务切换的基本流程,熟悉这幅图 有利于理解运行的过程.(来自Intel开发手册3)

大致要点解释

下图是一副由选择子或者IDT表到具体的代码空间的转换过程.
在这里插入图片描述
在80x86中描述符表(descriptor table)有三种类型,IDT,GDT,LDT.而在描述符表中的数据项被称为描述符(descriptor),在一些书籍中有时候被统一称为段描述符,而这里个人认为这个认识不够全面,因为段描述符只是说了系统段和存储段的意思而没有表达门描述符的概念,所以这里个人认为三个表(IDT,GDT,LDT)中的数据项应该统一被称为描述符.
在这里插入图片描述
而值得注意的是这里的描述符种类有很多,比如说代码段描述符,TSS描述符,中断门描述符,但是不是三个表(IDT,GDT,LDT)都可以表达这么多类型的数据项.

表名数据项
GDT存储段描述符(数据段描述符,代码段描述符),系统段描述符(LDT描述符,TSS描述符),调用门描述符或任务门描述符
LDT代码段描述符,数据段描述符,堆栈段描述符,任务门描述符或调用门描述符
IDT中断门描述符,陷阱门描述符或任务门描述符

注意,其中的调用门和任务门描述符通常在操作系统中没有使用,猜测应该是这样

1.80386段管理机制

1.1 段

80386有两种类型的段.存储段是存放可由程序直接进行访问的代码和数据的段.系统段是为了实现存储管理机制所使用的一种特别的段.在80386中,有两种系统段:任务状态段TSS和局部描述符表LDT段.

存储段没有特定的格式,存放的是简单的代码或者数据.系统段有特殊的格式,LDT段存放的是局部描述符表,整个段就是一张表,每个表项是8字节的段描述符号.TSS段存放的是任务状态,它有特定的数据结构,而操作系统可以在TSS数据结构最后加上自己的操作系统特性,下面会有介绍.
在这里插入图片描述

1.2 描述符

80386的描述符类型一共两种,除了段描述符还有一种是门描述符,门描述符一共四种类型:任务门,中断门,陷阱门和调用门.门描述符和段描述符差别很大,很多字段意义完全不同.80386描述符如下:
在这里插入图片描述
门描述符后面介绍,本节介绍段描述符.在保护方式下,每一个段都有一个相应的8字节描述符来描述.段描述符中保存了段的所有属性,如段基地址,段限长,段特权级等.程序通过段描述符可以得到段的所有属性.描述符通用格式如下:
在这里插入图片描述

1.2.1 存储段描述符

在这里插入图片描述
TYPE说明存储段描述符所描述的存储段的具体属性:

其中的位0指示描述符是否被访问过(Accessed),用符号A标记.A=0表示尚未被访问,A=1 表示段已被访问.当把描述符的相应选择子装入到段寄存器时,80386把该位置为1,表明描述符已被访问.操作系统可测试访问位,已确定描述符是否被访问过.

其中的位3指示所描述的段是代码段还是数据段,用符号E标记.E=0表示段为数据段,相应的描述符也就是数据段(包括堆栈段)描述符.数据段是不可执行的,但总是可读的. E=1表示段是可执行段,即代码段,相应的描述符就是代码段描述符.代码段总是不可写的,若需要对代码段进行写入操作,则必须使用别名技术,即用一个可写的数据段描述符来描述该代码段,然后对此数据段进行写入.

在数据段描述符中(E=0的情况),TYPE中的位1指示所描述的数据段是否可写,用W标记. W=0表示对应的数据段不可写.反之,W=1表示数据段是可写的.注意,数据段总是可读的.TYPE中的位2是ED位,指示所描述的数据段的扩展方向.ED=0表示数据段向高端扩展,也即段内偏移必须小于等于段界限.ED=1表示数据段向低扩展,段内偏移必须大于段界限.

在代码段描述符中(E=1的情况),TYPE中的位1指示所描述的代码段是否可读,用符号R标记.R=0表示对应的代码段不可读,只能执行.R=1表示对应的代码段可读可执行.注意代码段总是不可写的,若需要对代码段进行写入操作,则必须使用别名技术.在代码段中,TYPE中的位2指示所描述的代码段是否是一致代码段,用C标记.C=0表示对应的代码段不是一致代码段(普通代码段),C=1表示对应的代码段是一致代码段.
存储段描述符中的TYPE字段所说明的属性可归纳为下表:
在这里插入图片描述

1.2.2 系统段描述符

在这里插入图片描述
存储段描述符和系统段描述符差别很小,图中红色的地方是两者的差别之处.系统段描述符中的段基地址和段界限字段与存储段描述符中的意义完全相同;属性中的G位,AVL位,P位和DPL字段的作用也完全相同.存储段描述符属性中的D位在系统段描述符中不使用,现用符号X表示.系统段描述符的类型字段TYPE仍是4位,其编码及表示的类型列于下表,其含义与存储段描述符的类型却完全不同.

在这里插入图片描述
从上表可见,只有类型编码为2,1,3,9和B的描述符才是真正的系统段描述符,它们用于描述系统段LDT和任务状态段TSS,其它类型的描述符是门描述符.

1.3 描述符表

描述符都放在描述符表中.在80386中有三种类型的描述符表:全局描述符表GDT(Global Descriptor Table),局部描述符表LDT(Local Descriptor Table)和中断描述符表IDT(Interrupt Descriptor Table).在整个系统中,全局描述符表GDT和中断描述符表IDT是唯一的,局部描述符表可以有若干张,每个任务可以有一张.这三种描述符表都存储在内存中.

全局描述符表GDT含有描述操作系统所使用的代码段,数据段和堆栈段的描述符,系统段描述符.在任务切换时,并不切换GDT.系统段描述符只能放在GDT中,不能放在LDT中.

每个任务的局部描述符表LDT含有该任务自己的代码段,数据段和堆栈段的描述符,也包含该任务所使用的一些门描述符,如任务门和调用门描述符等.随着任务的切换,系统当前的局部描述符表LDT也随之切换.局部描述符表LDT其实是一个系统段,与之对应的描述符是LDT段描述符,它只能存放在GDT中.

IDT(中断描述符表)后面介绍.

CPU中有3个特殊的寄存器,GDTR,LDTR和IDTR,它们分别对应GDT,当前LDT和IDT,系统通过这三个寄存器来定位相应的描述符表.

GDTR一共46位,高32位以线性地址方式存放GDT的基地址,低16位存放GDT表限长.所以GDT最大长度为64KB.由于一个描述符占8字节,所以最多有8192个表项.但是第0个表项是不用的,所以最多存放8191个描述符.

IDTR:也是48位寄存器,高32位存放中断描述符表LDT的 32 位线性首地址,低16位IDT表的限长.虽然和GDT一样,IDT最多可以有8192个表项,但是由于80386只识别256个中断向量号,所以IDT最大长度是2K.

LDTR比较特殊,包括16位可见部分和48位不可见部分.16位可见部分存放GDT中对应的LDT段的选择符,48位不可见部分作为高速缓冲,存放LDT的32位线性首地址和16位限长.一个LDT的长度最大也是64KB.第0个表项也是不用的.
GDT,LDT,GDTR以及LDTR的关系如下图:
在这里插入图片描述

1.4 段选择符

段描述符表(GDT,LDT)是通过选择符来索引的,IDT不用通过选择符,直接用中断号索引.

保护模式下段寄存器存放的都是段选择符.选择符一共16位,格式如下:
在这里插入图片描述Index一共13位,正好可以索引到GDT或者LDT的最大限长.由于描述符表都是8直接对齐的,所以吧index放在高13位,这样把低3位屏蔽后就可以得到表内 偏移地址. TI(Table Indicator)位是引用描述符表指示位,TI=0指示从全局描述符表GDT中读取描述符;TI=1指示从局部描述符表LDT中读取描述符.
选择子的最低两位是请求特权级RPL(Requested Privilege Level),用于特权检查.CS和SS寄存器中的RPL就是CPL(current privilege level当前特权级).

1.5 段寄存器

80386的段寄存器都包含有一个16位可见部分和一个不可见部分.段寄存器的可见部分由程序来操作,就好像是简单的16位寄存器,存放16位的段选择符.不可见部分由CPU维护,作为高速缓冲.每当段选择符被加载到段寄存器中时,CPU取得段描述符表中相应的描述符,然后把段的属性放入不可见部分中.比如段基地址,限长,以及其他属性.这样避免每次访问内存

1.6 段变换

在这里插入图片描述
段选择符中TI位为0时的情况,这时从GDT中读取段描述符
在这里插入图片描述
段选择符中TI位为1时的情况,这时从LDT中读取段描述符.需要先从GDT中读取LDT段描述符,然后再从LDT中读取段基地址.(所以系统要先预设GDTR和LDTR的地址)

2.多任务

上面介绍了存储段和LDT段,这里介绍另外一个系统段任务状态段TSS.
为了提供多任务,80386使用了特殊的数据结构,主要有任务状态段TSS(Task State Segment)和任务寄存器TR.

2.1 任务状态段

一个任务的所有信息都存放在任务状态段中,任务状态段与相应的段描述符相关.任务段描述符只能存放在GDT中,TR寄存器16位可见部分存放TSS段选择符.

在任务切换过程中,首先,处理器中各寄存器的当前值被自动保存到TR所指定的TSS中;然后,下一任务的TSS的选择子被装入TR;最后,从TR所指定的TSS中取出各寄存器的值送到处理器的各寄存器中.由此可见,通过在TSS中保存任务现场各寄存器状态的完整映象,实现任务的切换.
在这里插入图片描述
从图中可见,TSS的基本格式由104(0x64)字节组成.这104字节的基本格式是不可改变的,但在此之外系统软件还可定义若干附加信息.基本的104字节可分为链接字段区域,内层堆栈指针区域,地址映射寄存器区域,寄存器保存区域和其它字段等五个区域.

2.2 任务寄存器

任务寄存器TR也是由可见和不可见两个部分所组成.其中16位的可见部分用来存放TSS段选择符,它指向GDT中的一个TSS描述符.处理器使用TR中的不可见部分来高速缓存TSS的段描述符,包括TSS段的基地址和段长度.
在这里插入图片描述

2.3 任务门

任务门描述符格式如下:
在这里插入图片描述
一个任务门描述符正像一个门为一个任务的执行提供控制和保护.任务门描述符可以位于GDT,LDT或IDT中.

2.4 任务切换

2.4.1任务切换的四种形式

处理器可以通过下列四种形式之一切换到其他任务执行:

  1. 在当前程序,任务或过程中执行一条JMP或CALL指令转到GDT中TSS描述符.(直接任务转换)
  2. 在当前程序,任务或过程中执行一条JMP或CALL指令转到GDT或当前LDT中一个任务门描述符.(间接任务转换)
  3. 通过一个中断或异常矢量指向IDT中的一个任务门描述符.(间接任务转换)
  4. 当标志位EFLAGS·NT设置时,当前任务执行指令IRET(或IRETD,用于32位程序转换.(直接任务转换)
    在这里插入图片描述
    在这里插入图片描述

2.4.2任务切换步骤

当处理器切换到一个新任务时,执行下列操作步骤:

  1. 从一个任务门或先前任务的连接域(反向链)中(由指令IRET启动任务切换),从指令JMP或CALL的操作数为新任务获取TSS段选择子.

  2. 检查当前的任务是否允许转向新任务,访问权限规则适用于指令JMP和CALL,当前任务的CPL阈值和新任务段选择子的RPL阈值必须小于或等于TSS描述符的DPL域值或所参考任务门的DPL域值.

    • 即直接任务转换要求:
      DPLTSS描述符≥MAX(CPL现行特权,RPL新任务的段选择子)
    • 间接任务转换要求:
      DPL任务门≥MAX(CPL现行特权,RPL指向任务门的选择子)
      除了由指令INT n引起的软件中断之外凡是异常或中断以及指令IRET允许切换到新任务,均无需考虑 目的任务门或TSS描述符的DPL,对于由指令INT n引起的中断,则要检查其DPL.
  3. 检查新任务的TSS描述符是否存在,以及是否有一个合法的界限(大于或等于 67H).

  4. 检查新任务是否有效(调用,跳转,异常或中断)和是否忙(IRET返回).

  5. 检查当前任务的TSS.新任务的TSS和任务切换中所使用的所有段描述符是否被分页进入系统存储器.

  6. 如果任务切换是由指令JMP或IRET引起,处理器则清除当前任务TSS描述符中的忙标志位B,如果由指令CALL,一次异常或一次中断所引起,设置忙标志位B.

  7. 如果任务切换是由指令IRET引起,处理器则清除临时保存的EFLAGS寄存器副本中的标志位NT,如果由指令CALL或JMP,一次异常或一次中断所引起,临时保存的EFLAGS寄存器副本中的标志位NT不变.

  8. 在当前任务的TSS中保存当前任务的状态,处理器根据TR内容寻址当前TSS的基地址,复制下列寄存器的状态到当前任务的TSS中;所有通用目的寄存器,保存在段寄存器中的段选择符,关于EFLAGS寄存器的临时存储副本,以及指令指针EIP.
      此时必须注意的是:如果所有的检查和保存都成功执行,处理器允许任务切换,如果在从第1步到第8步的过程中发生了一个不可恢复的错误,处理器将不能完成任务间的切换,并强迫处理器返回到启动任务切换指令执行之前的状态,如果这种错误发生在任务切换允许之后(即在第9步到第14步),处理器完成任务切换,而不执行其他的访问和段的有效性检查,并在开始执行新任务之前产生一个适当的异常.如果在允许之后发生了异常,异常句柄必须在允许处理器执行任务之前,自身完成任务切换.

  9. 如果任务切换是由执行CALL指令,一次异常或一次中断所引起,处理器将当前TSS的段选择子复制到新任务TSS的反向链中.临时保存在新任务TSS中EFLAGS寄存器副本的标志位NT被处理器设置;如果由指令IRET所引起,处理器恢复临时保存在堆栈中EFLAGS寄存器副本的标志位NT;如果由指令JMP所引起,标志位NT不变.

  10. 如果任务切换是由指令CALL,指令JMP,一次异常或一次中断所引起,处理器则设置新任务TSS描述符中的忙标志位B;如果由指令IRET所引起,忙标志位B被处理器清除.

  11. 设置新任务TSS中的副本标志位CR0·TS.

  12. 为TR装载新任务TSS所需要的段选择子和描述符.

  13. 从新任务的TSS中装载新任务的状态到处理器中,在该步中可能发生任何与装载和校验段描述符相关的错误,被装载的任务状态信息包含在LDTR,PDRB(即CR3),EFLAGS. EIP,通用目的寄存器和段寄存器.

  14. 开始执行新任务.对于一个异常句柄,新任务的第一条指令不执行.
    当任务成功切换时,当前执行任务的状态总被保存.如果该任务被恢复执行,执行使从所保存EIP值指向的指令处开始,寄存器的值也被恢复到任务挂起时的保存值,这与中断现场的恢复类似.
      当发生任务切换时,新任务的特权级并不继承前任挂起任务的特权级,新任务按CS寄存器的CPL域指定的特权级开始执行, CS从TSS中装载得到.通过各自独立的地址空间, 不同的TSS和访问权限可以对任务进行很好的隔离,在任务切换时软件并不需要执行对特权级的直接检查.

2.4.3一个任务的运行环境

一个任务的运行环境由寄存器组和地址空间组成.寄存器组中保存的是任务当前的状态.地址空间由若干个段构成,每个段都有相应的段描述符,这些描述符要么放在GDT中,为所有任务共享,要么放在LDT中,是任务的私有空间.
任务的段包括:
GDT中索引的代码段,数据段,一般这是操作系统的内核数据段代码段.
LDT段,就是一张局部描述符表,由该表再索引其他私有段,比如私有数据段,私有代码等.
TSS段,保存有该任务的所有信息,任务切换用.

3.中断与异常处理

3.1 中断描述符表(IDT)

中断描述符表IDT(Interrupt Descriptor Table)将每个异常或中断向量分别与它们的处理过程秩系起来.与GDT和LDT表类似,IDT也是由8字节长描述符组成的一个数组.与GDT不同的是,表中第1项可以包含描述符.为了构成IDT表中的一个索引值,处理器把异常或中断的向量号*8.因为最多只有256个中断或异常向量,所以IDT无需包含多于256个描述符.IDT中可以含有少于256个描述符,因为只有可能发生的异常或中断才需要描述符.不过IDT中所有空描述符项应该设置其存在位(标志)为0.

3.2 IDT描述符

IDT表中可以存放三种类型的门描述符:
♦  中断门(Interrupt gate)描述符
♦  陷阱门( Trap gate)描述符
♦  任务门( Task gate)描述符

任务门已在第2节–多任务里介绍过了.这里只给出中断门和陷阱门的描述符.
中断门描述符:
在这里插入图片描述
陷阱门描述符:
在这里插入图片描述

3.3 中断和异常处理

当响应一个异常或中断时,处理器使用异常或中断的向量作为IDT表中的索引.如果索引值指向中断门或陷阱门,则处理器使用与CALL指令操作调用门类似的方法调用异常或中断处理过程.如果索引值指向任务门,则处理器使用与CALL指令操作任务门类似的方法进行任务切换,执行异常或中断的处理任务.

3.3.1 不进行任务切换的处理过程(中断门/陷阱门)

异常和中断向量若指向中断门或陷阱门,则执行不进行任务切换的中断过程.异常或中断门引用运行在当前任务上下文中的异常或中断处理过程,如下图:
在这里插入图片描述

3.3.2 进行任务切换的(任务门)

异常和中断向量若指向任务门,则进行任务切换,执行中断任务.中断处理任务切换如下图:

在这里插入图片描述

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值