GDT表实现

GDT是保护模式下的内存段登记表。

 

 

 

 
段界限计算
段界限用 20 个二进制位来表示。只不过此段界限只是个单位量,它的单位要么是字节,要么是 4K,这是由描述符中的G位来指
定的。由于段界限只是个偏移量,是从 算起所以实际的段界限边界值=
 
(描述符中段界限+1) * (段界限的粒度大小: 4k或者 1) -1
 
这个公式很简单,就是表示有多少个 4KB 由于描述符中的段界限是从 起的,所以左边第个括号中要加个 ,表示 4KB 的实际数量。它与第二个括号中的段粒度大小相乘后得到的乘积是以
为起始的段的实际大小 由于地址是以0为起始的,所以公式的最后又减了1.

 

 

如果G位为 1,表示段界限粒度大小为 4KB 字节,故实际段界限=(描述符中段界限+ 1) k-1
个例子,如果是平坦模型,段界限为 OxFFFFF, 位为 ,套用上面公式,段界限边界值=0x100000*0x1000-1 =0xFFFFFFFF  =4G
 
 
段属性被拆分是由于历史原因。

段基地址要进行拼接才行形成完整的基地址。

 

 

 

GDT表属性

 


;-------------- gdt描述符属性 -------------
DESC_G_4K equ 1_00000000000000000000000b ;G位为1,4K粒子
DESC_D_32 equ 1_0000000000000000000000b ;DB位为1,32位系统
DESC_L equ 0_000000000000000000000b ;64位代码标记,此处标记为0便可。
DESC_AVL equ 0_00000000000000000000b ;cpu不用此位,暂置为0
DESC_LIMIT_CODE2 equ 1111_0000000000000000b ;代码段高32位长度F
DESC_LIMIT_DATA2 equ DESC_LIMIT_CODE2 ;数据段高32位长度F
DESC_LIMIT_VIDEO2 equ 0000_000000000000000b ;
DESC_P equ 1_000000000000000b ;P位在内存
DESC_DPL_0 equ 00_0000000000000b  ;访问权限
DESC_DPL_1 equ 01_0000000000000b
DESC_DPL_2 equ 10_0000000000000b
DESC_DPL_3 equ 11_0000000000000b
DESC_S_CODE equ 1_000000000000b ;S位是系统段
DESC_S_DATA equ DESC_S_CODE
DESC_S_sys equ 0_000000000000b ;非系统段,是代码段或数据段
DESC_TYPE_CODE equ 1000_00000000b ;x=1,c=0,r=0,a=0 代码段是可执行的,非依从的,不可读的,已访问位a清0.
DESC_TYPE_DATA equ 0010_00000000b ;x=0,e=0,w=1,a=0 数据段是不可执行的,向上扩展的,可写的,已访问位a清0.

;以下为系统代码段,数据段,显存段选择子的高32位初始化


DESC_CODE_HIGH4 equ (0x00 << 24) + DESC_G_4K + DESC_D_32 + DESC_L + DESC_AVL + DESC_LIMIT_CODE2 + DESC_P + DESC_DPL_0 + DESC_S_CODE + DESC_TYPE_CODE + 0x00
DESC_DATA_HIGH4 equ (0x00 << 24) + DESC_G_4K + DESC_D_32 + DESC_L + DESC_AVL + DESC_LIMIT_DATA2 + DESC_P + DESC_DPL_0 + DESC_S_DATA + DESC_TYPE_DATA + 0x00
DESC_VIDEO_HIGH4 equ (0x00 << 24) + DESC_G_4K + DESC_D_32 + DESC_L + DESC_AVL + DESC_LIMIT_VIDEO2 + DESC_P + DESC_DPL_0 + DESC_S_DATA + DESC_TYPE_DATA + 0x0b

;0x00 << 24 是填充高32位31-24的段基地址都为0

 

GDT表实现

;构建gdt及其内部的描述符
   GDT_BASE:   dd    0x00000000 
           dd    0x00000000

   CODE_DESC:  dd    0x0000FFFF 
           dd    DESC_CODE_HIGH4

   DATA_STACK_DESC:  dd    0x0000FFFF
             dd    DESC_DATA_HIGH4

   VIDEO_DESC: dd    0x80000007           ;limit=(0xbffff-0xb8000)/4k=0x7
           dd    DESC_VIDEO_HIGH4  ; 此时dpl已改为0

   GDT_SIZE   equ   $ - GDT_BASE
   GDT_LIMIT   equ   GDT_SIZE -    1 
  
   dq 50 dup(0)             ;不能预留 60个 ,60 * 8B 太大了(只有1M内存),50可以运行正常。
    ; times 60 dq 0                     ; 此处预留60个描述符的slot
   SELECTOR_CODE equ (0x0001<<3) + TI_GDT + RPL0         ; 相当于(CODE_DESC - GDT_BASE)/8 + TI_GDT + RPL0
   SELECTOR_DATA equ (0x0002<<3) + TI_GDT + RPL0     ; 同上
   SELECTOR_VIDEO equ (0x0003<<3) + TI_GDT + RPL0     ; 同上 

GDT_BASE:规定第一个GDT元素必须为全0,预防一些错误。

CODE_DESC:系统代码段,基地址为全0,段界限 可以访问 0- 4G

DATA_STACK_DESC:栈段和数据段,可以访问0-4G,后面在操作系统初始化时会修改栈地址。

VIDEO_DESC:显存段

 

访问每个GDT元素需要通过选择子进行访问,将选择子加载到段寄存器中,所以有了下面的几个SELECTOR。

计算GDT_LIMIT 是用于将GDT加载到GDT寄存器中

 

posted on 2022-05-19 18:43  thotf  阅读(449)  评论(0)    收藏  举报

导航