程序寄存器是唯一一个被所有过程共享的资源。虽然在给定时刻只能有一个过程是活动的,我们必须保证当一个过程(调用者)调用另一个(被调用者)时,被调用者不会覆盖某个调用者稍后会使用的寄存器的值。为此,IA32 (Intel Architecture 32 bit)采用了一组统一的寄存器使用惯例,所有的过程都必须遵守,包括程序库中的过程。
根据惯例,寄存器 EAX,EDX,ECX 被划分为调用者保存(caller save)寄存器。当过程 P 调用 Q 时,Q 可以覆盖这些寄存器,而不会破坏 P 所需要的数据。另外,寄存器 EBX,ESI 和 EDI 被划分为被调用者保存(callee save)寄存器。这意味着 Q 必须在覆盖它们之前,将这些寄存器的值保存到栈中,并在返回前恢复它们,因为 P(或某个更高层次的过程)可能会在今后的计算中需要这些值。此外,根据这里描述的惯例,必须保存寄存器 EBP,ESP。
如下面这段程序
int P(int x){
int y = x * x;
int z = Q(y);
return y + z;
}
过程 P 在调用 Q 之前计算 y,但是它必须保证 y 的值在 Q 返回后是可用的。有两种方式可以做到这一点:
寄存器 | 描述 |
---|---|
通用寄存器 | 8 个 32 位,存放正在处理的数据 |
段寄存器 | 6 个 16 位,处理内存访问 |
指令寄存器 | 1 个 32 位,指向要执行的下一条指令码 |
浮点寄存器 | 8 个 80 位,存放浮点数据 |
控制寄存器 | 5 个 32 位,确定处理器的操作模式 |
调试寄存器 | 8 个 32 位,在调试处理器时包含信息 |
标志寄存器 | EFLAGS |
浮点寄存器和调试寄存器没有在 XV6 中使用。
通常 X86 对操作系统隐藏了缓存,所以我们只需要考虑寄存器和主存两种存储器,不用担心主存的层次结构引发的差异。
通用寄存器 | 描述 |
---|---|
EAX | 用于操作数和结果数据的累加器 |
EBX | 指向数据内存段的数据的指针 |
ECX | 字符串和循环操作的计数器 |
EDX | IO 指针 |
EDI(destination) | 用于字符串操作的目标的数据指针 |
ESI(source) | 用于字符串操作的源的数据指针 |
ESP(stack) | 堆栈指针 |
EBP(base) | 堆栈数据指针 |
EAX,EBX,ECX,EDX 可以通过 16 位,8 位名称引用。
|<------------EAX---------------->|
|1 2 3 4 5 6 7 8 |1 2 3 4 5 6 7 8 |
|----------------|-------|--------|
|. . . . . . . . |. AH . | . AL . |
|----------------|-------|--------|
. . . . . . . . .|<------AX------>|
IA32 允许 3 种访问系统内存的方法:
段寄存器 | 描述 |
---|---|
CS(code segment) | 代码段基地址。处理器根据 CS 值和 EIP 中的偏移值取指令 |
DS(data segment) | 数据段基地址 |
ES(extra segment) | 附加段指针 |
FS | 同 ES |
GS | 同 ES |
SS(stack segment) | 堆栈段基地址;包含传递给函数和过程的数据值 |
EIP(extended instruction pointer)跟踪要执行的下一条指令码,记录偏移值或者线性地址;不可直接修改。
确定处理器的操作模式,以及当前正在处理任务的特性。
控制寄存器 | 描述 |
---|---|
CR0 | 控制处理器状态和操作模式的系统 |
CR1 | 当前没有使用 |
CR2 | 内存页面错误信息 |
CR3 | 内存页面目录信息 |
CR4 | 支持处理器特性和说明处理器特性的标志 |
不能直接读取或写入,需要通用寄存器 “中转” 一下。
该寄存器比较复杂,单独拿出来讲。每个操作都要有一种机制确定操作是否成功,IA32 平台使用 1 个 32 位的 EFLAGS 包含一组状态,控制和系统标志。
表明处理器进行的数学操作的结果。
标志 | 位 | 名称 | 描述 |
---|---|---|---|
CF | 0 | 进位标志 | 无符号整数运算最高有效位产生进位或借位,置 1 |
PF | 2 | 奇偶校验标志 | 奇校验位,使得寄存器和此位 1 的数目为奇数个 |
AF | 4 | 辅助进位标志 | 用于 BCD 码的运算 |
ZF | 6 | 零标志 | 操作结果为 0,置 1 |
SF | 7 | 符号标志 | 设置为结果的最高有效位 |
OF | 11 | 溢出标志 | 带符号数运算溢出,置 1 |
控制处理器的特定行为。
当前只定义了一个控制标志:DF
标志(direction flag),控制处理器处理字符串的方式。
DF 位置 1:字符串指令自动低递减内存地址,到达字符串的下一个字节。
DF 位置 0:字符串指令自动低递增内存地址一到达字符串的下一个字节。
控制操作系统级别的操作,应用程序不应该试图修改系统标志。
标志 | 位 | 名称 | 描述 |
---|---|---|---|
TF | 8 | 陷阱标志 | 置 1 时,启用单步模式,每次执行一条指令,等待下一条指令执行的信号。调试汇编程序时极有用 |
IF | 9 | 中断使能标志 | 控制处理器如何响应外部源接受到的信号 |
IOPL | 12~13 | IO 特权级别标志 | 表明当前正在运行的任务的 IO 权限级别 |
NT | 14 | 嵌套任务标志 | 控制当前执行的任务是否链接到前一个执行的任务。用于链接被中断和被调用的任务 |
RF | 16 | 恢复标志 | 控制处理器在调试模式如何响应异常 |
VM | 17 | 虚拟 8086 状态标志 | 表明处理器在虚拟 8086 状态执行,而不是保护模式或实模式 |
AC | 18 | 对准检查标志 | 和 CR0 的 AM 位一起用于启用内存引用的对准检查 |
VIF | 19 | 虚拟中断标志 | 处理器在虚拟模式中操作时,起到 IF 标志位的作用 |
VIP | 20 | 虚拟中断挂起标志 | 处理器在虚拟模式中操作时,标志一个中断正被挂起 |
ID | 21 | 识别标志 | 表示处理器是否支持 CPUID 指令 |