全局描述符表解析

概念

全局描述符表GDT是为了实现32位模式的分段,跟16位模式的分段是一个概念。只是实现方式不一样。
在32位中,描述一个段需要以下信息:

  • 段的大小(至少1M,即20位)

  • 段的起始地址(4G, 即32位)

  • 段的属性(禁止写入,禁止执行, 系统专用等,12位)

  我们用64位(8字节)来标识一个段的基地址,及其属性。可是CPU并没有一个这样的64位段寄存器,我们能是用的依然只有16位的段寄存器。而且由于CPU设计缺陷,段寄存器的低3位还不能用。

所以我们就需要做一个13位到64位的映射。段寄存器的13位最多能标识 8192 个段,那么就把 这8192个 8字节整齐的排列在内存里。并将起始地址保存在GDTR寄存器中。
如果想访问第1000个段,其段地址 = (GDTR + 1000 * 8) 中的 段起始地址的值

代码实现

这里写图片描述

    set_segmdesc(gdt + 1, 0xffffffff, 0x00000000, 0x4092);
    set_segmdesc(gdt + 2, 0x0007ffff, 0x00280000, 0x409a);
    load_gdtr(0xffff, 0x00270000);
//设置全局描述符表
void set_segmdesc(struct SEGMENT_DESCRIPTOR *sd, unsigned int limit, int base, int ar)
{
    if(limit > 0xfffff){    //如果段大小 > 1M,则G_bit 置 1。该段定义为4G空间
        ar |= 0x8000;
        limit /= 0x1000;
    }
    sd->limit_low = limit & 0xffff;             // limit 低16位
    sd->base_low = base& 0xffff;                // base 低16位
    sd->base_mid = (base >> 16) & 0xff;         // base 中8位
    sd->access_right = ar & 0xff;               // 属性低8位
    sd->limit_high = ((limit >> 16) & 0xf) | ((ar >> 8) & 0xf0);    // limit高4位 | 属性高8位
    sd-base_high = (base >> 24) & 0xff;         // base 高8位
}

void load_gdtr(int limit, int addr) 函数无法用C语言实现,只能求助汇编了

_load_gdtr:     ; void load_gdtr(int limit, int addr);
        MOV     AX,[ESP+4]      ; limit
        MOV     [ESP+6],AX
        LGDT    [ESP+6]
        RET

中断描述符

中断描述符 和 全局描述符 的实现方式相似
这里写图片描述

//设置全局描述符表
void set_segmdesc(struct SEGMENT_DESCRIPTOR *sd, unsigned int limit, int base, int ar)
{
    if(limit > 0xfffff){    //如果段大小 > 1M,?G_bit 置 1。?段定??4G空?
        ar | 0x8000;
        limit /= 0x1000;
    }
    sd->limit_low = limit & 0xffff;             // limit 低16位
    sd->base_low = base& 0xffff;                // base 低16位
    sd->base_mid = (base >> 16) & 0xff;         // base 中8位
    sd->access_right = ar & 0xff;               // 属性低8位
    sd->limit_high = ((limit >> 16) & 0xf) | ((ar >> 8) & 0xf0);    // limit高4位 | 属性高8位
    sd->base_high = (base >> 24) & 0xff;            // base 高8位
    return;
}
_load_idtr:     ; void load_idtr(int limit, int addr);
        MOV     AX,[ESP+4]      ; limit
        MOV     [ESP+6],AX
        LIDT    [ESP+6]
        RET 
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值