在64位模式下,每当将非空段选择器加载到任何数据段寄存器(DS、ES、SS、FS、GS)中时,处理器都会自动将相应的段描述符加载到描述符cache中,这和保护/兼容模式一样。但是,通过这个非空选择子读写内存时,数据段的基地址强制为0,段界限忽略,不进行界限检查而是进行canonical-address form检查。
加载非空选择子到数据段寄存器,仅忽略BASE_ADDRESS和SEGMENT_LIMIT这2个域,其他的各个域的作用与保护模式是相同的。(加载段寄存器的指令也只有LDS和LES被废除)
NULL_SELECTOR 位于GDT的0号槽,一共有4个分别是0 , 1 ,2 ,3,也就是RPL = 0,1,2,3
保护模式空选择子用于初始化不用的段寄存器,加载了空选择子的数据段描述符cache的属性域被标记为0x11(可以看syscall 指令的流程),段基地址和界限都是0.
64位模式对空选择子从新定义(这是个迷,手册上没有介绍怎么处理的),intel手册只是说:
在64位模式下,处理器不会对空段选择器执行运行时检查。当试图访问引用的段寄存器具有空段选择器的内存时,处理器不会导致GP故障。
对于数据段段寄存器来说只有使用空选择子才能避开装载段寄存器要进行的一系列特权级检查。64位模式下加载空选择子后段描述符cache基地址和界限为0,属性=1。不同的是SS,加载了空选择子的SS描述符cache界限=0xFFF,基地址=0,属性=0x18127
描述符cache的获取只能通过SMM方式间接得到。
64位:
- 特权级0 可以将所有数据段寄存器用0初始化并且可以正常读写内存。
- 特权级3 SS不能使用空选择子,并且描述符中属性的作用与保护模式相同,特权级检测规则也与保护模式相同。
由于段描述符没有被扩充为64位,FS和GS被改造,加入了MSR寄存器来支持64位的基地址。
CS 代码段不能装载空选择子,在长模式下 CS的多了一个L位,用于在兼容模式和64位模式之间切换。CS描述符的基地址和界限域和数据段一样被忽略了,但是所有的属性仍然有效。
所有段寄存器的基地址和界限被忽略,所以G、D/B和ED位忽略。(代码段L=1,D=1是无效组合)
64位模式空选择子用于DS ES FS GS SS数据段寄存器,可以减少特权级的检查,这才是符和手册上说的:
In 64-bit mode, the contents of the ES, DS, and SS segment registers are ignored. All fields (base, limit, and attribute) in the corresponding segment descriptor registers (hidden part) are also ignored
SS在特权级3下不能使用空选择子是因为CPU在切换特权级的时候仍然要检查CS及SS的DPL 、RPL。这与保护模式是一样的。
64位的段机制被削弱,当使用空选择子初始化数据段寄存器时,基于段的保护机制也被削弱,甚至是没有,这就要靠分页来进行保护。切换到长模式的必要条件就是分页。