您的位置:首页 > 其它

一个操作系统的实现(4)-认识LDT

2016-05-23 18:44 295 查看
看到这里,你应该已经很了解GDT了,如果还不了解GDT。请看这篇文章:
一个操作系统的实现(2)-认识保护模式
,认识保护模式那篇文章的最后详细介绍了由16位寻址升级到32位寻址而引入的
GDT


LDT(Local Descriptor Table):从名字上面就可以看出来它与GDT(Gobal Descriptor Table)的区别。GDT是全局描述符表,LDT是局部描述符表(相对于GDT)。

下面仍然是从代码的角度讲解什么是LDT。主要讲解在上一节的基础上增加的代码。在文章的最后会附上所有代码。为了描述LDT,在上一节的基础上添加了如下代码:


现在来看上面的代码。

首先,

在GDT中增加了一个
描述符
和描述符对应的
选择子


然后,

增加了两个节,在上述代码的最后两段。分别是
新的描述符表LDT
代码段
,这个代码段的描述符在LDT中。用来演示LDT的如何使用。

接下来看16位代码段中的初始化代码,

这里的初始化代码对描述符进行初始化。包括两个部分,一个是
初始化LDT在GDT中的描述符
,另一个是
初始化LDT中的描述符


最后,在32位代码段中增加如下内容:


这里面有个
lldt ax
。它与lgdt类似,lgdt用来将gdt的基址(32位)与界限(16位)加载到gdtr中。类似地,lldt是将
ldt描述符的选择子
加载到ldtr中。

你看看上面的LDT的结构,与GDT结构是不是非常像。是的,LDT与GDT有两个最主要的差别,一个是上面所说LDT使用lldt加载的对象是选择子而GDT使用lgdt加载的对象是gdt的基地址和界限(通常用一个在内存中的结构体表示)。另外一个差别就是LDT的选择子
TI位
与GDT的选择子的TI位不同。还记的TI吗?它是选择子结构中的一位。不记得的话看下面的选择子结构:
1514131211109876543210
描述符索引TIRPL
第2位是TI位,上一节课我也不清楚它用来干什么的。到这里再来解释它就很清晰了。

仔细观察上面LDT选择子与GDT选择子,你会发现:LDT的选择子比GDT的选择子多了一个
SA_TIL
属性。在
pm.inc
中找到它的定义如下:


结合上图可知,SA_TIL将选择子
SelectorLDTCodeA
的TI位置为1。实际上,TI位便是用来区别GDT的选择子和LDT的选择子的关键所在。如果TI被置为1,系统将从局部描述符表LDT中读取描述符;如果TI位为0,系统将从全局描述符表GDT中读取描述符。

因此,当上面的代码运行到
jmp SelectorLDTCodeA:0
处时,系统会从LDT中找到
LABEL_LDT_DESC_CODEA
描述符,并跳转到相应的段中。

本例中LDT中的代码比较简单,只是在屏幕上输入一个字符L。

不难想象,在[SECTION .s32]中打印完“In Protect Mode now.”这个字符串后,一个红色的字符L将会出现。程序运行结果如下:





现在,你对LDT应该有了大致的了解了吧。简单来说,他是一种描述符表,与GDT差不多,只不过它的选择子的TI位必须置1.在运用它时,需要先用lldt指令加载ldtr,lldt的操作数是GDT中用来描述LDT的描述符。

上面的例子中的LDT只有一个代码段。随着以后的逐渐深入,我们还可以在其中增加更多的段,比如数据段、堆栈段等。通过,我们可以把一个单独的任务所用到的所有东西封装在LDT中,这种思想是多任务处理的一个雏形。

下面是完整代码:

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  操作系统 ubuntu