GDTR: 保存全局描述符表的32位基址和16位表长度值
IDTR:中断描述符表的32位线性基址和16位表长度值
lDTR:由两部分组成,
当使用LLDT把含有LDT表段的选择符加载到LDTR时,LDT的段描述符的段基址,段限长,以及描述符属性也会被加载到LDTR中。当进行任务切换时,处理器会把新任务LDT的段选择符合和段描述符会被自动加载到LDTR
GDT和LDT关系:
系统中所有任务共享的段由GDT来映射,这样的段通常包含有操作系统的段以及所有任务各自包含LDT的特殊段。
段选择子:16位的选择符,保存在CS,DS等寄存器中,格式如下
GDT表的索引,
TI=0时,为GDT的索引
TI=1,时,为LDT的索引
段描述符:包含段基址,段限长,特权级等信息。
如何通过段选择子,GDT和LDT查找代码所在的段。
当TI=1时表示段描述符在LDT中,如下图所示:
-
还是先从GDTR寄存器中获得GDT基址。
-
从LDTR寄存器中获取LDT所在段的位置索引(LDTR高13位)。
-
以这个位置索引在GDT中得到LDT段描述符从而得到LDT段基址。
-
用段选择器高13位位置索引值从LDT段中得到段描述符。
-
段描述符符包含段的基址、限长、优先级等各种属性,这就得到了段的起始地址(基址),再以基址加上偏移地址yyyyyyyy才得到最后的线性地址。
当 TI=0时表示段描述符在GDT中,如下图所示:
-
先从GDTR寄存器中获得GDT基址。
-
然后再GDT中以段选择器高13位位置索引值得到段描述符。
-
段描述符符包含段的基址、限长、优先级等各种属性,这就得到了段的起始地址(基址),再以基址加上偏移地址yyyyyyyy才得到最后的线性地址
下面以Linu-0.11 多任务简单内核一段代码为例:
# Move to user mode (task 0)
pushfl
andl $0xffffbfff, (%esp)
popfl
movl $TSS0_SEL, %eax !TSS0_SEL=0X20
ltr %ax
movl $LDT0_SEL, %eax !LDT0_SEL=0X28
lldt %ax
movl $0, current
sti
pushl $0x17 !返回时弹入SS
pushl $init_stack !返回时弹入ESP
pushfl !返回时弹入EFLAGS
pushl $0x0f !返回时弹入CS
pushl $task0 !返回时弹入EIP
iret
当执行IRET从模拟的中断返回时,栈里面的内容被返回到EIP,CS,EFLAGS,ESP,SS中,
CS=0x0f,可以得到索引为0000 0000 0000 1,TI=1,说明是LDT中的索引,此时LDTR内容为Ox28,在GDT中以0x28
为索引,得到的描述符word 0x0040, ldt0, 0xe200, 0x0 # LDT0 descr 0x28,这样就可以得到LDT0的基址,然后再以CS中的索引,在LDT中得到task0所在段
GDT:
gdt: .quad 0x0000000000000000 /* NULL descriptor */
.quad 0x00c09a00000007ff /* 8Mb 0x08, base = 0x00000 */
.quad 0x00c09200000007ff /* 8Mb 0x10 */
.quad 0x00c0920b80000002 /* screen 0x18 - for display */
.word 0x0068, tss0, 0xe900, 0x0 # TSS0 descr 0x20
.word 0x0040, ldt0, 0xe200, 0x0 # LDT0 descr 0x28
.word 0x0068, tss1, 0xe900, 0x0 # TSS1 descr 0x30
.word 0x0040, ldt1, 0xe200, 0x0 # LDT1 descr 0x38
end_gdt:
.fill 128,4,0
LDT:
.align 3
ldt0: .quad 0x0000000000000000
.quad 0x00c0fa00000003ff # 0x0f, base = 0x00000
.quad 0x00c0f200000003ff # 0x17
tss0: .long 0 /* back link */
.long krn_stk0, 0x10 /* esp0, ss0 */
.long 0, 0, 0, 0, 0 /* esp1, ss1, esp2, ss2, cr3 */
.long 0, 0, 0, 0, 0 /* eip, eflags, eax, ecx, edx */
.long 0, 0, 0, 0, 0 /* ebx esp, ebp, esi, edi */
.long 0, 0, 0, 0, 0, 0 /* es, cs, ss, ds, fs, gs */
.long LDT0_SEL, 0x8000000 /* ldt, trace bitmap */
.fill 128,4,0
krn_stk0:
# .long 0
/************************************/
.align 3
ldt1: .quad 0x0000000000000000
.quad 0x00c0fa00000003ff # 0x0f, base = 0x00000
.quad 0x00c0f200000003ff # 0x17
tss1: .long 0 /* back link */
.long krn_stk1, 0x10 /* esp0, ss0 */
.long 0, 0, 0, 0, 0 /* esp1, ss1, esp2, ss2, cr3 */
.long task1, 0x200 /* eip, eflags */
.long 0, 0, 0, 0 /* eax, ecx, edx, ebx */
.long usr_stk1, 0, 0, 0 /* esp, ebp, esi, edi */
.long 0x17,0x0f,0x17,0x17,0x17,0x17 /* es, cs, ss, ds, fs, gs */
.long LDT1_SEL, 0x8000000 /* ldt, trace bitmap */
.fill 128,4,0
krn_stk1: