【IDT】 windows IDT GDT LDT
IDT:
(Interrupt Descrptor Table)中断描述符表,用来处理中断的。
IDT的获取:
- 可以通过SIDT指令,它可以在内存中找到IDT,返回一个IDTR结构的地址。
- 也可以通过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
- 在保护模式下,对一个段的描述包括3方面因素:Base Adress, Limit, Access 它们加在一起放在一个64-bit长的数据结构中,被称为段描述符。
- 段描述符使用数组存储,使用LGDT指令将GDT的入口地址装入GDTr寄存器。
- 段选择子,一个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相关推荐
- 【转载】【VSCode】Windows下VSCode编译调试c/c++
转载自:http://blog.csdn.net/c_duoduo/article/details/51615381 懒得自己配置或自己配置出现不明问题的朋友可以点这里: [VSCode]Windo ...
- 【原创】Windows® Embedded CE 6.0 Fundamentals 读书笔记_Chapter 9
Chapter 9 第九章主要是介绍关于应用程序开发的一章.这一章比较适合应用层开发的人员来了解如何基于wince6.0开发应用层程序,首先我 们还是先看一些单词 //================ ...
- pydev集成mysql_【Python】Windows平台下Python、Pydev连接Mysql数据库
Mysql数据库是跨平台的,不是说Python一定就要连接Mongodb. Python连接Mysql数据库是非常easy的. 首先,你要配置好Python的开发环境,详见<[Python]Wi ...
- 【转】Windows IIS注册asp 此操作系统版本不支持此选项 错误解决方法
[转]Windows IIS注册asp 此操作系统版本不支持此选项 错误解决方法 参考文章: (1)[转]Windows IIS注册asp 此操作系统版本不支持此选项 错误解决方法 (2)https: ...
- 【ninja】Windows下安装ninja环境
[ninja]Windows下安装ninja环境 ninja官网传送门 环境准备 Windows环境 git环境 python环境 VS SDK 安装步骤 1.先从git仓库拉取ninja git c ...
- 【优化】windows双网叠加 多网叠加 网速叠加 教程
[优化]windows双网叠加 多网叠加 网速叠加 教程 1 连接两个以上的网络, 网络不能是同一个 例如 网线-A + wifi-B 2 控制面板\所有控制面板项\网络连接 最后 确定保存 ...
- 【C++】Windows控制台API基本使用(上)
目录 前言 一.控制台缓冲区大小 一.获取缓冲区大小 二.设置缓冲区大小 三.更详细的结构体 四.特性 二.窗口大小 一.获取窗口大小 二.设置窗口大小 三.光标位置 一.获取光标位置 二.设置光标位 ...
- 【转载】windows 如何一键关闭所有进程程序 --- (博客园 - 木人子韦)
[转载]Windows 如何一键关闭所有进程程序 --- (博客园 - 木人子韦) 1.桌面创建一个快捷方式,点击鼠标右键跳出的菜单=> 新建=>快捷方式 01 在"请键入对象的 ...
- 【VSCode】Windows下VSCode编译调试c/c++【更新】
版权声明:本文为博主原创文章,转载请注明出处. --------– 2017.06.10 更新--------- 便携版已更新,点此获取便携版 用于cpptools插件的配置文件更新 更新的launc ...
最新文章
- select count(*)加其他字段_count(1)、count(*) 与 count(列名) 的执行区别
- #4 什么是shell与bash的特性
- 强连通分量(Strongly_Connected_Components)
- 团体程序设计天梯赛-练习集L1-025 正整数A+B (15分)(getline输入)
- HMS数据库设置和优化
- Android多线程优劣,Android 开发中用到的几个多线程解析
- 这有一个机器人,粉刷本领强
- vs2010mfc单文档中添加对话框中的控件
- 通信行业最齐全的英语缩语手册
- 【技巧】安卓版按键精灵手机抓抓 取色取坐标 获取屏幕触点坐标
- Owlet for Mac(3D光线追踪渲染软件) 破解版
- cat环境搭建及springboot项目接入
- 软件项目管理系统-进度编辑
- 【C语言】扫雷游戏(包含递归展开、手自动标记功能)
- 同步通信和异步通信的爱恨情仇
- 单链表的基本操作----------头插法/尾插法建立链表
- python license activation_激活函数activation
- 【CheatEngine】关于BCR的内存分析
- HDU 5246 超级赛亚ACMer 【贪心】【STL版本二分】
- java poi 设置时间空间_java - POI - 如何将单元格值设置为Date并应用默认的Excel日期格式?...
热门文章
- 罗氏、GSK、波士顿科学、益普生、德国默克、Abcam、Wugen等公司新动态 | 跨国药企在中国...
- 新版Microsoft Edge配置 (Internet Explorer模式,默认浏览器设置)、组策略模板的中央存储创立及ADMX管理
- 解决eclipse中ctrl+S项目自动重启问题
- 55、室内装修材料燃烧性能等级
- DHTMLX Gantt:拥有高级资源计算逻辑,助力高效甘特图解决方案
- input type=“checkbox“
- Powerpoint教程_编程入门自学教程_菜鸟教程-免费教程分享
- 魅蓝x android,魅蓝X的屏幕尺寸是多少?分辨率是多少?
- matplotlib保存图片为pdf格式,文字以字体形式保存,可以illustrator编辑,而不是喵点格式。
- 使用Crypto实现RSA算法的数字签名和检验