专家
公告
财富商城
电子网
旗下网站
首页
问题库
专栏
标签库
话题
专家
NEW
门户
发布
提问题
发文章
内存梳理0. 实模式和保护模式区别及寻址方式
2019-04-14 17:28
发布
生成海报
站内文章
/
模拟电子
17869
0
1322
在
上一篇
中提到了x86 保护模式,那么什么是保护模式, 本文很好的梳理了保护模式和实模式。
实模式与保护模式的来历
最早期的8086 CPU只有一种工作方式,那就是实模式,而且数据总线为 16位,地址总线为20位,实模式下所有寄存器都是16位。而从80286开始就有了保护模式,从80386开始CPU数据总线和地址总线均为32位,而且寄存器都是32位。但80386以及现在的奔腾、酷睿等等CPU为了向前兼容都保留了实模式,现代操作系统在刚加电时首先运行在实模式下,然后再切换到保护模式下运行。
实模式寻址方式
刚才说了8086 CPU数据总线为16位,也就是一次最多能取2^16=64KB数据,这个数据也解释了实模式下为什么每个段最大只有64KB。但刚才还说了其地址总线为20位,这样它能寻址的能力其实是2^20=1MB,这也就是实模式下CPU的最大寻址能力。既然它有1MB寻址能力,那怎么用16位的段寄存器表示呢?
这就引出了分段的概念,8086CPU将1MB存储空间分成许多逻辑段,每个段最大限长为64KB(但不一定就是64KB)。这样每个存储单元就可以用“段基地址+段内偏移地址”表示。段基地址由16位段寄存器值左移4位表达,段内偏移表示相对于某个段起始位置的偏移量。比如:
SEG=0x07c0
jmpi offset, #SEG
offset: mov ax,cs
保护模式寻址方式
在定义“逻辑地址”时看到保护模式和实模式的区别在于它是用
段选择符
而非
段基地址
,这也许就是保护模式的真谛所在,
从段入手
,全面理解保护模式编程基本概念和寻址方式。
1.
段的定义
段是虚拟地址到线性地址转换的基础,段的特征有以下三个:
段基址,段限长,段属性
。这三个特征
存储在段描述符
(
segment descriptor
)之中,用以实现从逻辑地址到线性地址的转换。
段描述符存储在段描述符表
(
desriptor table
)之中,
通常,我们使用段选择符定位段描述符在这个表中的位置
。
每个
逻辑地址由
16
位的段选择符
+32
位的偏移量
组成。
逻辑地址转换成线性地址的原理和过程如下:
2.
段描述符表
描述符表的长度可变,每个描述符的长度是
8B
,最多可以包含
8K
个这样的描述符(为什么呢?因为段选择符是
16
位的,其中的
13bit[bit3-bit15]
用来作
index
)。有
两种描述符表
,
GDT(global descriptor table)
和
LDT(local descriptor table)
。结构如下:(
fd02
)
段描述符表存放在由操作系统维护着的特殊数据结构之中,由处理器的内存管理硬件来引用。虚拟地址空间被分割成大小相等的两半,一半由
GDT
来映射,一半由
LDT
来映射。整个虚拟地址空间还有
2
的
14
次方个段,一半是由
GDT
映射的全局虚拟地址空间,一半是由
LDT
映射的局部虚拟地址空间。系统发生任务切换的时候,会更新任务的
LDT
。
每个系统必须定义一个
GDT
,用于系统中的所有任务和程序。可选择性定义若干个
LDT
。
GDT
本身不是一个段,而是线性地址空间的一个数据结构;
GDT
的线性基地址和长度必须加载进
GDTR
之中。因为段描述符长度是
8
,所以
GDT
长度位
8n-1.
同时,因为每个描述符长度是
8
,所以
GDT
的基地址最好进行
8
字节对齐。
LDT
表存放在
LDT
类型的段之中,此时
GDT
必须含有
LDT
的段描述符。访问
LDT
需要使用段选择符,为了减少访问
LDT
时的段转换次数,
LDT
的段选择符,段基址,段限长都要放在
LDTR
寄存器之中。
注意:查找
GDT
在线性地址中的基地址,需要借助
GDTR
;而查找
LDT
相应基地址,需要的是
GDT
中的段描述符。
LDT
本身是一个段,而
GDT
不是。
两外,使用
SGDT
和
SIDT
指令的时候,需要存储
6B
的“伪描述符”(baseaddress+limit),此时为了避免对齐检查出错,需要将它放在地址位基数开始的地方。
3.
段选择符
段选择符
也称为
段选择子
,
16bit
,它指向段描述符表中的段描述符。段选择符的结构如下:
段选择符示例:
其中
a
~
d
分别表示内核代码段
/
内核数据段
/
任务代码段
/
任务数据段的值,分别是
0x0008
,
0x0010
,
0x000f
,
0x0017.
段选择符通常是作为指针变量的一部分可见,但选择符的值通常是由链接或者加载器设置或者修改,而不是应用程序。(看图)
从上图中,我们需要注意以下几点:
1
)段寄存器只有六个,一个程序可以定义很多段,但只能同时访问六个
2
)我们提供隐藏部分,也就是描述符缓冲,来减少对描述符表的引用次数。
3
)有缓存,必然涉及到缓存一致性的维护,我们在描述符表中的描述符修改过后立即更新缓存。
4
)有两类加载指令可以改变段寄存器的值:
MOV
(
pop/lds/les/lss/lgs/lfs
)等显示指令和
CALL
(
JMP/RET/IRET/INTn/INTO/INT3
)等隐式加载指令。
4.
段描述符
4.1段描述符的通用格式
对这个图的简要解释:
1
)段限长:两个字段,一个
20b
,和
G
以及
E
地段决定段限长的实际大小和方向。
2
)
base
:
32b
,一般是
16
字节对齐
3
)
type
:指定段或者门的类型,访问种类和扩展方向,对它的解释需要依赖描述符类型标志
S
。具体解释结果如下:
4
)描述符类型标志
s
5
)描述符特权级
DPL
6)
段存在标志
P
7
)默认操作大小
/
默认栈指针大小
/
上下界标志
D/B
8
)颗粒度标志
G
4.2
代码和数据段描述符类型
S=1
的时候,该描述符用于代码段和数据段,意义如下表所示。
数据段的描述符,类型字段的低三位可以分别表示已访问(
A
),可写(
W
),拓展方向(
E
)
A
位指名自从上次操作系统复位该位之后,一个段是否被访问过。当处理器将一个段选择符加载进入相关寄存器之后,就会置位该位,直到它被明确地清除。可用于虚拟内存管理和调试。
在保护模式下,代码段是不可写的。
解说:关于一致性代码段和非一致性代码段?
4.3
系统描述符类型
如果段描述符的
S
标志是
0
的话,那么该描述符是一个系统段描述符。处理器能够识别以下类型的系统段描述符。
1
)局部描述符表的段描述符
2
)任务段(
TSS
)描述符
3
)调用门描述符
4
)中断门描述符
5
)陷阱门描述符
6
)任务门描述符
两大类:系统段描述符和门描述符。它们的具体描述符如下,使用方法见后续的
blog
后记:
存储管理模型比较繁杂,而且对应具体的硬件和相应的数据结构,需要反复理解和记忆才能弄通,总之在这个过程中,有一个问题一直需要思考:
XX
是什么?怎么得到它?得到它了以后什么东西会用到它?另外,此处总结操作系统的一条规律:哪里有速度差,哪里就有缓存;哪里有缓存,哪里就有一致性维护。
Ta的文章
更多
>>
内存梳理0. 实模式和保护模式区别及寻址方式
0 个评论
热门文章
×
关闭
举报内容
检举类型
检举内容
检举用户
检举原因
广告推广
恶意灌水
回答内容与提问无关
抄袭答案
其他
检举说明(必填)
提交
关闭
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