直观的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 该值为保留位,暂时没啥用,以后可被系统软件使用
浙公网安备 33010602011771号