直观的GDT_Table演示

在由实模式进入保护模式的时候,GDT是一个绕不开的知识点,而网上讲的都太理论化,我结合了好多篇不同作者写的文章才算把它弄懂,下面我直接用直观的方式来展现这个东西。

   假设我们的16位程序加载于:  0192h:0100h
                    jmp 16位程序段
                        gdt_table
                                16位程序段
                                      lgdt
                                      jmp 32位程序段
     我们的32位程序开始于:  0192h:0200h
                                32位程序内容
            结束于:  0192h:0300h
  
  那么我们32位程序的线性地址(真实物理地址)为: 01920h + 0200h = 1B20h  ; 该地址即为32位程序的段基地址  Base 0:32 = 0x00001b20
                                  段界限为: 0300h - 0200h = 100h   ; 该差值即为32位程序的段界限   Limit 0:19 =    0x00100  该值最大长度为20位,多了没处放哈

  

    desc_gdt_start:                             ; 每一条段描述符都是8字节,64位

    desc_def:           dd  0     ,  0          ; 第一条必须是空的描述符,后面的顺序任意

    ; 段基址占4个字节,32位,GDT里头会分成几部分存
    ; 假设我们的 Code32 所在的段地址为:
    desc_code32:        db  0x00,              ; Limit 0:7    0x001(00)
                        db  0x01,               ; Limit 8:15   0x0(01)00
                        db  0x20,               ; Base 0:7     0x00001b(20)
                        db  0x1b,               ; Base 8:15    0x0000(1b)20
                        db  0x00,               ; Base 16:23   0x00(00)1b20
                        db  0x98,               ; Access Byte
                        db  0x40                ; Flag=4  Limit 16:19 0x(0)0100
                        db  0x00                ; Base 24:31 段地址24-31位   0x(00)001b20

    ; 显存固定的,不用计算 段地址: 0x000b8000,  段界限: 0x0fffff,   属性:0x92
    desc_video:         db  0xff,               ; Limit 0:7                 0x0ff(ff)
                        db  0xff,               ; Limit 8:15                0x0(ff)ff
                        db  0x00,               ; Base 0:7                  0x000b80(00)
                        db  0x80,               ; Base 8:15                 0x000b(80)00
                        db  0x0b,               ; Base 16:23                0x00(0b)8000
                        db  0x92,               ; Access Byte               0x92
                        db  0xff                ; Flag + Limit 16:19        0x(f)ffff
                        db  0x00                ; Base 24:31 段地址24-31位  0x(00)0b8000 
    desc_gdt_end:
    gdt_ptr             equ desc_gdt_end - desc_gdt_start
                        dd  0

    selector_code32     equ desc_code32   -     desc_gdt_start  
    selector_video      equ desc_video    -     desc_gdt_start

  

  对照下代码来理解这个属性图:

                        db  0x98,               ; Access Byte
                        db  0x40                ; Flag=4  Limit 16:19 0x(0)0100

  AccessByte: 0x98 换算成二进制是  10011000             
                p = 1b,          1 表示内存中存在, 0 表示不存在
                DPL = 00b,     表示描述符特权级【0,1,2,3】,值越小权限越高
                S = 1b,          1 表示数据段, 0 表示系统段
                TYPE = 1000b     该值为十进制8,查表得知其意为:只执行

  

          
      Flag=4:  0x4  换算成二进制是  0100(另外4位被Limit用了)   
            G = 0b,         0 表示段界限粒度为字节, 1 表示段界限为4KB
            D/B = 1b,        在可执行代码段中,该值为D位,D=1表示32位地址及32、8位操作数, D=0表示16位地址及16、8位操作数
                                          向下扩展数据段中,该值为B位,B=1表示段的上部界限为4GB, B=0表示段的上部界限为64KB
                                          在描述堆栈的时候,该值为B位,B=1表示使用32位段寄存器 esp,D=0表示使用16位段寄存器 sp
            0,            未使用,0,1都可以
            VAL = 0b        该值为保留位,暂时没啥用,以后可被系统软件使用

  


原文地址:https://www.cnblogs.com/zhj11226/p/12846900.html