您的位置:首页 > 其它

操作系统实践之第二章(LDT的使用)

2016-11-15 20:27 99 查看
前面我们已经使用过GDT了,本节主要体验一下LDT的使用。

首先LDT也是描述符表,跟GDT的区别主要在于G(Global)和L(Local)上的不同。那么我们如何在代码中使用LDT呢?下面将给出示例。

使用LDT的主要代码框架如下:

[SECTION .gdt]
…
LABEL_DESC_LDT:    Descriptor       0,        LDTLen - 1, DA_LDT	; LDT
…
SelectorLDT		equ	LABEL_DESC_LDT		- LABEL_GDT
…
[SECTION .s16]
…
; 初始化 LDT 在 GDT 中的描述符
xor	eax, eax
mov	ax, ds
shl	eax, 4
add	eax, LABEL_LDT
mov	word [LABEL_DESC_LDT + 2], ax
shr	eax, 16
mov	byte [LABEL_DESC_LDT + 4], al
mov	byte [LABEL_DESC_LDT + 7], ah

; 初始化 LDT 中的描述符
xor	eax, eax
mov	ax, ds
shl	eax, 4
add	eax, LABEL_CODE_A
mov	word [LABEL_LDT_DESC_CODEA + 2], ax
shr	eax, 16
mov	byte [LABEL_LDT_DESC_CODEA + 4], al
mov	byte [LABEL_LDT_DESC_CODEA + 7], ah
…
[SECTION .s32]; 32 位代码段. 由实模式跳入.
…
; Load LDT
mov	ax, SelectorLDT
lldt	ax

jmp	SelectorLDTCodeA:0	; 跳入局部任务
…
; LDT
[SECTION .ldt]
ALIGN	32
LABEL_LDT:
;                            段基址       段界限      属性
LABEL_LDT_DESC_CODEA: Descriptor 0, CodeALen - 1, DA_C + DA_32 ; Code, 32 位
LDTLen		equ	$ - LABEL_LDT
; LDT 选择子
SelectorLDTCodeA	equ	LABEL_LDT_DESC_CODEA	- LABEL_LDT + SA_TIL
; END of [SECTION .ldt]
; CodeA (LDT, 32 位代码段)
[SECTION .la]
ALIGN	32
[BITS	32]
LABEL_CODE_A:
mov	ax, SelectorVideo
mov	gs, ax			; 视频段选择子(目的)
mov	edi, (80 * 12 + 0) * 2	; 屏幕第 10 行, 第 0 列。
mov	ah, 0Ch			; 0000: 黑底    1100: 红字
mov	al, 'L'
mov	[gs:edi], ax

; 准备经由16位代码段跳回实模式
jmp	SelectorCode16:0
CodeALen	equ	$ - LABEL_CODE_A
; END of [SECTION .la]


代码的结构很清晰。我们先在GDT中增加了一个描述符来表示对应的LDT,然后定义了LDT选择子,后面又对描述符进行了初始化。另外我们在代码中还增加了两个节,其中一个是新的描述符表,即LDT;另一个是代码段,对应新增的LDT中的一个描述符。

其中有一段用于加载LDT,指令为lldt,对照它的兄弟lgdt我想大家就知道它的用途了。它负责加载ldtr寄存器,它的操作数是一个选择子,这个选择子对应的就是用来描述LDT的那个描述符。

LDT中的描述符和我们先前用的GDT中的描述符的差别在于后面又加了一个SA_TIL属性。该属性在pm.inc中定义如下:

SA_TIL  EQU  4

根据选择子的结构我们可以知道,SA_TIL属性的作用就是将选择子中的TI位置为1。TI位为1时,操作系统会从当前LDT中去寻找相应的描述符。

LDT的使用总体来说并不复杂,我们可以总结一下使用LDT的流程。

1.   定义我们所需的LDT,指定相应的描述符。

2.   定义LDT中描述符对应的选择子。

3.   在GDT中添加LDT对应的描述符。

4.   为GDT中的LDT定义选择子。

5.   初始化LDT在GDT中的描述符。

6.   初始化LDT中定义的描述符。

7.   使用lldt加载LDT选择子指定的内容。

8.   用jmp等指令来运行相关的局部操作。

程序运行的流程像这样:首先根据GDT中LDT描述符对应的选择子将其载入到ldtr寄存器中;当我们在使用LDT中选择子的时候,由于其TI位为1,系统知道应该从ldtr所指的内存中(即指定的LDT中)查找相应的描述符;也可以将GDT和LDT之间的关系看成一个二级索引,GDT就是第一级索引,而LDT就是第二级索引,最后LDT选择子指向的描述符就是索引项。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: