1.3.2 设置中断描述符表和全局描述符表

1.3.2 设置中断描述符表和全局描述符表

setup程序继续为保护模式做准备,此时要通过setup程序自身提供的数据信息对中断描述符表寄存器IDTR和全局描述符表寄存器GDTR进行初始化设置。

小贴士

GDT(Global Descriptor Table,全局描述符表):它是系统中唯一存放段寄存器内容(段描述符)的数组,配合程序进行保护模式下的段寻址。它在操作系统的进程切换中具有重要意义,可理解为所有进程的总目录表,其中存放着每一个任务(task)局部描述符表(LDT,Local Descriptor Table)地址和任务状态段(TSS,Task Structure Segment)地址,用于完成进程中各段的寻址、现场保护与现场恢复。

GDTR(Global Descriptor Table Register,GDT基地址寄存器):GDT可以存放在内存的任何位置,当程序通过段寄存器引用一个段描述符时,需要取得GDT的入口, GDTR所标识的即为此入口。在操作系统对GDT的初始化完成后,可以用LGDT(Load GDT)指令将GDT基地址加载至GDTR。

IDT(Interrupt Descriptor Table,中断描述符表):保存保护模式下所有中断服务程序的入口地址,类似于实模式下的中断向量表。

IDTR(Interrupt Descriptor Table Register,IDT基地址寄存器):IDT基地址寄存器,保存IDT的起始地址。

内核实现代码如下:

 
 
  1. //代码路径:boot/setup.s  
  2.  
  3. lidt    idt_48  
  4. lgdt    gdt_48  
  5.  
  6. gdt:  
  7.     .word   0,0,0,0     ! dummy  
  8.  
  9.     .word   0x07FF      ! 8Mb-limit=2047 (2048*4096=8Mb)  
  10.     .word   0x0000      ! base address=0 
  11.     .word   0x9A00      ! code read/exec  
  12.     .word   0x00C0      ! granularity=4096, 386  
  13.  
  14.     .word   0x07FF      ! 8Mb-limit=2047 (2048*4096=8Mb)  
  15.     .word   0x0000      ! base address=0 
  16.     .word   0x9200      ! data read/write  
  17.     .word   0x00C0      ! granularity=4096, 386  
  18.  
  19. idt_48:  
  20.     .word   0       ! idt limit=0 
  21.     .word   0,0     ! idt base=0L 
  22.  
  23. gdt_48:  
  24.     .word   0x800       ! gdt limit=2048, 256 GDT entries  
  25.     .word   512+gdt,0x9 ! gdt base = 0X9xxxx 

这些代码设置所需要的数据分别在idt_48和gdt_48所对应的标号处,它们与寄存器的对应方式如图1-18所示。

 
图1-18 设置GDTR和IDTR

点评

32位的中断机制和16位的中断机制在原理上有比较大的差别,最明显的是16位的中断机制用的是中断向量表,中断向量表的起始位置在0x00000处,这个位置是固定的。32位的中断机制用的是中断描述符表IDT,位置是不固定的,可以由操作系统的设计者根据设计要求灵活安排,由IDTR寄存器来锁定其位置。

GDT表是保护模式下管理段描述符的数据结构,对操作系统自身的运行和管理,以及进程调度有重大意义,后面的章节会有详细讲解。

因为,此时此刻内核尚未真正运行起来,还没有进程,所以现在创建的GDT表的第一项为空,第二项为内核代码段描述符,第三项为内核数据段描述符,其余项皆为空。

IDT表虽然已经设置,实为一张空表,原因是目前已关中断,无须调用中断服务程序。此处反映的是数据“够用即得”的思想。

创建这两个表的过程可理解为是分两步进行的:

(1)在设计内核代码时,已经将两个表写好,并且把需要的数据也写好。

(2)将专用寄存器(IDTR和GDTR)指向表。

此处的数据区域是在内核源代码中设定和编译并直接加载至内存形成的一块数据区域。专用寄存器的指向由程序中的lidt指令和lgdt指令完成,具体操作见图1-18。

值得一提的是,在内存中做出数据的方法有两种:

(1)划分一块内存区域并初始化数据,“看住”这块内存区域,使之能被找到;

(2)由代码做出数据,如用push代码压栈,“做出”数据,此处采用的是第一种方法。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值