GDT

以前的Intel 8086 是16位的CPU,它有着16位的寄存器,16位的数据总线,20位的地址总线以及1MB的寻址能力。一个地址是由段和偏移两部分组成的,物理地址遵循如下计算公式:

物理地址(Physical Address)= 段值(Segment)*16 + 偏移(Offset)

其中,段值和偏移都是16位的。

从80386开始,Intel家族的CPU进入32位时代。80386有32位地址线,所以寻址空间达到4GB。

当然,现在的计算机在实模式下,也是使用16位的寄存器,用“段:偏移”的方法寻址1MB的地址空间。

而在保护模式下,我们有了32位的寄存器,一个寄存器就可以寻址4GB的空间,是不是从此段值就被抛弃了呢?实际上并没有,新政策下的地址仍然使用“SEG:OFFSET”这样的形式来表示,只不过保护模式下“段”的概念发生了根本性的变化。段值仍然由原来16位的cs,ds等寄存器表示,但此时它仅仅变成了一个索引,这个索引指向一个数据结构的一个表项,表项中详细定义了段的起始地址,界限(段的最大长度),属性等内容。这个数据结构就是传说中的GDT(实际上还可能是LDT)。GDT中的表项也有一个专门的名字,叫做描述符。

也就是说,GDT的作用是用来提供段式存储机制,这种机制是通过段寄存器和GDT中的描述符共同提供的。

其中描述符的种类很多,他们的数据结构各有所不同,如下:

下面我们具体来看一个代码段和数据段描述符:


描述符是一个8字节的数据结构,代码段和数据段描述结构定义如下:

typedef struct _CODE_DATA_SEGMMENT_DESC{
unsigned char limit_0_7;
unsigned char limit_8_15;
unsigned char base_0_7;
unsigned char base_8_15;
unsigned char base_16_23;
unsigned char type: 4;
unsigned char system: 1;
unsigned char dpl: 2;
unsigned char present: 1;
unsigned char limit_16_19: 4;
unsigned char avl: 1;
unsigned char l: 1;
unsigned char d_b: 1;
unsigned char granularity: 1;
unsigned char base_24_31;
} CODE_DATA_SEGMMENT_DESC, *PCODE_DATA_SEGMMENT_DESC;

根据这些域的名字就可以大概知道它的意思了

(1)limit 代表段的边界值(即最大值)

(2)base 代表段的基地址

(3)type域用来指明描述符的类型

(4)system域为1表示这个描述符是普通描述符,为0则为系统描述符

(5)dpl表明访问这个段需要的最低权限(即多少Ring)

(6)present表示描述符对应的段是否在物理内存中

(7)avl软件可利用位。80386对该位的使用未做规定,Intel公司也保证今后开发生产的处理器只要与80386兼容,就不会对该位的使用做任何定义或规定

(8)d_b对于可执行代码段,称为D标志。D=0 默认16位地址和16位或8位操作数,D=1 默认32位地址和32位操作数或8位操作数。(指令前缀0x66选择非默认值的操作数大小,0x67 选择非默认值的地址大小);

对于栈段,称为B标志。B=0 使用16位栈指针,B=1 使用32位栈指针。

对于下扩数据段,称为B标志。B=0 堆栈段上界限0xFFFF(64KB),B=1 堆栈段上界限0xFFFFFFFF(4GB)

(9)granularity确定段限长字段limit值的单位,G=0 单位为1Byte,G=1 单位为4KB


其中,Type域对应如下:

普通描述符:

系统描述符:

接着,我们来看下段寄存器中的值,即描述符在GDT中的相对偏移。实际上,它有一个专门的名称,叫做段选择子(Selector)。而且,它并不是一个简单的偏移,而是要稍微复杂些,结构定义如下:

typedef struct _SELECTOR{
unsigned short rpl: 2;
unsigned short ti: 1;
unsigned short index: 13;
} SELECTOR, *PSELECTOR;

(1) 索引值(index):给出了描述符在GDT或LDT中的索引项号;

(2) 表指示标志TI(Table Index):TI=0 描述符在GDT中,TI=1 描述符在LDT

