1.段描述符
-
保护模式大大提高了安全性,其中很大一部分的安全就体现在了内存段的描述方面,偏移地址还是和实模式下一样,但是段寄存器保存的再也不是段基址了,为了更安全添加了约束条件,这些“约束条件”便是对内存段的描述信息,由于信息太多,一个寄存器肯定放不下,所以专门找了数据结构——全局描述符表,其中每一个表项都称为段描述符,其大小为64字节,用来描述各内存段的起始地址、大小、权限等信息,全局描述符表很大所以放在内存中,由GDTR寄存器指向它。
-
段寄存器里面保存的内容叫“选择子”,selector,选择子其实就是个数,用来索引全局描述符表中的段描述符。把全局描述符表当成数组,选择子就像是数组的下标一样
实模式下存在的问题:
- 实模式下的用户程序可以随意破坏存储代码的内存区域,所以要添加个内存段类型属性来阻止这种行为。
- 实模式下的用户程序和操作系统是同一级别的,所以要添加个特权级属性来阻止这种行为。
其次,是一些访问内存段的必要属性条件:
- 内存段是一片内存区域,访问内存就要提供段基址,所以要有段基址属性。
- 为了限制程序访问内存的范围,还要对段大小进行约束,所以要有段界限属性
段描述符是8字节大小,图中为了方便展示,才“人为的”分成了低32位和高32位。其实他们不能分成两部分,必须是连续的8字节,这样CPU才能读取到正确的段信息
下面是段描述符各字段的解释:
- 段基址:保护模式下地址总线宽度是32位,段基址需要用32位地址来表示
- 段界限:20位,段界限表示段边界的扩展最值。内存访问需要用到“段基址:段内偏移地址”,段界限其实是用来限制段内偏移地址的
实际的段界限边界值=(描述符中段界限+1)*(段界限的颗粒大小:4KB或1)-1
- TYEP字段:4位,用来指定本描述符的类型。段描述符在CPU眼里分为两大类,要么描述的是系统段,要么描述的是数据段,这是由段描述符中S位决定的,用它指示是否是系统段。
在CPU眼里,凡是硬件运行需要用到的东西都可以称之为系统,凡是软件(操作系统也属于软件)需要的东西都称为数据,我们主要关注非系统段
-A位表示accessed位,这是由CPU来设置的,每当该段被CPU访问后,CPU就将此位置1。
-C表示一致性代码
-R表示可读,R为1表示可读,R为0表示不可读
-X表示该段是否可执行。X为1表示可执行,0表示不可执行
-E用来标识段的扩展方向,E为0表示向上扩展,即地址越来越高,通常用于代码段和数据段。E为1表示向下扩展,地址越来越低,通常用于栈段。
-W指是否可写,W为1表示可写,0表示不可写
- S字段:S为1表示数据段,S为0表示系统段
- DPL字段:描述符特权级,这两位能表示4种特权级,分别是0、1、2、3、4级特权。数字越小权力越大
- P字段:段是否存在于内存中,存在P为1,不存在P位0。P字段是由CPU来检查的。
- AVL字段:可用的,是针对用户来说的,也就是操作系统可以随意用此位。
- L字段:用来设置是否64位代码段。L为1表示64位代码段,L为0表示32位代码段
- D/B字段:用来指示有效地址(段内偏移地址)及操作数的大小。
对于代码段来说,此位是D位,若D为0,表示指令中的有效地址和操作数都是16位,指令有效地址用IP寄存器。若D为0,表示指令中的有效地址及操作数为32位,指令有效地址用EIP寄存器
对于栈段来说,此位是B位,用来指定操作数大小。若B为0,使用SP寄存器,也就是栈的起始地址是16位寄存器的最大寻址范围,0xFFFF。若B为1,使用的是ESP寄存器,也就是栈的起始地址是32寄存器的最大寻址范围,0xFFFFFFFF。 - G字段:粒度,它与段界限一起来决定段的大小。若G为0,表示段界限的单位是1字节,这样的段最大是2的20次方*1字节,即1MB。若G为1,表示段界限的单位是4KB,这样段最大是2的20次方*4KB,即4GB。
2.全局描述符表GDT
- 段描述符存放在全局描述符表GDT中,全局描述符表位于内存中,需要专门的寄存器指向它,这个寄存器便是GDTR,专门用来存储GDT的内存地址及大小,GDTR是个48位寄存器。对此寄存器的访问用lgdt指令。
- lgdt指令格式是:lgdt48位内存数据
- 这48位内存数据划分为两部分,其中前16位是GDT以字节为单位的界限值,其范围是2的16次方等于65536个字节,每个描述符的大小是8字节,故GDT最多可容纳的描述符数量是65536/8=8192个,即GDT中可容纳8192个段或门。后32位是GDT起始地址
3.段选择子
- 段寄存器CS、DS、ES、FS、GS、SS,在实模式下时,段中存储的是段基址,即内存段的起始地址。而在保护模式下时,由于段基址已经存入段描述符中,所以段寄存器中再存放段基址是没有意义的,在段寄存器中存放的是一个叫做段选择子的东西——selector。
- 段选择子:第0~1位用来存储RPL。第2位是TI位,用来指示选择子是在GDT中,还是在LDT中索引描述符。第3~15位是描述符的索引值,用此值在GDT中索引描述符,由于选择子的索引部分是13位,即2的13次方等于8192,故最多可索引8192个段,这和GDT中最多定义8192个描述符吻合。
- 注意:GDT中的第0个段描述符是不可用的,若选择到了GDT中的第0个描述符,处理器将发出异常