GDTR和GDT
GDT和GDTR关系
GDT是global descriptor table,全局描述符表,它是描述符组成的一张描述符表。描述符就是段描述符它用来描述一个段的信息,由8个字节组成(64bit),其中信息包括了段地址和偏移地址界限等,特权级等一些信息。
GDTR中的r是register,表示的是用来存储GDT位置的寄存器,叫做全局描述符表寄存器。GDTR内部有48位,分为32位的线性地址和16位的边界。
IA-32中地址线是32位宽,所以最大内存4GB。GDT一定是存储在内存里的,通过GDTR就可以找到GDT。那GDTR可以指向多少个GDT呢?我们来算一算,GDTR的偏移地址是16位最大寻址能力是2^16 B,而一个GDT是占用8B=2^3 B,所以最大可以存储2^13(8192)个GDT。
两者的关系我理解是这样的:把GDTR理解为指针,GDT理解为指针指向的内存,要访问GDT就要通过GDTR,因为GDT是有标号的,所以要访问某个GDT只需从GDTR中获得基地址+标号*8即可。
关于图中为什么GDT画在底端的1M内存,因为GDT是保护模式下的机制,但是需要在进入保护模式之前就完成对GDT的初始化即在实模式下,众所周知实模式下只能访问1M内存,所以才有了途中的画法。
GDTR的结构
关于边界:其实就是偏移地址,但是他是会比大小小1的,因为是从0开始偏移的。
GDT的结构
它的64位的使用情况如下:
我们结合一个64位的描述符0x004F 9AFF FFFF FFFF来看一下具体含义:
首先可以确定该段的32位段地址:0x004F 9AFF FFFF FFFF即0x00FF FFFF。
段界限:0x004=F 9AFF FFFF FFFF,即0xF FFFF。
同理可得其8到15位是:A9即1 01 0 1001表示的含是
标志 | 数值 | 含义 |
---|---|---|
P | 1 | 该段位于内存| |
DPL | 01 | 特权级为1 |
S | 0 | 描述符类型为系统段 |
TYPE | 1001 | 可执行且已经访问 |
它的20到23位是:4 即0100表示的含义是:
标志 | 数值 | 含义 |
---|---|---|
G | 0 | 字节为单位 |
D/B | 1 | 32位 |
L | 0 | 不使用64位处理器 |
AVL | 0 | 软件avalible,系统不用这位 |
如何在MBR中建立GDT和GDTR?
- 1.确定gdt_size和gdt_base
MBR被加载到内存0x7c00处,MBR自身的大小是512B,我们把GDT放在MBR后面,所以gdt_base是0x7c00+0x200(512B)也就是0x7e00处,紧接着定义gdt_size,这样二者在内存上是相邻的,从内存写入GDTR的48bit的时候就可以直接写入连续的6B。当然gdt_size的大小必须确定GDT之后才知道它的大小。
gdt_size dw 0 ;GDT的大小,最后计算得出
gdt_base dd 0x00007e00 ;GDT的物理地址
- 2.建立GDT
既然确定了gdt_base,下一步就是在相应的位置顺延写入相应的数据。值得注意的是GDT中的0号位置我们都写NULL描述符。
;创建0#描述符,它是空描述符,这是处理器的要求
;根据ds:bx寻址
mov dword [bx+0x00],0x00
mov dword [bx+0x04],0x00
;创建#1描述符,保护模式下的代码段描述符
mov dword [bx+0x08],0x7c0001ff ;0x7c00开始的512B就是加载MBR的内存
mov dword [bx+0x0c],0x00409800
;创建#2描述符,保护模式下的数据段描述符(文本模式下的显示缓冲区)
mov dword [bx+0x10],0x8000ffff ; 0xb800开始的一段显存
mov dword [bx+0x14],0x0040920b
;创建#3描述符,保护模式下的堆栈段描述符
;安装栈段的描述符
mov dword [bx+0x18],0x00007a00 ;0x7c00开始的栈段
mov dword [bx+0x1c],0x00409600
- 3.设置GDTR寄存器
步骤1已经说过,现在只要计算get_size大小写入这连续的48bit即可,每个gdt是8,四个就是32B,所以界限是31(0开始的)。
mov word [cs: gdt_size+0x7c00],31 ;描述符表的界限(总字节数减一)
lgdt [cs: gdt_size+0x7c00] ;先定义的gdt_size