Chinaunix首页 | 论坛 | 博客
  • 博客访问: 326435
  • 博文数量: 135
  • 博客积分: 867
  • 博客等级: 准尉
  • 技术积分: 865
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-15 14:50
文章分类

全部博文(135)

文章存档

2012年(135)

分类: 嵌入式

2012-07-03 17:45:38

内存寻址

                                                  版本 1.0

最近 研究了一下内存寻址,没有一份资料能讲的透彻,不是不细致,而是缺乏整体感,都不全面,让人看完后没有一个整体模型,现就我关心的问题记录如下,如果要很全面很细致的记录的话会花费我很多精力,所以只是记录大概流程,以后再慢慢修正吧。

所有贴图皆来自网络

一.分段的由来 1.8086

分段的产生主要是因为 8086 处理器,不了解的可以去查一下资料。因为 8086 20 根地址线,能访问 2 20 次方共 1MB 的地址空间,但是其寄存器确是 16 , 无法保存 20 位的地址。这时就将 20 位地址分为两部分,一部分是前 16 , 保存在 cpu 的段寄存器中 , 剩下的 4 位保存在通用寄存器中,这样就形成了所谓的 段地址 : 偏移地址 形式。把 1MB 地址空间分成了 16 份,每份 64KB ,当需要寻址时就要把两部分合并,显然合并方法就是 完整地址 = 段地址 <<4 + 偏移地址 , 那么左移四位就相当于乘以 16.

这里需要注意 :

理论上每段是 64KB ,但实际偏移地址是 16 位,故其偏移有可能超出本段的范围,那么实际上 8086 是允许这样的,这样不同的地址可以有不同的段地址 : 偏移地址 的组合方法,亦即两个段可以覆盖同一区域。这里加完之后的 20 位地址即为物理地址。

2.80386 1 )实模式

         Cpu 刚加电或复位时便进入实模式,此模式下工作方式同 8086 基本一致,同样是只能访问 1MB 地址空间,并且分段。

2 )保护模式

         实模式初始化完成后便进入保护模式,此模式下便有了虚拟地址(逻辑地址)、线性地址、物理地址的区分。

逻辑地址,即为程序代码中使用的地址,分为段基址和段内偏移地址,但其合成方法有别于 8086 ,不再是简单的加法,而要复杂得多,就是通过所谓段描述符的机构进行转换。

线性地址,即逻辑地址转换完成后形成的一个 32 位的地址 ,注意 8086 中此处是 20 位, 8086 中线性地址即为物理地址,但此处不一定是,还有分页机制。

物理地址,真正的物理内存的地址,要得到他可真不容易。

二.段描述符表 1.GDT LDT IDT 定义

描述符表有三种 , 分别为全局描述符表 GDT 、局部描述符表 LDT 和中断描述符表 IDT

这三个表是在内存中操作系统或系统程序员 所建,并不是固化在哪里,所以从理论上是可以被读写的。这三个表都是描述符表格 描述符表是由若干个描述符组成 个描述符占用 8 个字节的内存空间 ,每个描述符表内最多可以有 8129 个描述符。描述符是描述一个段的大小,地址及各种状态的

1.       全局描述符表 GDT

全局描述符表在系统中只能有一个 , 且可以被每一个任务所共享 . 大部分描述符都可以放在 GDT 中,能被多个任务共享的内存区就是通过 GDT 完成的 ,

2.       局部描述符表 LDT:

局部描述符表在系统中可以有多个 , 通常情况下是与任务的数量保持对等 , 但任务可以没有局部描述符表 . 任务间不相干的部分也是通过 LDT 实现的 . 这里涉及到地址映射的问题 . GDT 一样 , 中断门和陷阱门放在 LDT 中是不会起作用的 .

3.       中断描述符表 IDT:

GDT 一样 , 中断描述符表在系统最多只能有一个 , 中断描述符表内可以存放 256 个描述符 , 分别对应 256 个中断 . 因为每个描述符占用 8 个字节 , 所以 IDT 的长度可达 2K. 中断描述符表中可以有任务门、中断门、陷阱门三个门描述符 ,其它的描述符在中断描述符表中无意义。

4.       GDTR 寄存器

GDTR 是一个长度为 48bit 的寄存器,内容为一个 32 位的基地址和一个 16 位的段限。其中 32 位的基址是指 GDT 在内存中的地址。由系统设置初始化时设置,之后不会改变。

5.       LDTR 寄存器

LDTR 是局部描述符寄存器,由一个可见的 16 位寄存器(段选择子)和一个不可见的描述符寄存器组成(描述符寄存器实际上是一个不可见的高速缓冲区)。

 

 

注意 GDTR LDTR 有区别,原因是每个 LDT 都在 GDT 中存在索引,所以 LDTR 有个段选择符,用来记录当前 LDT GDT 中的索引位置,任务切换时,先将新任务的 LDT GDT 中的索引存入 LDTR 的段选择符,然后再把相应的描述符内容加载到 LDTR 的段描述符寄存器,这样此任务以后的指令就不需要再次查找 GDT 表了。

2.LDT TSS GDT 的关系

每个任务都有自己 LDT TSS ,这是确定的,但是所有任务的 LDT 表和 TSS GDT 的关系是什么?

3. 任务切换

在这里还要引入一个段选择子的概念。段选择子是一个段寄存器 13 位用来指示描述符在描述符表中的索引号 ,低两位是表示使用描述符的特权级别;另外一位( T1 )是 GDT LDT 的信号量,如果 T1=0 ,则使用 GDTR ,如果 T1=1 ,则使用 LDTR

系统中的段寄存器共有六个: CS SS DS ES FS GS 。每个段寄存器都有其相应的一个隐藏描述符寄存器,用来保存此寄存器所选段的段描述符。当选择子被装入段寄存器时,微处理器会自动将其对应的描述符装入描述符寄存器。

系统任务切换时, LDT 切换,而 GDT 不切换(因为真个系统只有一个 GDT ),这时新任务的 LDT 描述符的选择子就被装入到 LDTR 中。然后根据其索引号在 GDT 表中查找到相应的 LDT 描述符项,把此描述符的内容加载到 LDTR 的段描述符寄存器中,这样下次就不用查找 GDT 表了。

4. 地址映射

大致流程:

A. 查看段选择符,如果其中 T1=0 ,说明是查找 GDT 表,如果 T1=1 ,则查找 LDT 表。

B. 如果是 GDT ,则从 GDTR 中取出 GDT 表在内存中的基地址,然后和段选择符的索引 index*8 相加,得到描述符项在 GDT 中的地址,然后从此项中取出段基址,再把段基址和偏移量运算得到线性地址。

C. 如果是 LDT ,则从 LDTR 中的描述符寄存器中取出 LDT 表在内存中的地址,然后和段选择符的索引 index*8 相加,得到描述符项在 LDT 中的地址,然后从此项中取出段基址,再把段基址和偏移量运算得到线性地址。

D. 如果不采用分页机制那么线性地址就已经是物理地址了。

阅读(1317) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~