(3) 请求特权级RPL(Requested Privilege Level):0,1,2,3三个特权级。


保护模式下寻址示意图如下:


/*
描述:仿XT枚举GDT中的描述符
作者:莫灰灰
Blog:http://blog.csdn.net/hu3167343
*/

#include <ntddk.h>
typedef struct _SELECTOR{
    unsigned short rpl: 2;
    unsigned short ti: 1;
    unsigned short index: 13;
} SELECTOR, *PSELECTOR;

typedef struct _CODE_DATA_SEGMMENT_DESC{
    unsigned char limit_0_7;
    unsigned char limit_8_15;
    unsigned char base_0_7;
    unsigned char base_8_15;
    unsigned char base_16_23;
    unsigned char type: 4;
    unsigned char system: 1;
    unsigned char dpl: 2;
    unsigned char present: 1;
    unsigned char limit_16_19: 4;
    unsigned char avl: 1;
    unsigned char l: 1;
    unsigned char d_b: 1;
    unsigned char granularity: 1;
    unsigned char base_24_31;
} CODE_DATA_SEGMMENT_DESC, *PCODE_DATA_SEGMMENT_DESC;

typedef struct _INTER_TRAP_GATE_DESC{
    unsigned short offset_0_15;
    unsigned short selector;
    unsigned char reserved;
    unsigned char type: 4;
    unsigned char system: 1;
    unsigned char dpl: 2;
    unsigned char present: 1;
    unsigned short offset_16_31;
} INTER_TRAP_GATE_DESC, *PINTER_TRAP_GATE_DESC;

typedef struct _CALL_GATE_DESC{
    unsigned short offset_0_15;
    unsigned short selector;
    unsigned char param_count: 5;
    unsigned char some_bits: 3;
    unsigned char type: 4;
    unsigned char system: 1;
    unsigned char dpl: 2;
    unsigned char present: 1;
    unsigned short offset_16_31;
} CALL_GATE_DESC, *PCALL_GATE_DESC;

typedef struct _TASK_GATE_DESC{
    unsigned short reserved1;
    unsigned short selector;
    unsigned char reserved2;
    unsigned char type: 4;
    unsigned char system: 1;
    unsigned char dpl: 2;
    unsigned char present: 1;
    unsigned short reserved3;
} TASK_GATE_DESC, *PTASK_GATE_DESC;

typedef struct _GENERAL_DESC{
    unsigned int unknown1;
    unsigned char unknown2;
    unsigned char type: 4;
    unsigned char system: 1;
    unsigned char dpl: 2;
    unsigned char present: 1;
    unsigned short unknown3;
} GENERAL_DESC, *PGENERAL_DESC;

typedef struct _GDTR{
    unsigned short GdtLimit;
    unsigned short LowGdtbase;
    unsigned short HighGdtbase;
} GDTR, *PGDTR;

#define         MAKELONG(a, b) ((unsigned long) (((unsigned short) (a)) | ((unsigned long) ((unsigned short) (b))) << 16)) //IDT  

#define FOUR_BYTE_TO_DWORD( byte_0_7, byte_8_15, byte_16_23, byte_24_31 ) \
    \
    (unsigned int)byte_0_7            |                              \
    (unsigned int)byte_8_15 << 8    |                              \
    (unsigned int)byte_16_23 << 16    |                              \
    (unsigned int)byte_24_31 << 24

#define TWENTY_BIT_TO_DWORD( bit_0_7, bit_8_15, bit_16_19 ) \
    \
    (unsigned int)bit_0_7            |                \
    (unsigned int)bit_8_15 << 8        |                \
    (unsigned int)bit_16_19 << 16

#define TWO_SHORT_TO_DWORD( short_0_15, short_16_31 ) \
    \
    (unsigned int)short_0_15        |          \
    (unsigned int)short_16_31 << 16

