GDTR和GDT
GDT是Global Descriptor Table,全局描述符表,它是描述符组成的一张描述符表。描述符就是段描述符,它用来描述一个段的信息,由8个字节组成(64bit),其中信息包括了段地址、偏移地址界限、特权级等一些信息。
GDTR中的R是Register,是用来存储GDT地址信息的寄存器,叫做全局描述符表寄存器。GDTR内部有48位,分为32位的线性地址和16位的边界。
GDT和GDTR关系
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画在底端的1M内存,因为GDT是保护模式下的机制,但是需要在进入保护模式之前就完成对GDT的初始化即在实模式下,众所周知实模式下只能访问1M内存,所以才有了图中的画法。
GDTR的结构
关于边界:其实就是可偏移地址大小,但是它会比GDT的大小小1,因为是从0开始偏移的。
GDT的结构
我们结合一个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表示的含是:
它的20到23位是:4 即0100表示的含义是:
如何建立GDT、如何加载GDTR
01
确定gdt_size和gdt_base
MBR被加载到内存0x7c00处,MBR自身的大小是512B,我们把GDT放在MBR后面,所以gdt_base是0x7c00+0x200(512B)也就是0x7e00处,紧接着定义gdt_size,这样二者在内存上是相邻的,从内存写入GDTR的48bit的时候就可以直接写入连续的6B。当然gdt_size的大小必须确定GDT中的描述符之后才知道它的大小。
02
建立GDT
既然确定了gdt_base,下一步就是在相应的位置顺延写入相应的数据。值得注意的是GDT中的0号位置写NULL描述符。
03
设置GDTR寄存器
步骤1已经说过,现在只要计算get_size大小写入这连续的48bit即可,每个gdt是8B,四个就是32B,所以界限是31(0开始的)。
文章转自:小组18级成员--高星坤