IDT:

(Interrupt Descrptor Table)中断描述符表,用来处理中断的。

IDT的获取:

  1. 可以通过SIDT指令,它可以在内存中找到IDT,返回一个IDTR结构的地址。
  2. 也可以通过kpcr结构获取

ISR:

中断服务例程

CPU通过查找在中断服务描述表(IDT)中找到的中断服务例程(ISR),知道如何响应以及对新接收到的中断执行哪些内核例程。

IDT的指针存储在每个物理处理器的IDTR寄存器中,每个处理器都有自己的IDTR寄存器,指向自己的中断描述符表。

IDT位置

可以通过读取IDTR寄存器的值来检查中断服务描述表在内核中的位置:

r  idtr


IDT 结构:

实模式和保护模式

CPU复位(reset)或加电(power on)的时候以实模式启动,处理器以实模式工作。
在实模式下,内存寻址方式和8086相同,由16位段寄存器的内容乘以16(10H)当
做段基地址,加上16位偏移地址形成20位的物理地址,最大寻址空间1MB,最大分
段64KB。可以使用32位指令。32位的x86 CPU用做高速的8086。在实模式下,所
有的段都是可以读、写和可执行的。
286架构导入保护模式,允许硬件等级的存储器保护。然而要使用这些新的特色,
需要额外先前不需要的软件指令。由于x86微处理机主要的设计规格,是能够完全
地向前兼容于针对先前所有x86芯片所撰写的软件,因此286芯片的开机是处于
’实模式’—也就是关闭新的存储器保护特性的模式,所以可以运行针对旧的微处
理器所设计的软件。到现在为止,即使最新的x86 CPU一开始在电源打开处于实
模式下,也能够运行针对先前任何芯片所撰写的软件.[1]

GDT、LDT与IDT

  1. 在保护模式下,对一个段的描述包括3方面因素:Base Adress, Limit, Access 它们加在一起放在一个64-bit长的数据结构中,被称为段描述符。
  2. 段描述符使用数组存储,使用LGDT指令将GDT的入口地址装入GDTr寄存器。
  3. 段选择子,一个16位的数据结构。

    三个都是比较重要的系统表
    这三个表都是在内存中由操作系统所建。但并不是固化在那里,所以从理论上是可以被读写的。

这三个表都是描述符表。

GDT: 全局服务描述符表
LDT: 局部描述符表
IDT: 中断服务描述符表

GDT 与IDT表

GDT的理解

    GDT全局服务描述表(Global Descriptor Table)
先理解一下实模式下得编程模型:在实模式下,对一个内存地址的访问是通过Segment:Offset的方式来进行的,其中Segment就是一个段的BaseAdress,一个Segment的最大长度是64kb,这是16bit系统所能表示的最大长度。

而offset是相对于此Segment Base Adress的偏移量。 Base Adress + offset就是一个内存绝对地址。由此,我们可以看出,一个段具备两个因素:Base Address 和 Limit (段的最大长度)
对于一个内存地址访问,需要指出: 使用哪个段,及相对于这个段Base Address 的offset 这个offset应该小于此段的limit。 对于16 bit 系统 ,limit不需要指定,默认最大长度为64k,且16bit的offset永远也不会大于此limit。
在保护模式下,内存的管理模式分为两种: 段模式和页模式,其中页模式也是基于段模式的。段模式是必不可少的。页模式是可选的。
对于段模式来讲,访问一个内存地址仍然使用Segment:offset的方式。 由于保护模式运行在32位系统上,那么segment的两个因素: Base Address 和limit 都是32位的。允许将一个段的地址设为32bit所能表示的任何值,而不像实模式下,一个段的Base Address只能是16的倍数。 保护模式,顾名思义,就是又为段模式提供了保护机制。也就是说一个段的描述符需要规定对自身的访问权限(Access)。
所以,在保护模式下,对一个段的描述则包括3方面的因素:【Base Address, limit , Access】,它们加在一起被放在一个64bit长的数据结构中,被称为段描述符。
在这种情况下,如果我们直接通过一个64-bit段描述符来引用一个段的时候,就必须使用一个64-bit长的段寄存器装入这个段描述符。但为了保持向后兼容,将段寄存器仍然规定为16-bit。(虽然
每个段寄存器事实上有一个64-bit长的不可见部分,但对于程序员来说,段寄存器就是16bit的),那么我们无法通过16-bit的长度的段寄存器来直接引用64-bit的段描述符,怎么办?
解决的方法就是把这些长度为64bit的段描述符放入一个数组中,而将段寄存器中的值作为下标索引来间接引用。这个全局的数组就是GDT。事实上,在GDT中存放的不仅仅是段描述符,还有其他描述符。
GDT可以被存放在内存的任何位置,当通过段寄存器引用一个段描述符时,CPU必须知道GDT的入口,也就是基地址放在哪里。所以Intel设计了一个寄存器GDTR用来存放GDT入口地址。
程序员将GDT设定在内存某个位置之后,可以通过:LGDT指令将GDT的入口地装入此寄存器。从此以后,CPU就根据此寄存器中的内容作为GDT的入口来访问GDT了。

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

我们知道,在实模式下,CPU是16位的,意思是 寄存器是16位的,数组总线是16位的,但地址总线是20位的。物理内存计算公式:

                物理地址   =  段地址 * 16 + 偏移量

段地址和偏移量都是16位,能寻址的最大内存地址为1M

2的20次方就是1M

若一个内存地址是20:30 最终的内存地址是: 20 * 16 +30

实模式和保护模式

实模式只有20位地址总线, 寻址空间只有1M ,以及8个16位的通用寄存器。4个16位的段寄存器。为了能够通过16位的寄存器去构成20位的主存地址,采取一种特殊的方法,使用下面的地址:

段基址: 段偏移量

物理地址 = 段地址 << 4 + 段内偏移

保护模式下,CPU的32条地址线全部有效,可寻址4G的字节的物理地址空间。但是为了兼容16位。此时计算机中的通用寄存器都成为32位。

在保护模式下存在一些限制。把这些限制信息放在一个全局服务描述表(GDT)中。

GDT的作用是提供段式存储机制。段寄存器提供段值,即描述符在GDT中的索引。

在进入保护模式前、必须准备好GDT、描述符和描述符选择子。

全局服务描述表:

    包含一个段的基址,界限及属性内容。其中段基地址和16位的系统中的段地址一样。只是在16位系统中段地址必须是16的倍数,但是在32位系统中段地址可以是任意地址。

寻址方式:

段地址(选择子)------在GDT中找到描述符-------
在描述符中找到段地址-----段地址+偏移地址 = 线性地址

IDT结构体:

//idtr指向这个结构体
typedef struct _IDT_INFO{UINT16 uIdtLimit;   // IDT范围UINT16 uLowIdtBase;   // IDT低基址UINT16 uHighIdtBase;   // IDT高基址
}IDT_INFO, *PIDT_INFO;// IDT表中描述符结构体
//0x8 bytes (sizeof)
typedef struct _IDTENTRY
{// USHORT == UINT16USHORT uOffsetLow;       //0x0,低地址偏移USHORT uSelector;     //0x2,段选择器//USHORT uAccess;      //0x4UINT8 uReserved;     // 保留UINT8 GateType : 4;     // 中断类型UINT8 StorageSegment : 1;   // 为0则是中断门UINT8 DPL : 2;      // 特权级UINT8 Present : 1;      // 如未使用中断可置为0USHORT uOffsetHigh; //0x6   // 高地址偏移
}IDTENTRY, *PIDTENTRY;

获取IDTR

__asm sidt stcIDT

遍历IDT:

#include <ntifs.h>
#include <ntddk.h>#define MAKE_LONG(a,b) ((a) + (b<<16))typedef struct _IDT_INFO {UINT16 uIdtLimit;   // IDT范围UINT16 uLowIdtBase;   // IDT低基址UINT16 uHighIdtBase;   // IDT高基址
}IDT_INFO, * PIDT_INFO;//0x8 bytes (sizeof)
typedef struct _IDTENTRY
{// USHORT == UINT16USHORT uOffsetLow;       //0x0,低地址偏移USHORT uSelector;     //0x2,段选择器//USHORT uAccess;      //0x4UINT8 uReserved;     // 保留UINT8 GateType : 4;     // 中断类型UINT8 StorageSegment : 1;   // 为0则是中断门UINT8 DPL : 2;      // 特权级UINT8 Present : 1;      // 如未使用中断可置为0USHORT uOffsetHigh; //0x6   // 高地址偏移
}IDTENTRY, *PIDTENTRY;void OnUnload(DRIVER_OBJECT* pDriver)
{pDriver;
}NTSTATUS DriverEntry(DRIVER_OBJECT* pDriver, UNICODE_STRING* pRegPath)
{NTSTATUS status = STATUS_SUCCESS;pRegPath;pDriver->DriverUnload = OnUnload;//KdBreakPoint();IDT_INFO stcIDT = { 0 };PIDTENTRY pIdtEntry = NULL;ULONG uAddr = 0;// IDT table__asm sidt stcIDT;// IDT arraypIdtEntry = (PIDTENTRY)MAKE_LONG(stcIDT.uLowIdtBase, stcIDT.uHighIdtBase);KdPrint(("-------------IDT---------------\n"));KdPrint(("IDT Addr: 0x%p\n", pIdtEntry));for (ULONG i = 0; i < 0x100; ++i){KdPrint(("Interrupted number: %d\n", i));uAddr = MAKE_LONG(pIdtEntry[i].uOffsetLow, pIdtEntry[i].uOffsetHigh);KdPrint(("Interrupted Addr: 0x%p\n", uAddr));KdPrint(("selector: %d\n", pIdtEntry[i].uSelector));KdPrint(("GataType: %d\n", pIdtEntry[i].GateType));KdPrint(("DPL: %d\n\n", pIdtEntry[i].DPL));}return status;
}

