保护模式下的分段内存寻址
2015-05-28 14:46
302 查看
段选择符([b]段寄存器中的值)[/b]
32位汇编中16位段寄存器(CS、DS、ES、SS、FS、GS)中不再存放段基址,而是段描述符在段描述符表中的索引值,D3-D15位是索引值,D0-D1位是请求特权级(RPL)用于特权检查,D2位是描述符表引用指示位TI,TI=0指 示从全局描述表GDT中读取描述符,TI=1指示从局部描述符中LDT中读取描述符。这些信息总称段选择符(段选择子).
![](http://hi.csdn.net/attachment/201008/24/48588_1282618331NT4z.jpg)
关于特权级的说明:任务中的每一个段都有一个特定的级别。每当一个程序试图访问某一个段时,就将该程序所拥有的特权级与要访问的特权级进行比较,以决定能否访问该段。系统约定,CPU只能访问同一特权级或级别较低特权级的段。
段描述符
占8个字节64位,每一个段都有一个对应的描述符。根据描述符所描述的对象不同,描述符可分为三类:储存段描述符,系统段描述符,门描述符(控制描述 符)。在描述符中定义了段的基址,限长和访问内型等属性。其中基址给出该段的基础地址,用于形成线性地址;限长说明该段的长度,用于存储空间保护;段属性 说明该段的访问权限、该段当前在内存中的存在性,以及该段所在的特权级。
以下是描述符表中的一项描述符的定义:
![](http://bbs.pediy.com/attachment.php?attachmentid=74471&thumb=1&d=1355721903)
段描述符表
IA-32处理器把所有段描述符按顺序组织成线性表 放在内存中,称为段描述符表。分为三类:全局描述符表GDT,局部描述符表LDT和中断描述符表IDT。GDT和IDT在整个系统中只有一张,而每个任务 都有自己私有的一张局部描述符表LDT,用于记录本任务中涉及的各个代码段、数据段和堆栈段以及本任务的使用的门描述符。GDT包含系统使用的代码段、数 据段、堆栈段和特殊数据段描述符,以及所有任务局部描述符表LDT的描述符。
全局描述符表GDT
全局描述符表GDT(Global Descriptor Table):在整个系统中,全局描述符表GDT只有一张(一个处理器对应一个GDT),GDT可以被放在内存的任何位置,但CPU必须知道GDT的入口,也就是基地址放在哪里,Intel的设计者门提供了一个寄存器GDTR用来存放GDT的入口地址,程序员将GDT设定在内存中某个位置之后,可以通过LGDT指令将GDT的入口地址装入此寄存器,从此以后,CPU就根据此寄存器中的内容作为GDT的入口来访问GDT了。GDTR中存放的是GDT在内存中的基地址和其表长界限。
注意:GDT的第一项总为空,且称为空段描述符,指向GDT中该描述符的选择器被称为空选择器。
GDTR全局描述符表寄存器
48位,高32位存放GDT基址,低16为存放GDT限长。
![](http://hi.csdn.net/attachment/201008/24/48588_128261824694v4.jpg)
局部描述符表LDT
局部描述符表LDT(Local Descriptor Table):局部描述符表可以有若干张,每个任务可以有一张。
LDTR局部描述符表寄存器
LDTR寄存器保存了16位段选择符、32位基地址、16位段界限和LDT描述符属性。基地址是指LDT的0字节的线性地址。
LLDT指令:装载LDTR寄存器中的段选择符(16位)那部分。
SLDT指令:保存LDTR寄存器中的段选择符(16位)那部分。
16位段选择符中,高13位存放LDT在GDT中的索引值。
保护模式下分段内存寻址
IA-32处理器仍然可以使用xxxx:yyyyyyyy(段选择器:偏移量)样式的逻辑地址来表示一个线性地址。那么CPU是如何将这样的一个逻辑地址转换成一个线性地址呢?首先,要获取逻辑地址所在段的基地址。那么要怎样才能得到段的基址呢?在上面说明中我们知道,要得到段的基址首先通过段选择符xxxx中TI位指定的段描述符所在位置: 当 TI=0时表示段描述符在GDT中,如下图所示:① 先从GDTR寄存器中获得GDT基址。② 然后再GDT中以段选择符高13位位置索引值得到段描述符。③
段描述符符包含段的基址、限长、优先级等各种属性,这就得到了段的起始地址(基址),再以基址加上偏移地址yyyyyyyy才得到最后的线性地址。
![](http://blog.rootk.com/file/cdc5e2064e8f7279d6dabf4aaf3fc0b9.jpg)
当TI=1时表示段描述符在LDT中,如下图所示:① 还是先从GDTR寄存器中获得GDT基址。② 从LDTR寄存器中获取LDT所在段的位置索引(LDTR高13位)。③ 以这个位置索引在GDT中得到LDT段描述符从而得到LDT段基址。④ 用段选择符高13位位置索引值从LDT段中得到段描述符。⑤ 段描述符符包含段的基址、限长、优先级等各种属性,这就得到了段的起始地址(基址),再以基址加上偏移地址yyyyyyyy才得到最后的线性地址。
![](http://blog.rootk.com/file/fd20bfcfff3ea81f0640406db9316f83.jpg)
例子:
给出逻辑地址:21h:12345678h,将其转换为线性地址
a. 选择子SEL=21h=0000000000100 0 01b 他代表的意思是:选择子的index=4即100b,选择GDT中的第4个描述符;TI=0代表选择子是在GDT选择;左后的01b代表特权级RPL=1
b. OFFSET=12345678h,若此时GDT第四个描述符中描述的段基址(Base)为11111111h,则线性地址=11111111h+12345678h=23456789h
参考连接:
http://ju.outofmemory.cn/entry/111444
http://blog.csdn.net/billpig/article/details/5833980
32位汇编中16位段寄存器(CS、DS、ES、SS、FS、GS)中不再存放段基址,而是段描述符在段描述符表中的索引值,D3-D15位是索引值,D0-D1位是请求特权级(RPL)用于特权检查,D2位是描述符表引用指示位TI,TI=0指 示从全局描述表GDT中读取描述符,TI=1指示从局部描述符中LDT中读取描述符。这些信息总称段选择符(段选择子).
![](http://hi.csdn.net/attachment/201008/24/48588_1282618331NT4z.jpg)
关于特权级的说明:任务中的每一个段都有一个特定的级别。每当一个程序试图访问某一个段时,就将该程序所拥有的特权级与要访问的特权级进行比较,以决定能否访问该段。系统约定,CPU只能访问同一特权级或级别较低特权级的段。
段描述符
占8个字节64位,每一个段都有一个对应的描述符。根据描述符所描述的对象不同,描述符可分为三类:储存段描述符,系统段描述符,门描述符(控制描述 符)。在描述符中定义了段的基址,限长和访问内型等属性。其中基址给出该段的基础地址,用于形成线性地址;限长说明该段的长度,用于存储空间保护;段属性 说明该段的访问权限、该段当前在内存中的存在性,以及该段所在的特权级。
以下是描述符表中的一项描述符的定义:
段描述符表
IA-32处理器把所有段描述符按顺序组织成线性表 放在内存中,称为段描述符表。分为三类:全局描述符表GDT,局部描述符表LDT和中断描述符表IDT。GDT和IDT在整个系统中只有一张,而每个任务 都有自己私有的一张局部描述符表LDT,用于记录本任务中涉及的各个代码段、数据段和堆栈段以及本任务的使用的门描述符。GDT包含系统使用的代码段、数 据段、堆栈段和特殊数据段描述符,以及所有任务局部描述符表LDT的描述符。
全局描述符表GDT
全局描述符表GDT(Global Descriptor Table):在整个系统中,全局描述符表GDT只有一张(一个处理器对应一个GDT),GDT可以被放在内存的任何位置,但CPU必须知道GDT的入口,也就是基地址放在哪里,Intel的设计者门提供了一个寄存器GDTR用来存放GDT的入口地址,程序员将GDT设定在内存中某个位置之后,可以通过LGDT指令将GDT的入口地址装入此寄存器,从此以后,CPU就根据此寄存器中的内容作为GDT的入口来访问GDT了。GDTR中存放的是GDT在内存中的基地址和其表长界限。
注意:GDT的第一项总为空,且称为空段描述符,指向GDT中该描述符的选择器被称为空选择器。
GDTR全局描述符表寄存器
48位,高32位存放GDT基址,低16为存放GDT限长。
![](http://hi.csdn.net/attachment/201008/24/48588_128261824694v4.jpg)
局部描述符表LDT
局部描述符表LDT(Local Descriptor Table):局部描述符表可以有若干张,每个任务可以有一张。
LDTR局部描述符表寄存器
LDTR寄存器保存了16位段选择符、32位基地址、16位段界限和LDT描述符属性。基地址是指LDT的0字节的线性地址。
LLDT指令:装载LDTR寄存器中的段选择符(16位)那部分。
SLDT指令:保存LDTR寄存器中的段选择符(16位)那部分。
16位段选择符中,高13位存放LDT在GDT中的索引值。
保护模式下分段内存寻址
IA-32处理器仍然可以使用xxxx:yyyyyyyy(段选择器:偏移量)样式的逻辑地址来表示一个线性地址。那么CPU是如何将这样的一个逻辑地址转换成一个线性地址呢?首先,要获取逻辑地址所在段的基地址。那么要怎样才能得到段的基址呢?在上面说明中我们知道,要得到段的基址首先通过段选择符xxxx中TI位指定的段描述符所在位置: 当 TI=0时表示段描述符在GDT中,如下图所示:① 先从GDTR寄存器中获得GDT基址。② 然后再GDT中以段选择符高13位位置索引值得到段描述符。③
段描述符符包含段的基址、限长、优先级等各种属性,这就得到了段的起始地址(基址),再以基址加上偏移地址yyyyyyyy才得到最后的线性地址。
![](http://blog.rootk.com/file/cdc5e2064e8f7279d6dabf4aaf3fc0b9.jpg)
当TI=1时表示段描述符在LDT中,如下图所示:① 还是先从GDTR寄存器中获得GDT基址。② 从LDTR寄存器中获取LDT所在段的位置索引(LDTR高13位)。③ 以这个位置索引在GDT中得到LDT段描述符从而得到LDT段基址。④ 用段选择符高13位位置索引值从LDT段中得到段描述符。⑤ 段描述符符包含段的基址、限长、优先级等各种属性,这就得到了段的起始地址(基址),再以基址加上偏移地址yyyyyyyy才得到最后的线性地址。
![](http://blog.rootk.com/file/fd20bfcfff3ea81f0640406db9316f83.jpg)
例子:
给出逻辑地址:21h:12345678h,将其转换为线性地址
a. 选择子SEL=21h=0000000000100 0 01b 他代表的意思是:选择子的index=4即100b,选择GDT中的第4个描述符;TI=0代表选择子是在GDT选择;左后的01b代表特权级RPL=1
b. OFFSET=12345678h,若此时GDT第四个描述符中描述的段基址(Base)为11111111h,则线性地址=11111111h+12345678h=23456789h
参考连接:
http://ju.outofmemory.cn/entry/111444
http://blog.csdn.net/billpig/article/details/5833980
相关文章推荐
- 内存寻址(二)--存储保护机制(CPU实模式与保护模式)
- 深入理解计算机系统-之-内存寻址(二)--存储保护机制(CPU实模式与保护模式)
- 四、保护模式之内存分段管理机制
- 32位保护模式内存寻址原理
- 操作系统实践之第二章(保护模式下的分段寻址)
- 内存梳理0. 实模式和保护模式区别及寻址方式
- X86保护模式下的内存寻址
- 为什么在保护模式下IA-32处理器最高可访问4GB的内存
- 实模式和保护模式区别及寻址方式
- 玩儿转C语言:系统内存模型之实模式和保护模式
- 内存寻址 是否分段 形象描述
- 保护模式超强的寻址功能:天空任鸟飞
- 深入理解Linux内存寻址的分段机制
- 32位寻址-保护模式
- 实模式和保护模式区别及寻址方式
- java开发操作系统内核:由实模式进入保护模式之32位寻址
- 实模式和保护模式区别及寻址方式
- <<Linux内核完全剖析 --基于0.12内核>>学习笔记 第4章 80x86保护模式及其编程 4.3 分段机制
- 保护模式下寻址
- 使用WinIO库实现保护模式下的IO和内存读写(_inp,_outp)