char* NonSystemType[16] =
{
    "数据段:只读",                    // 00
    "数据段:只读,访问",            // 01
    "数据段:读写",                    // 02    
    "数据段:读写,访问",            // 03
    "数据段:只读,向下扩展",        // 04
    "数据段:只读,向下扩展,访问",    // 05
    "数据段:读写,向下扩展",        // 06
    "数据段:读写,向下扩展,访问",    // 07
    "代码段:只执行",                // 08
    "代码段:只执行,访问",            // 09
    "代码段:执行/读",                // 10
    "代码段:执行/读,访问",            // 11    
    "代码段:只执行,符合",            // 12
    "代码段:只执行,符合,访问",        // 13    
    "代码段:执行/只读, 符合",        // 14
    "代码段:执行/只读, 符合,访问"    // 15
};

char* SystemType[16] =
{
    "保留",                        // 00
    "16位:任务状态段(可用)",    // 01
    "LDT",                        // 02
    "16位:任务状态段(忙)",        // 03
    "16位:调用门",                // 04
    "任务门",                    // 05
    "16位:中断门",                // 06
    "16位:陷阱门",                // 07
    "保留",                        // 08
    "32位:任务状态段(可用)",    // 09
    "保留",                        // 10
    "32位:任务状态段(忙)",        // 11
    "32位:调用门",                // 12
    "保留",                        // 13
    "32位:中断门",                // 14
    "32位:陷阱门"                // 15
};

VOID FindGDT()
{      
    PGENERAL_DESC  GDT; 
    PCODE_DATA_SEGMMENT_DESC Code_Data_Desc;
    PCALL_GATE_DESC Call_Gate;
    GDTR  Gdt_Base;  
    ULONG GdtCount;
    ULONG i; 
    ULONG BaseAddr;
    ULONG limit;
    ULONG offset;
    PUCHAR TypeName;
    ULONG  DPL;
    PUCHAR SegmentSize;

    __asm  sgdt  Gdt_Base;

    GDT = (PGENERAL_DESC) MAKELONG( Gdt_Base.LowGdtbase, Gdt_Base.HighGdtbase );
    GdtCount = (ULONG)((Gdt_Base.GdtLimit) >> 3);

    for(i = 0; i < GdtCount; i++)
    {
        Code_Data_Desc = (PCODE_DATA_SEGMMENT_DESC) &GDT[i];
        BaseAddr = FOUR_BYTE_TO_DWORD( Code_Data_Desc->base_0_7,Code_Data_Desc->base_8_15,
            Code_Data_Desc->base_16_23,Code_Data_Desc->base_24_31);
        limit = TWENTY_BIT_TO_DWORD( Code_Data_Desc->limit_0_7,    Code_Data_Desc->limit_8_15,    
            Code_Data_Desc->limit_16_19    );
        if ( Code_Data_Desc->granularity == 1 )
        {
            SegmentSize = "Page";//4kb
        } 
        else 
        {
            SegmentSize = "Byte";//1byte
        }
        if ( GDT[i].system == 1 )    //代码和数据段描述符
        {
            TypeName = NonSystemType[Code_Data_Desc->type];
        }
        else
        {
            TypeName = SystemType[GDT[i].type];
        }
        if (GDT[i].type == 12) //32位调用门
        {
            Call_Gate = (PCALL_GATE_DESC) &GDT[i];
            DPL = Call_Gate->dpl;
        } 
        else
        {
            DPL = Code_Data_Desc->dpl;
        }
        if (strncmp(TypeName, "保留", strlen("保留")) != 0) 
        {
            DbgPrint("GDT-ID:%04x 基址: 0x%08X 界限:0x%08X 段粒度:%s 段特权级:%d 类型:%s", i,BaseAddr,limit,SegmentSize,DPL,TypeName);
        }
    } 
}

VOID DriverUnload(IN PDRIVER_OBJECT DriverObject) 
{     
    KdPrint(("Unloading...")); 
} 

NTSTATUS DriverEntry( 
                     IN PDRIVER_OBJECT DriverObject, 
                     IN PUNICODE_STRING RegistryPath 
                     ) 
{   
    DriverObject->DriverUnload = DriverUnload; 
    FindGDT(); 
    return STATUS_SUCCESS; 
} 




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值