获取IDTR

__asm sidt stcIDT

遍历IDT:

#include <ntifs.h>
#include <ntddk.h>#define MAKE_LONG(a,b) ((a) + (b<<16))typedef struct _IDT_INFO {UINT16 uIdtLimit;   // IDT范围UINT16 uLowIdtBase;   // IDT低基址UINT16 uHighIdtBase;   // IDT高基址
}IDT_INFO, * PIDT_INFO;//0x8 bytes (sizeof)
typedef struct _IDTENTRY
{// USHORT == UINT16USHORT uOffsetLow;       //0x0,低地址偏移USHORT uSelector;     //0x2,段选择器//USHORT uAccess;      //0x4UINT8 uReserved;     // 保留UINT8 GateType : 4;     // 中断类型UINT8 StorageSegment : 1;   // 为0则是中断门UINT8 DPL : 2;      // 特权级UINT8 Present : 1;      // 如未使用中断可置为0USHORT uOffsetHigh; //0x6   // 高地址偏移
}IDTENTRY, *PIDTENTRY;void OnUnload(DRIVER_OBJECT* pDriver)
{pDriver;
}NTSTATUS DriverEntry(DRIVER_OBJECT* pDriver, UNICODE_STRING* pRegPath)
{NTSTATUS status = STATUS_SUCCESS;pRegPath;pDriver->DriverUnload = OnUnload;//KdBreakPoint();IDT_INFO stcIDT = { 0 };PIDTENTRY pIdtEntry = NULL;ULONG uAddr = 0;// IDT table__asm sidt stcIDT;// IDT arraypIdtEntry = (PIDTENTRY)MAKE_LONG(stcIDT.uLowIdtBase, stcIDT.uHighIdtBase);KdPrint(("-------------IDT---------------\n"));KdPrint(("IDT Addr: 0x%p\n", pIdtEntry));for (ULONG i = 0; i < 0x100; ++i){KdPrint(("Interrupted number: %d\n", i));uAddr = MAKE_LONG(pIdtEntry[i].uOffsetLow, pIdtEntry[i].uOffsetHigh);KdPrint(("Interrupted Addr: 0x%p\n", uAddr));KdPrint(("selector: %d\n", pIdtEntry[i].uSelector));KdPrint(("GataType: %d\n", pIdtEntry[i].GateType));KdPrint(("DPL: %d\n\n", pIdtEntry[i].DPL));}return status;
}

遍历GDT:

