汇编语言线性地址简述

< 上一页x86存储管理简述 页转换下一页 >

在上一节《x86存储管理》中提到了线性地址,接下来为大家简单介绍一下线性地址。

逻辑地址转换为线性地址

多任务操作系统允许几个程序(任务)同时在内存中运行。每个程序都有自己唯一的数据区。假设现有 3 个程序,每个程序都有一个变量的偏移地址为 200h,那么,怎样区分这 3 个变量而不进行共享?

x86 解决这个问题的方法是,用一步或两步处理过程将每个变量的偏移量转换为唯一的内存地址。

第一步,将段值加上变量偏移量形成线性地址 (linear address)。这个线性地址可能就是该变量的物理地址。但是像 MS-Windows 和 Linux 这样的操作系统采用了分页 (paging) 功能,它使得程序能使用比可用物理空间更大的线性空间。这种情况下,就必需采用第二步页转换 (page translation),将线性地址转换为物理地址。

首先了解一下处理器如何用段和选择符来确定变量的线性地址。每个段选择符都指向一个段描述符(位于描述符表中),其中包含了该内存段的基地址。如下图所示,逻辑地址中的 32 位偏移量加上段基址就形成了 32 位的线性地址。

逻辑地址转化位线性地址

线性地址是一个 32 位整数,其范围为 0FFFFFFFFh,它表示一个内存位置。如果禁止分页功能,那么线性地址也就是目标数据的物 理地址。

分页

分页是 x86 处理器的一个重要功能,它使得计算机能运行在其他情况下无法装入内存的一组程序。处理器初始只将部分程序加载到内存,而程序的其他部分仍然留在硬盘上。

程序使用的内存被分割成若干小区域,称为页 (page),通常一页大小为 4KB。当每个程序运行时,处理器会选择内存中不活跃的页面替换出去,而将立即会被请求的页加载到内存。

操作系统通过维护一个页目录 (page directory) 和一组页表 (page table) 来持续跟踪当前内存中所有程序使用的页面。当程序试图访问线性地址空间内的一个地址时,处理器会自动将线性地址转换为物理地址。这个过程被称为页转换 (page translation)。

如果被请求页当前不在内存中,则处理器中断程序并产生一个页故障 (page fault)。操作系统将被请求页从硬盘复制到内存,然后程序继续执行。从应用程序的角度看,页故障和页转换都是自动发生的。

使用 Microsoft Windows 工具任务管理器(task manager)就可以查看物理内存和虚拟内存的区别。如下图所示计算机的物理内存为 256MB。任务管理器的 Commit Charge 框内为当前可用的虚拟内存总量。虚拟内存的限制为 633MB,大大高于计算机的物理内存。

windows任务管理器示例

描述符表

段描述符可以在两种表内找到:全局描述符表(global description table)和局部描述符表(local description table)。

全局描述符表(GDT)开机过程中,当操作系统将处理器切换到保护模式时,会创建唯——张 GDT,其基址保存在 GDTR(全局描述符表寄存器)中。表中的表项(称为段描述符)指向段。操作系统可以选择将所有程序使用的段保存在 GDT 中。

局部描述符表(LDT)在多任务操作系统中,每个任务或程序通常都分配有自己的段描述符表,称为 LDT。LDTR 寄存器保存的是程序 LDT 的地址。每个段描述符都包含了段在线性地址空间内的基地址。

一般,段与段之间是相互区分的。如下图所示,图中有三个不同的逻辑地址,这些地址选择了 LDT 中三个不同的表项。这里,假设禁止分页,因此, 线性地址空间也是物理地址空间。

索引局部描述符表

段描述符详细信息

除了段基址,段描述符还包含了位映射字段来说明段限长和段类型。只读类型段的一个例子就是代码段。如果程序试图修改只读段,则会产生处理器故障。

段描述符可以包含保护等级,以便保护操作系统数据不被应用程序访问。下面是对每个描述符字段的说明:

1) 基址

一个 32 位整数,定义段在 4GB 线性地址空间中的起始地址。

2) 特权级

每个段都可以分配一个特权级,特权级范围从 0 到 3,其中 0 级为最高级,一般用于操作系统核心代码。如果特权级数值高的程序试图访问特权级数值低的段,则发生处理器故障。

3) 段类型

说明段的类型并指定段的访问类型以及段生长的方向(向上或向下)。数据(包括堆栈)段可以是可读类型或读/写类型,其生长方向可以是向上的也可以是向下的。代码段可以是只执行类型或执行/只读类型。

4) 段存在标志

这一位说明该段当前是否在物理内存中。

5) 粒度标志

确定对段限长字段的解释。如果该位清零,则段限长以字节为单位。如果该 位置 1,则段限长的解释单位为 4096 字节。

6) 段限长:

这个 20 位的整数指定段大小。按照粒度标志,这个字段有两种解释:
  • 该段有多少字节,范围为 1〜1MB。
  • 该段包含多少个 4096 字节,允许段大小的范围为 4KB〜4GB。
< 上一页x86存储管理简述 页转换下一页 >

编程帮,一个分享编程知识的公众号。跟着站长一起学习,每天都有进步。

通俗易懂,深入浅出,一篇文章只讲一个知识点。

文章不深奥,不需要钻研,在公交、在地铁、在厕所都可以阅读,随时随地涨姿势。

文章不涉及代码,不烧脑细胞,人人都可以学习。

当你决定关注「编程帮」,你已然超越了90%的程序员!

编程帮二维码
微信扫描二维码关注