x86 架构寄存器

最后更新: 2024-07-28 09:42:04 +0800 +0800
tags: X86 | X86-64 | Assembly
原文以英文撰写。您正在阅读AI翻译版本。

x86 架构寄存器保存程序员可见的整数、控制、状态、地址转换、调试、浮点和向量状态。 宽度和可用性取决于执行模式及启用的扩展。调用约定会为其中一部分寄存器分配软件角色, 但不会改变其架构行为。

通用寄存器和子寄存器 #

IA-32 暴露 EAX、EBX、ECX、EDX、ESI、EDI、EBP 和 ESP。x86-64 将它们扩展为 RAX 至 RSP,并增加 R8 至 R15。子寄存器命名同一架构寄存器的不同部分:

  • RAX 为 64 位,EAX 是其低 32 位,AX 是低 16 位,AL 和 AH 命名 AX 的低字节和高字节。
  • 在 64 位模式中写入 32 位目标会清除高 32 位。
  • 写入 16 位或 8 位目标会保留其他位。
  • REX 前缀使 SPL、BPL、SIL 和 DIL 可用,但会阻止指令编码 AH、BH、CH 或 DH。

RIP 是 64 位指令指针,32 位代码使用 EIP。普通 MOV 不能写入它;分支、调用、返回、异常和中断返回会改变控制流。RSP 是当前栈指针。

函数边界处的寄存器用途来自 ABI。System V AMD64 使用 RDI、RSI、RDX、RCX、R8 和 R9 传递初始整数参数,而 Microsoft x64 使用 RCX、RDX、R8 和 R9。当 ABI 和展开信息允许时,RBP 可以作为帧指针,也可以作为通用寄存器。Linux 系统调用使用另一种寄存器约定,因此不能混淆函数调用和内核入口的角色。

RFLAGS #

RFLAGS 扩展了较旧的 EFLAGS 和 FLAGS 寄存器。常见的算术状态位包括:

标志含义
CF无符号进位或借位
PF结果低字节的偶校验
AF传统十进制操作的辅助进位
ZF零结果
SF结果的符号位
OF有符号溢出

控制和系统位包括:

  • DF,为字符串指令选择索引递增或递减。
  • IF,根据特权和虚拟化规则控制可屏蔽中断的传递。
  • TF,请求在一条指令后触发调试陷阱。
  • IOPL,参与端口 I/O 和选定的中断控制检查。
  • NT,在传统保护模式中记录嵌套硬件任务状态。
  • RF、VM、AC、VIF、VIP 和 ID,其含义取决于模式和启用的功能。

指令定义它们写入、保留或置为未定义的标志。PUSHF/POPF、中断进入和返回操作也会应用特权限制;软件不能假设当前 CPL 下的每个可见位都能被更改。

段寄存器和隐藏描述符缓存 #

CS、SS、DS、ES、FS 和 GS 具有可见选择子和隐藏的描述符状态。在保护模式中加载选择子会获取描述符,并缓存其基址、界限、类型和访问权限。编辑描述符表不会更新已经加载的缓存。

在 64 位模式中,普通地址生成会忽略 CS、SS、DS 和 ES 的基址和界限。FS 和 GS 保留通过模型特定寄存器或受支持指令设置的 64 位基址,操作系统使用它们保存线程本地和每 CPU 数据。在架构规定的范围内,选择子和描述符规则仍然适用。

GDTR 和 IDTR 保存全局描述符表和中断描述符表的线性基址及字节界限。LDTR 和 TR 保存局部描述符表及任务状态段的选择子和缓存描述符。LGDT、LIDT、LLDT 和 LTR 会在特权检查下建立这些值。x86 保护模式和特权描述了表格式和转换。

控制和系统寄存器 #

控制寄存器配置执行和地址转换:

  • CR0 包含保护模式、分页、写保护、缓存和选定的数值状态控制。
  • CR2 接收与页错误相关的线性地址。
  • CR3 选择分页结构根,并在启用 PCID 时可以携带进程上下文标识符。
  • CR4 在支持时启用 PAE、全局页、操作系统管理的 SIMD 状态、SMEP、SMAP 和保护密钥等架构功能。
  • CR8 在 64 位模式下控制外部中断的任务优先级阈值。

模型特定寄存器(MSR)提供其他控制,包括用于长模式和不可执行启用的 EFER、系统调用目标、FS/GS 基址、内存类型和性能监控。确切的 MSR 集合取决于模型,必须从厂商文档中发现或选择。RDMSR 和 WRMSR 是特权指令。

调试寄存器 #

DR0 至 DR3 保存线性断点地址。DR7 启用断点,并选择执行、写入或数据访问条件以及支持的长度。DR6 报告调试异常发生的原因。保留编码和通用检测行为特定于架构,因此调试器或内核必须在恢复不可信调试状态之前清理值。

软件断点会将指令字节替换为 INT3。硬件调试寄存器避免更改代码,但只提供少量槽位。调试异常会与单步执行、任务切换、虚拟化和事务执行交互。

x87、MMX、SIMD 和掩码寄存器 #

x87 浮点单元暴露一个八项寄存器栈,以及控制、状态、标签、指令指针和数据指针状态。 MMX 别名引用 x87 寄存器的低 64 位存储,这正是传统 MMX 代码在返回 x87 操作前执行 EMMS 的原因。

SSE 引入 XMM 寄存器。AVX 将其低位存储扩展到 YMM;AVX-512 将其扩展到 ZMM, 并增加 K0 至 K7 的操作掩码寄存器。架构和模式决定可见寄存器数量。写入传统 SSE 目标可以保留高位向量状态,而 VEX 和 EVEX 编码的操作会应用其规定的高位清除行为。因此, 混用这些形式可能在选定处理器上产生依赖或转换开销。

MXCSR 控制 SIMD 浮点舍入、异常屏蔽、状态和非规格化处理。操作掩码寄存器控制 AVX-512 的逐通道合并或清零。其他扩展可能增加原始浮点保存格式未表示的 tile 或其他状态。

扩展状态管理 #

FXSAVE 和 FXRSTOR 覆盖 x87、MMX、SSE 及相关控制状态。XSAVE 系列使用 XCR0、 CPUID 枚举和组件位图管理可扩展状态区域。管理态组件可以使用额外的控制和保存机制。

操作系统必须只启用能够安全初始化、保存、恢复和暴露的状态组件。用户软件在执行 AVX 或更高版本指令前,会同时检查处理器支持和操作系统启用状态。上下文切换策略可以急切保存 状态,也可以使用受支持的优化,但每个线程可见的架构状态必须保持隔离。

评论

在 GitHub 上阅读或评论(发表评论需要登录)