#include <ntddk.h>#define MAKE_LONG(a,b) ((LONG)(((UINT16)(((DWORD_PTR)(a)) & 0xffff)) | ((UINT32)((UINT16)(((DWORD_PTR)(b)) & 0xffff))) << 16))typedef struct _GDT_INFO {UINT16 uGdtLimit;UINT16 uLowGdtBase;UINT16 uHighGdtBase;
}GDT_INFO, *PGDT_INFO;//0x8 bytes (sizeof)
typedef struct _GDTENTRY
{USHORT LimitLow;                                                        //0x0USHORT BaseLow;                                                         //0x2union{struct{UCHAR BaseMid;                                                  //0x4UCHAR Flags1;                                                   //0x5UCHAR Flags2;                                                   //0x6UCHAR BaseHi;                                                   //0x7} Bytes;                                                            //0x4struct{ULONG BaseMid : 8;                                           ULONG Type : 4;     ULONG S : 1;ULONG Dpl : 2;                                               ULONG Pres : 1;                                              ULONG LimitHi : 4;                                           ULONG Avl : 1;                                               ULONG Reserved_0 : 1;                                        ULONG D_B : 1;                                       ULONG Granularity : 1;                                       ULONG BaseHi : 8;                                            } Bits;                                                          } HighWord;
}GDTENTRY, *PGDTENTRY;void OnUnload(DRIVER_OBJECT* pDriver)
{pDriver;
}NTSTATUS DriverEntry(DRIVER_OBJECT* pDriver, UNICODE_STRING* pRegPath)
{NTSTATUS status = STATUS_SUCCESS;pRegPath;pDriver->DriverUnload = OnUnload;//KdBreakPoint();GDT_INFO stcGDT = { 0 };PGDTENTRY pGdtEntry = NULL;unsigned int nGdtEntry = 0;ULONG uData = 0;// IDT table__asm sgdt stcGDT;// IDT arraypGdtEntry = (PGDTENTRY)MAKE_LONG(stcGDT.uLowGdtBase, stcGDT.uHighGdtBase);KdPrint(("-------------GDT---------------\n"));KdPrint(("GDT Addr: 0x%p\n", pGdtEntry));nGdtEntry = stcGDT.uGdtLimit / 8;for (ULONG i = 0; i < nGdtEntry; ++i){if (!(pGdtEntry[i].HighWord.Bits.Pres)) continue;uData = (ULONG)pGdtEntry[i].BaseLow+ ((ULONG)(pGdtEntry[i].HighWord.Bits.BaseMid) << 16)+ ((ULONG)(pGdtEntry[i].HighWord.Bits.BaseHi) << 24);KdPrint(("BaseAddr: 0x%p\n", uData));uData = pGdtEntry[i].LimitLow+ ((ULONG)(pGdtEntry[i].HighWord.Bits.LimitHi) << 16);KdPrint(("Segment Limit: 0x%08X ", uData));(pGdtEntry[i].HighWord.Bits.Granularity)? KdPrint(("pages\n")): KdPrint(("bytes\n"));KdPrint(("DPL: %d\n", pGdtEntry[i].HighWord.Bits.Dpl));if ((pGdtEntry[i].HighWord.Bits.S == 0)){KdPrint(("Type: System segment\t"));switch (pGdtEntry[i].HighWord.Bits.Type){case 12:KdPrint(("Call Gate "));break;case 14:KdPrint(("Interruptting Gate "));break;case 15:KdPrint(("Trap Gate "));break;case 5:KdPrint(("Task Gate "));break;default:KdPrint(("Unknown "));break;}KdPrint(("\n"));}else{if (pGdtEntry[i].HighWord.Bits.Type & 0x8){KdPrint(("Type: Code Segment\n"));KdPrint(("Attr: "));KdPrint(("%s", pGdtEntry[i].HighWord.Bits.Type & 0x4 ? "C" : "-"));KdPrint(("%s", pGdtEntry[i].HighWord.Bits.Type & 0x2 ? "R" : "-"));KdPrint(("%s", pGdtEntry[i].HighWord.Bits.Type & 0x1 ? "A" : "-"));KdPrint(("\n"));}else{KdPrint(("Type: Data Segment\n"));KdPrint(("Attr: "));KdPrint(("%s", pGdtEntry[i].HighWord.Bits.Type & 0x4 ? "E" : "-"));KdPrint(("%s", pGdtEntry[i].HighWord.Bits.Type & 0x2 ? "W" : "-"));KdPrint(("%s", pGdtEntry[i].HighWord.Bits.Type & 0x1 ? "A" : "-"));KdPrint(("\n"));}}KdPrint(("\n"));}return status;
}

REFERENCE

https://www.cnblogs.com/ciyze0101/p/5350613.html windows 下的IDT hook和GDT的学习
https://blog.csdn.net/ggh19/article/details/113705230?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1-113705230-blog-50654629.pc_relevant_default&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1-113705230-blog-50654629.pc_relevant_default&utm_relevant_index=2 操作系统中的描述符和GDT

