一、段描述符
1、段界限边界值=(描述符中段界限 + 1)*(段界限粒度大小)- 1
由于段界限从0开始,所以左边加个1,由于地址从0开始,所以最右边减个1。段界限是用来限制偏移地址的,若超出这个范围,CPU会抛出异常,
2、G位为0,表示段界限粒度为1字节,为1,表示段粒度大小为4KB。
3、type,共4位,当指定了S位后,type才有确切的意义,3 2 1 0位依次从左向右如下图X R C A
A位是Accessed位,由CPU设置,每当CPU访问过,便设置为1。
C表示一致性代码段
R表示可读,为1代表可读,为0代表不可读
X表示可执行,为1代表可执行,为0代表不可执行
E表示标识段的扩展方向,为0表示向上扩展,为1表示向下扩展
W表示是否可写,为1表示可写,为0表示不可写。
4、S位,为0代表系统段,为1代表数据段。代码、数据、栈都是硬件的输入,都是数据段,各种成为“门”的结构是系统段。
5、DPL,Descriptor Priviledge Level描述符特权级,从高到低分别是0、1、2、3,操作系统处于0,用户程序处于3。
6、P字段,Present,是否存在在内存中,如果位于内存中,为1,否则为0。
7、AVL: available,是否可用,对用户来说。
8、L字段:为1表示64位代码段,为0表示32位。
9、D/B:用来指示有效地址及操作数的大小。
二、全局描述符表GDT(Global Descriptor Table)
段描述符存放在GDT中,GDT本质是个段描述符类型的数组。GDT的起始地址由GDTR(GDT Register)指向,它48位。对gdtr的初始化只能使用lgdt指令。格式是lgdt48,前16位是GDT的大小减1,后32位是gdt的起始地址。由于16位表示65536,一个段描述符8字节=64B,所以gdt可容纳65536 / 16 = 2^13 = 8192个段描述符。
GDT第0个描述符不可用:防止因为选择子忘记初始化而选择到第0个段描述符。如果选择子未初始化,它的值是0。
三、选择子
段寄存器中保存的是选择子(selector),它索引到全局描述符表的对应段描述符。
由于段寄存器16位,所以选择子也是16位。
第0~1位存储RPL(请求特权级)。
第2位是TI(Table Indicator)位,用来指示选择子是在GDT中还是在LDT中,0表示在GDT中,1表示在LDT中。
第3~15位存储的是段描述符的索引。
四、LDT
Local Descriptor Table
加载指令:lldt 16,首地址存在gdtr中。
LDT第0个描述符可用:因为当在LDT中,意味着选择子的第2位为1,所以选择子一定经过了初始化,所以排除了忘记初始化的可能。
五、打开A20地址线
将端口0x92的第1位置为1。
in al, 0x92
or al, 00000010B
out 0x92, al
六、保护模式的开关,cr0寄存器的PE位。
PE(Potection Enable)
可以看出PE位位于第0位。所以,把cr0存的值与0x1或一下即可。
mov eax, cr0
or eax, 0x00000001
mov cr0, eax