本课时主要介绍GDT表项的细节,以及如何重新加载GDT表。之所以重新加载GDT表,是因为原表项太小,以及该内存可能被用作其它用途,如栈。

GDT表项格式

\image (24).png

以下仅界限表项的属性部分:
● S:1-代码段或数据段,0 - 系统段
● DPL:特权级,取值0-3
● P:段是否存在,1存在,0不存在
● D/B:指示代码或栈的大小是32位还是16位,1 - 32位,0-16位
● G:段界限的单位。1 - 界限的单位是4KB,0 - 字节。
● L和AVL:我们不没有用到,使用0即可。
● type:见下表,用于描述段的具体类型
\image (25).png

GDTR寄存器

使用LGDT指令,可以将GDT表相关的信息加载到GDTR寄存器中。后续对寄存器的访问,都会通过其指向的GDT表。
\image (26).png

在重新设置后,需要使用jmp $选择子, $offset跳转。有的同学认为,可以不跳转,因为CS的值为8,新表中代码段描述符对应的选择子也为8,二者相等,无需跳转。
\image (27).png

之所以要重新跳转,是为了使CS寄存器重新加载新GDT表中相应的信息。如下图所求,CS寄存器除了保存选择子信息外,还会在内部自动保存从GDT表中加载的基地址、界限、属性等相关信息。当使用jmp $选择子, $offset进行跳转后,CS将从新表中加载新的信息,这样就避免了仍然使用原来的信息。所以,最好是重新加载,以使用新的信息。
\image (28).png

当然,在目前的工程中,由于新表中代码段相关的信息和旧表中的相同,所以不重新加载也不影响程序的运行。

参考资料

● 课程附带的intel编程文档卷3:Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 3 (3A, 3B, 3C & 3D): System Programming Guide



登陆发表评论