在实模式下,逻辑地址空间中存储单元的地址由段值和段内偏移两部分组成。在保护模式下,虚拟地址空间(相当于逻辑地址空间)中存储单元的地址由段选择子和段内偏移两部分组成。与实模式相比,段选择子取代了段值。
段选择子长16位。其高13位是描述符索引(Index)。所谓描述符索引是指描述符在描述符表中的序号。段选择子的第2位是引用描述符指示位,标记为TI,TI=0指示从全局描述符表GDT中读取该段的描述符;TI=1指示从局部描述符表LDT中读取该段的描述符。选择子最低两位是请求特权级RPL,用于特权检查。
选择子确定描述符,描述符确定段基地址,段基地址和段内偏移之和就是线性地址。所以,虚拟地址空间中的由段选择子和段内偏移构成的二维虚拟地址,就是这样确定了现行地址空间中的一维线性地址。
例如某个段选择子的值是0030H (0000,0000,0011,0000B),那么:描述符索引Index=6,描述符指示位TI=0(在GDT,而非LDT中),RPL=0,所以它指定全局描述符表中的第6个描述符,请求特权级是0
由于段选择子中的描述符索引字段由13位表示,所以可区分8096个描述符(2^13)。这也就是描述符表最多含有8096个描述符的原因。
由于每个描述符长8个字节,根据段选择格式,屏蔽选择低3位后所得的值就是段选择子所指定的描述符在描述符表中的偏移,这可以认为是安排选择子高13位作为描述符索引的原因。
有一种特殊的选择子称为空选择子(NULL),它的Index=0,TI=0,而RPL任意值。空选择子有特定的用途,当用空选择子进行存储访问时会引起异常。空选择子是特别定义的,它不对应于全局描述符表GDT中的第0个描述符,因此GDT中的第0个描述符总不会被CPU访问,一般把它置全0.但是当TI=1时,Index=0的选择子不是空选择子,它指定了当前任务LDT中的第0个描述符。
**********************************************************************************
举例:第三章、P25代码chapter3/a/pmtest1.asm中:
%include “pm.inc” ... [SECTION .gdt] LABEL_GDT: Descriptor 0, 0, 0 ;空描述符 LABEL_DESC_CODE32: Descriptor 0, SegCode32Len-1, DA_C+DA_32 ;非一致代码段 LABEL_DESC_VIDEO: Descriptor 0B8000h, 0ffffh, DA_DRW ;显存首地址 GdtLen equ $-LABEL_GDT ;Gdt长度 ;GdtPtr等待后面被lgdt [GdtPtr]指令加载 GdtPtr dw GdtLen-1 ;Gdt界限 dd 0 ;Gdt基址 SelectorCode32 equ LABEL_DESC_CODE32 - LABEL_GDT SelectorVideo equ LABEL_DESC_VIDEO - LABEL_GDT
说明:
1、查看宏Descriptor可以发现,这里一个段描述符实际上定义了8个byte的数据
因此,以上两句相当于:
SelectorCode32 equ 0000,0000,0000,1000
SelectorVideo equ 0000,0000,0001,0000
所以,选择子SelectorCode32指示了GDT中的第1个(从下标1开始计)段,特权级为0; 选择子SelectorVideo指示了GDT中的第2个(从下标1开始计)段,特权级为0
2、LABEL_GDT是空描述符,可以对应一个空选择子,但这里没有这么做
**********************************************************************************