分段管理机制
段选择子和偏移地址的二维虚拟地址转换为一维的线性地址
一 段定义和虚拟地址到线性地址的转换
三个参数定义段:段基地址 段界限 和段属性 同时也是段描述符的结构
段基地址为段的开始地址 386下为32位 可以在线性地址空间中的任何一个字节开始
段界限规定段的大小 保护模式下用20位表示
段界限的单位分为字节和4k字节两种 由段属性中的g位表示 粒度值为0是字节 为1是4k字节
字节单位 则界限为从1到1m(2的20次方)
4k字节单位 界限为从4k到4g (20的20次方*4k(2的12次方))=2的32次方=4g
当以4k的字节为单位的时候 实际的段界限=limit*4k+0fffh(=4k)=(limit SHL 12)+0fffh
此时段的界限实际上就扩展成32位
在保护模式下 段的长度大大超过实模式下的65k字节(2的16次方)
通过增加段界限 可以增加段的容量 对于普通数据段有效
对于堆栈段 (特殊的数据段) 堆栈底在高地址端 随着压栈操作的进行 堆栈向低地址扩展 为了适应普通数据段和堆栈段在两个相反方向上的扩展 数据段的段属性中扩展的方向位ED ed=0表示向高扩展 ed=1表示低地址扩展
一般只有堆栈向低地址扩展
p位表示存在位 为1表示有效
1 堆栈段被定义为独特的段 ds和ss包含不同的选择子
2 一个堆栈靠将它复制到一个更大的段来扩充自己 而不是靠将显存的页增加到它的段上
只有数据段才有ed的属性位 向高扩展0到limt的偏移为合法 limit+1到1m-1为非法
向低地址扩展limit+1到1m-1为合法 0-limit为非法
每次的虚拟地址转化要对偏移进行检查 非法则异常
二 存储段描述符
每个段描述符8个字节 在保护方式下 每个段一个描述符
描述符分为三类 存储段描述符 (代码和数据) 、系统段描述符 、门描述符(控制描述符)
1.存储段描述符的格式
dpl表示特权级
dt 描述符类型 dt=1 存储段;dt=0 系统段和门
type为具体属性 位0表示是否被访问过 用A标记;为0是未访问 为1已访问
位3表示代码段还是数据段 用e标记 e=0表示数据段 e=1表示代码段 e为是否执行段
代码段不可写 如果想写 需要用别名技术 即用一个可写的数据段描述符进行写入
e=0 type中的位 1指示描述符的数据段是否可写 w标记 w=0表示不可写 w=1表示可写 数据段总是可读的
type中的位 2 是ed位 描述扩展方向
e=1 type中的位1 指示代码段是否可读 r标记 r=0表示不可读 r=1表示可读 代码段默认总是不可写的
type中的位 2表示是否是一致代码段 c标记 c=0表示非一致代码段 c=1表示一致代码段 consistent
g表示段界限的粒度 g=0为字节 g=1为4k字节
d位 代码段中 决定使用的地址和操作数的大小 d=1表示32为地址和32位或8位操作数
d=0表示16位地址和16位或8位操作数 也称为16位代码段
向下扩展的数据段 d决定上部的边界 d=1表示4g d=0表示64k
ss堆栈 d决定push和pop使用的寄存器 d=1使用32的esp d=0使用16位的sp
avl 未定义
描述符内的第6字节中的位5必须置为0
2.存储段描述符的结构类型表示
DESC STRUC
LIMITL DW 0;段界限的低16
BASEL DW 0;基地址低16
BASEM DB 0;基地址中间8位
ATTRIB DB 0;属性
LIMITH DB 0;段界限的高4位 包括段属性的高4位
BASEH DB 0;基址的高8
DESC ENDS
例如datas desc <OFFFFH, ,10H,0F2H, , >
可读写的有效数据段 基址为100000h 以字节为单位的界限是0ffffh 描述符特权级为dpl=3
三全局和局部描述符表
一个任务会涉及到多个段 一个任务一个描述符 多个描述符组成描述符表
386中有三种类型的描述符表 :GDT LDT 和IDT
GDT和IDT在系统中只有一张 LDT局部表可以有多张
下面的描述符表有6个描述符构成:
DESCTAB LABEL BYTE
DESC1 DESC <1234H,5678H,34H,92H,,> DESC1 DESC <1234H,5678H,34H,93H,,> DESC1 DESC <5678H,1234H,56H,98H,,> DESC1 DESC <5678H,1234H,56H,99H,,> DESC1 DESC <0FFFFH,,10H,16H,,> DESC1 DESC <0FFFFH,,10H,90H,,>
每个描述符表成为一个特殊的数据段 这样的表最多可以包含有8k 共8192个描述符 也是项目数字
8192个项目的原因:由16位的段寄存器中的选择子确定 ,前3位为属性位 高13位表示项目在对应的描述符表中的相对于首项描述符的便宜 也是序号 所以2的13次方为8192个描述符项 每个描述符由8个字节描述
每个任务得LDT含有该任务自己的代码段、数据段和堆栈段的描述符,也包含该任务所使用的一些门描述符
随着任务的切换,系统当前的LDT也随之切换
GDT含有每个任务都可能或可以访问的段的描述符,通常包含描述操作系统所使用的代码段、数据段和堆栈段的描述符
,也包含特殊数据段描述符 例如描述任务LDT的特殊数据段等 任务切换并不切换gdt
LDT使各个任务私有的各个段隔离 保护
GDT可以使各个任务都需要的段能被共享
下图显示共享和保护
gdt和ldt都可以包含8192个描述符 而段的最大值可以达到4g 所以最大的虚拟空间为4g*8192*2=64tb
四 段选择子
实模式是 段值和段内偏移
保护模式是 虚拟地址空间中存储单元的地址为段选择子和段内偏移两部分组成 其中段选择子代替了段值
段选择子16位
高13位位描述符索引 index。描述符在描述符表中的序号。 段选择子的第2位是引用描述符表指示位 标记为 TI 位
table indicator 为0表示GDT 为1表示ldt 获取描述符
选择子的最低2位是请求特权机RPL requested privilege level 用来特权检查
RPL字段
当程序访问一个段时,要把当前特权级别与所访问段的特权比较,使用rpl 改变权级的测试规则, 与所访问的段的权级比较的不是cpl 而是cpu与rpl中更外层的特权级别,cpl存放在cs寄存器的rpl字段中 每当代码段选择子被装入cs中 cpu自动把cpl存放在cs的rpl字段
五 段描述符的告诉缓冲寄存器
保护模式下 段寄存器的值为段选择子
1.每个段寄存器有一个高速缓冲寄存器 段描述符高速缓冲寄存器或者描述符投影寄存器 不可见
2.选择子被装入到段寄存器 cpu会将描述符表中的描述符的信息保存的缓冲寄存器
3.此后对段的访问 就会直接使用描述符缓冲寄存器的新内容 而不再去描述符表中取
段描述符高速缓冲寄存器 对应cs ss ds es fs gs
内容包括32位基地址 32位段界限 还包括10位的段属性
注意此寄存器的信息更新时机 除了选择子被装入到段寄存器外 还有在改变描述符表中的某个当前段的描述符后 也要更新此时缓冲寄存器的内容 即使选择子未变 需要通过重新装载段寄存器来实现