【IDT】 windows IDT GDT LDT相关推荐

  1. 【转载】【VSCode】Windows下VSCode编译调试c/c++

    转载自:http://blog.csdn.net/c_duoduo/article/details/51615381 懒得自己配置或自己配置出现不明问题的朋友可以点这里:  [VSCode]Windo ...

  2. 【原创】Windows® Embedded CE 6.0 Fundamentals 读书笔记_Chapter 9

    Chapter 9 第九章主要是介绍关于应用程序开发的一章.这一章比较适合应用层开发的人员来了解如何基于wince6.0开发应用层程序,首先我 们还是先看一些单词 //================ ...

  3. pydev集成mysql_【Python】Windows平台下Python、Pydev连接Mysql数据库

    Mysql数据库是跨平台的,不是说Python一定就要连接Mongodb. Python连接Mysql数据库是非常easy的. 首先,你要配置好Python的开发环境,详见<[Python]Wi ...

  4. 【转】Windows IIS注册asp 此操作系统版本不支持此选项 错误解决方法

    [转]Windows IIS注册asp 此操作系统版本不支持此选项 错误解决方法 参考文章: (1)[转]Windows IIS注册asp 此操作系统版本不支持此选项 错误解决方法 (2)https: ...

  5. 【ninja】Windows下安装ninja环境

    [ninja]Windows下安装ninja环境 ninja官网传送门 环境准备 Windows环境 git环境 python环境 VS SDK 安装步骤 1.先从git仓库拉取ninja git c ...

  6. 【优化】windows双网叠加 多网叠加 网速叠加 教程

    [优化]windows双网叠加 多网叠加 网速叠加 教程 1 连接两个以上的网络, 网络不能是同一个 例如  网线-A   +   wifi-B 2 控制面板\所有控制面板项\网络连接 最后 确定保存 ...

  7. 【C++】Windows控制台API基本使用(上)

    目录 前言 一.控制台缓冲区大小 一.获取缓冲区大小 二.设置缓冲区大小 三.更详细的结构体 四.特性 二.窗口大小 一.获取窗口大小 二.设置窗口大小 三.光标位置 一.获取光标位置 二.设置光标位 ...

  8. 【转载】windows 如何一键关闭所有进程程序 --- (博客园 - 木人子韦)

    [转载]Windows 如何一键关闭所有进程程序 --- (博客园 - 木人子韦) 1.桌面创建一个快捷方式,点击鼠标右键跳出的菜单=> 新建=>快捷方式 01 在"请键入对象的 ...

  9. 【VSCode】Windows下VSCode编译调试c/c++【更新】

    版权声明:本文为博主原创文章,转载请注明出处. --------– 2017.06.10 更新--------- 便携版已更新,点此获取便携版 用于cpptools插件的配置文件更新 更新的launc ...

最新文章

  1. select count(*)加其他字段_count(1)、count(*) 与 count(列名) 的执行区别
  2. #4 什么是shell与bash的特性
  3. 强连通分量(Strongly_Connected_Components)
  4. 团体程序设计天梯赛-练习集L1-025 正整数A+B (15分)(getline输入)
  5. HMS数据库设置和优化
  6. Android多线程优劣,Android 开发中用到的几个多线程解析
  7. 这有一个机器人,粉刷本领强
  8. vs2010mfc单文档中添加对话框中的控件
  9. 通信行业最齐全的英语缩语手册
  10. 【技巧】安卓版按键精灵手机抓抓 取色取坐标 获取屏幕触点坐标
  11. Owlet for Mac(3D光线追踪渲染软件) 破解版
  12. cat环境搭建及springboot项目接入
  13. 软件项目管理系统-进度编辑
  14. 【C语言】扫雷游戏(包含递归展开、手自动标记功能)
  15. 同步通信和异步通信的爱恨情仇
  16. 单链表的基本操作----------头插法/尾插法建立链表
  17. python license activation_激活函数activation
  18. 【CheatEngine】关于BCR的内存分析
  19. HDU 5246 超级赛亚ACMer 【贪心】【STL版本二分】
  20. java poi 设置时间空间_java - POI - 如何将单元格值设置为Date并应用默认的Excel日期格式?...

热门文章

  1. 罗氏、GSK、波士顿科学、益普生、德国默克、Abcam、Wugen等公司新动态 | 跨国药企在中国...
  2. 新版Microsoft Edge配置 (Internet Explorer模式,默认浏览器设置)、组策略模板的中央存储创立及ADMX管理
  3. 解决eclipse中ctrl+S项目自动重启问题
  4. 55、室内装修材料燃烧性能等级
  5. DHTMLX Gantt:拥有高级资源计算逻辑,助力高效甘特图解决方案
  6. input type=“checkbox“
  7. Powerpoint教程_编程入门自学教程_菜鸟教程-免费教程分享
  8. 魅蓝x android,魅蓝X的屏幕尺寸是多少?分辨率是多少?
  9. matplotlib保存图片为pdf格式,文字以字体形式保存,可以illustrator编辑,而不是喵点格式。
  10. 使用Crypto实现RSA算法的数字签名和检验