寄存器是 CPU 内部用来存放数据的一些小型存储区域,用来暂时存放参与运算的数据和运算结果以及一些 CPU 运行需要的信息。
本文将归纳下面几种寄存器:
目录
一 通用寄存器
二 标志寄存器
三 指令寄存器
四 段寄存器
五 控制寄存器
六 调试寄存器
七 描述符寄存器
八 任务寄存器
九 MSR寄存器
最常用的,也是最基础的有8个通用寄存器(注意一般看到的EAX、ECX也是指的这类寄存器再32位CPU上的拓展,另外AL、AH之类是指的这类寄存器的低位、高位):
寄存器 | 原文 | 解释 | 说明 |
AX | accumulator | 累加寄存器 | 通常用来执行加法,函数调用的返回值一般也放在这里面 |
CX | counter | 计数寄存器 | 通常用来作为计数器,比如for循环 |
DX | data | 数据寄存器 | 数据存取 |
BX | base | 基址寄存器 | 读写I/O端口时,edx用来存放端口号 |
SP | stack pointer | 栈指针寄存器 | 栈顶指针,指向栈的顶部 |
BP | base pointer | 基址指针寄存器 | 栈底指针,指向栈的底部,通常用ebp+偏移量的形式来定位函数存放在栈中的局部变量 |
SI | source index | 源变址寄存器 | 字符串操作时,用于存放数据源的地址 |
DI | destination index | 目标变址寄存器 | 字符串操作时,用于存放目的地址的,和esi两个经常搭配一起使用,执行字符串的复制等操作 |
标志寄存器,里面有众多标记位,记录了 CPU 执行指令过程中的一系列状态,这些标志大都由 CPU 自动设置和修改:
寄存器 | 解释 |
CF | 进位标志 |
PF | 奇偶标志 |
ZF | 零标志 |
SF | 符号标志 |
OF | 补码溢出标志 |
TF | 跟踪标志 |
IF | 中断标志 |
...... |
eip: 指令寄存器可以说是CPU中最最重要的寄存器了,它指向了下一条要执行的指令所存放的地址,CPU的工作其实就是不断取出它指向的指令,然后执行这条指令,同时指令寄存器继续指向下面一条指令,如此不断重复,这就是CPU工作的基本日常。
在 x64 架构下,32位的 eip 升级为64位的 rip寄存器。
通过引入分段的概念,将内存空间划分为不同的区域,并通过段基址+段内偏移来寻址。
段寄存器就是用来保存段基地址的。
寄存器 | 原文 | 解释 |
ES | extra segment | 附加段寄存器 |
CS | code segment | 代码段寄存器 |
SS | stack segment | 栈段寄存器 |
DS | data segment | 数据段寄存器 |
FS | segment part 2 | 无名寄存器 |
GS | segment part 3 | 无名寄存器 |
通用寄存器、段寄存器、标志寄存器、指令寄存器,这四组寄存器共同构成了一个基本的指令执行环境,一个线程的上下文也基本上就是这些寄存器,在执行线程切换的时候,就是修改它们的内容。
控制寄存器CR0,CR1(保留),CR2,CR3和CR4(64位新增CR8)决定处理器的工作模式和当前执行的任务的特性。
寄存器 | 解释 |
CR0 | 存储了CPU控制标记和工作状态,(最重要) |
CR1 | 保留未使用 |
CR2 | 页错误出现时保存导致出错的地址 |
CR3 | 存储了当前进程的虚拟地址空间的重要信息——页目录地址 |
CR4 | 也存储了CPU工作相关以及当前人任务的一些信息 |
CR8 | 64位新增扩展使用 |
这边重点关注一下CR0寄存器:
其中:
【1】PG(Paging (bit 31 of CR0)) 设置时启用分页;清除时禁用分页.当分页被禁用时,所有的线性地址都被当作物理地址处理.如果PE标志(寄存器CR0的第0位)没有被设置,PG标志就没有作用;当PE标志被清除时,设置PG标志会导致一个一般保护异常(#GP).
【2】CD(Cache Disable (bit 30 of CR0)) 当CD和NW标志清零时,处理器内部(和外部)缓存中的整个物理内存的内存位置的缓存被启用.当CD标志被设置时,缓存被限制.为了防止处理器访问和更新其缓存,CD标志必须被设置,并且缓存必须被无效化,这样就不会发生缓存命中.
【3】NW(Not Write-through (bit 29 of CR0)) 当NW和CD标志被清零时,回写(对于奔腾4,英特尔至强,P6系列和奔腾处理器)或直写(对于Intel486处理器)被启用以用于命中缓存和失效周期的写入.
【4】AM(Alignment Mask (bit 18 of CR0)) 设置时启用自动对齐检查;清除时禁用对齐检查.只有当AM标志被设置,EFLAGS寄存器中的AC标志被设置,CPL为3,并且处理器工作在受保护或虚拟8086模式下时,才会进行对齐检查.(32位下必须是4字节对齐 / 64位下必须是8字节对齐)
【5】WP(Write Protect (bit 16 of CR0)) 当设置时,禁止超级用户程序(例如特权级0的程序)写入只读页;当清除时,允许超级用户程序(例如特权级0的程序)写入只读页(无论U/S位设置如何).这个标志有利于实现UNIX等操作系统所使用的创建新进程(forking)的写时拷贝法.这个标志必须在软件设置CR4.CET之前设置,只要CR4.CET=1,就不能清除它.
【6】TS(Task Switched (bit 3 of CR0)) 任务切换标志位
【7】PE(Protection Enable (bit 0 of CR0)) 设置时启用保护模式;清除时启用实地址模式.这个标志并不直接启用分页.它只启用段级保护.要启用分页,必须同时设置PE和PG标志.
PG = 0且PE = 0 处理器工作在实地址模式下;
PG = 0且PE = 1 处理器工作在没有开启分页机制的保护模式下;
PG = 1且PE = 0 在PE没有开启的情况下 无法开启PG;
PG = 1且PE = 1 处理器工作在开启了分页机制的保护模式下;
另外,其他的控制寄存器的具体说明可以参考帖子:控制寄存器说明
在x86/x64 CPU 内部,还有一组用于支持软件调试的寄存器。
寄存器 | 解释 |
DR0-DR3 | 这是四个用于存储地址的寄存器。 |
DR4-DR5 | 这两个有点特殊,受前面提到的CR4寄存器中的标志位DE位控制,如果CR4的DE位是1,则DR4、DR5是不可访问的,访问将触发异常。如果CR4的DE位是0,则DR4和DR5将会变成DR6和DR7的别名,相当于做了一个软链接。这样做是为了将DR4、DR5保留,以便将来扩展调试功能时使用。 |
DR6 | 这个寄存器中存储了硬件断点触发后的一些状态信息。 |
DR7 | 调试控制寄存器,这里面记录了对DR0-DR3这四个寄存器中存储地址的中断方式(是对地址的读,还是写,还是执行)、数据长度(1/2/4个字节)以及作用范围等信息。 |
所谓描述符,其实就是一个数据结构,用来记录一些信息,“描述”’一个东西。把很多个描述符排列在一起,组成一个表,就成了描述符表。
描述符寄存器指向描述符表。在x86/x64系列CPU中,有三个非常重要的描述符寄存器,它们分别存储了三个地址,指向了三个非常重要的描述符表。
寄存器 | 解释 | 指向 |
GDTR | 全局描述符表寄存器 | 全局分段描述符表GDT |
LDTR | 局部描述符表寄存器 | 局部分段描述符表LDT |
IDTR | 中断描述符表寄存器 | 中断描述符表IDT |
GDTR/LDTR:指向GDT和LDT中的表项,就是段描述符,描述了一个内存分段的信息,其结构如下:
IDTR:中断描述符表寄存器,指向了中断描述符表IDT,这个表的每一项都是一个中断处理描述符,当CPU执行过程中发生了硬中断、异常、软中断时,将自动从这个表中定位对应的表项,里面记录了发生中断、异常时该去哪里执行处理函数。
任务寄存器TR,指向当前运行的任务,这是在硬件层面上,对多任务切换的支持。
从80486之后的x86架构 CPU,内部增加了一组新的寄存器,统称为 MSR 寄存器,中文直译是模型特定寄存器,意思是这些寄存器不像上面列出的寄存器是固定的,这些寄存器可能随着不同的版本有所变化。这些寄存器主要用来支持一些新的功能。
总结,以上就是全部要介绍的寄存器了,但这并不是 x86 CPU 全部所有的寄存器,除了这些,还存在 XMM、MMX、FPU 浮点数运算等其他寄存器,这边也不再赘述了。