GDT、LDT和IDT

三个重要的系统表GDT、LDT和IDT 首先说明的是,这三个表是在内存中由操作系统或系统程序员所建,并不是固化在哪里,所以从理论上是可以被读写的。

这三个表都是描述符表。描述符表是由若干个描述符组成,每个描述符占用8个字节的内存空间,每个描述符表内最多可以有(8K)8129个描述符。描述符是描述一个段的大小,地址及各种状态的。描述符表有三种,分别为全局描述符表GDT、局部描述符表LDT和中断描述符表IDT。

GDT表与IDT表

在整个系统中,全局描述符表GDT只有一张(一个处理器对应一个GDT),GDT可以被放在内存的任何位置。系统用GDTR寄存器存放当前GDT表的基地址。用LDTR寄存器存放LDT表的地址。

寄存器 加载指令 保存指令
GDTR寄存器 LGDT SGDT
LDTR寄存器 LLDT SLDT
IDTR寄存器 LIDT SIDT

由于每个进程都有自己的一套程序段、数据段、堆栈段,有了局部描述符表则可以将每个进程的程序段、数据段、堆栈段封装在一起,只要改变LDTR就可以实现对不同进程的段进行访问。 随着任务的切换,系统当前的局部描述符表LDT也随之切换。通过LDT可以使各个任务私有的各个段与其它任务相隔离,从而达到受保护的目的。通过GDT可以使各任务都需要使用的段能够被共享。

我们可以这样理解GDT和LDT:GDT为一级描述符表,LDT为二级描述符表。
在这里插入图片描述
推荐两篇不错的文章:
GDT,LDT,GDTR,LDTR 详解,包你理解透彻

简单解释Windows如何使用FS段寄存器
该文中实操从FS的值查询GDT表和LDT表转换为虚拟地址,能加深对段寄存器的印象。
流程如下
选择子Index确定描述符序号
查询描述符确定段基地址
段基地址与偏移之和就是线性地址

IDT表

整个系统IDT表也只有一张,GDT表也可以被放在内存的任何位置寄存器。IDTR寄存器存放IDT表的基地址。x86CPU最大可以支持256种中断ISR(中断处理程序),每个表项为8字节。Intel指定或保留了前32个中断号的作用,操作系统可以指定其余的中断号的作用。

中断的过程中可以产生新的中断。中断时有优先级的,高优先级的中断可以“中断”低优先级的中断。有的ISR不能被中断,可以使用STI (set interrupt-enable flag) and CLI(clear interrupt-enable flag)设置IF标志来启动和关闭中断。
!idt –a 命令可以看到所有中断处理函数的地址。

另外小贴士:实模式下IVT的每个表项是四字节。地址是从0x0h——0x3FFh也最多256项IVT。
Int 0x13h IVT偏移地址:0x4ch
Int 0x2Eh IDT偏移地址 :0x170h(KiSystemService)

在这里插入图片描述

typedef struct _IDTR //IDT基址
{
    
    
    USHORT limit; //范围 占8位
    ULONG base;  //基地址 占32位 PIDT_ENTRY类型指针
}IDTR,*PIDTR;

IDT表的每个成员是一个8字节的数据结构_IDT_ENTRY。

typedef struct _IDT_ENTRY
{
    
    
    USHORT offset_low; //中断处理函数地址低16位
    USHORT selector;
    UCHAR  reserved;
    UCHAR  type:4;
    UCHAR  always0:1;
    UCHAR  dpl:2;
    UCHAR  present:1;
    USHORT offset_high;//中断处理函数地址低16位
}IDT_ENTRY,*PIDT_ENTRY;//+3.offset_high<<16+offset_low //int 3 中断处理函数地址

参考文献

GDT,LDT,GDTR,LDTR 详解,包你理解透彻
http://www.techbulo.com/708.html

简单解释Windows如何使用FS段寄存器
https://bbs.pediy.com/thread-159935.htm

猜你喜欢

转载自blog.csdn.net/qq_43312649/article/details/109674318
ldt