目录
2.7 模式指定寄存器(MSRs)(Model Specific Registers)
2.10 保护模式寄存器(Protected Mode Registers)
2.10.1 全局描述符表寄存器(GDTR)(Global Descriptor Table Registers)
2.10.2 局部描述符表寄存器(LDTR)(Local Descriptor Table Registers)
2.10.3 任务寄存器(TR)(Task Registers)
2.10.4 中断描述符表寄存器(IDTR)(Interrupt Descriptor Table Registers)
1. 关于X64架构
X64结构是一个向后兼容的X86结构的扩展。它提供了一个传统的32位模式。实际上,它等同于一个X86模式,和一个新的64位模式。
2. X64架构的寄存器结构
2.1 通用目的寄存器
X64将X86的8个通用寄存器扩展为64位,增加了8个新的通用64位寄存器。64位寄存器的名称都以字母“r”开头(当然,寄存器名称不区分大小写,也可以是“R”开头),例如,eax的64位扩展寄存器命名为rax,新增加的寄存器命名从r8到r15。
每个寄存器的低32位,低16位,低8位可在操作数中直接寻址。这包括像esi这样的寄存器,其低8位在以前是不能直接寻址的。下面的列表指出了64位通用寄存器的低位名称。
64位 | 低32位 | 低16位 | 低8位 | 描述 |
rax | eax | ax | al | 累加器 |
rbx | ebx | bx | bl | 基地址 |
rcx | ecx | cx | cl | 循环记数器 |
rdx | edx | dx | dl | 数据寄存器,通常扩展A寄存器 |
rsi | esi | si | sil | 字符串操作的源索引 |
rdi | edi | di | dil | 字符串操作的目的索引 |
rbp | ebp | bp | bpl | 栈指针 |
rsp | esp | sp | spl | 基地址指针(栈帧基地址) |
r8 | r8d | r8w | r8b | 新增通用寄存器 |
r9 | r9d | r9w | r9b | 新增通用寄存器 |
r10 | r10d | r10w | r10b | 新增通用寄存器 |
r11 | r11d | r11w | r11b | 新增通用寄存器 |
r12 | r12d | r12w | r12b | 新增通用寄存器 |
r13 | r13d | r13w | r13b | 新增通用寄存器 |
r14 | r14d | r14w | r14b | 新增通用寄存器 |
r15 | r15d | r15w | r15b | 新增通用寄存器 |
注意:使用REX.W指令前缀时,不能访问AH、BH、CH 和 DH。当操作数包含 64 位寄存器时,会添加此前缀(由汇编程序自动添加)。
输出到32位子寄存器的操作数自动零扩展到整个64位寄存器(注:0扩展不影响符号位,因为有符号数最高位为1才表示负数)。输出到8位和16位字寄存器的操作数不是0扩展(这是为了兼容x86的行为)。
ax、bx、cx和dx的高 8 位仍可寻址为ah、bh、ch、dh,但不能与所有类型的操作数一起使用。
指令指针寄存器eip和标识寄存器flags已被分别扩展为64位。
2.2 浮点数寄存器
x64处理器也提供了几套浮点寄存器:
8个80位x87 寄存器。
8个64位MMX寄存器。(这些与x87 寄存器重叠)
原来的8个128位SSE寄存器增加到16个。
2.3 指令指针寄存器
指令指针寄存器rip和标识寄存器flags已被分别扩展为64位。
注意:指令指针只能用于rip相对寻址,它是在long模式中引入的。
名称 | ||
64位 | 32位 | 16位 |
RIP | EIP | IP |
2.4 段寄存器
段寄存器全部为16位长。
名称 | 描述 |
CS | 代码段 |
DS | 数据段 |
SS | 堆栈段 |
ES | 扩展段 (用于字符串操作) |
FS | 通用目的段 |
GS | 通用目的段 |
无论GDT中的段描述符是什么,CS、DS、ES 和 SS的段都被视为它们的基数为 0。FS 和 GS 例外,它们有 MSR 来改变它们的基数。
对所有段禁用限制检查。
2.5 标识寄存器
位 | 标识 | 描述 |
0 | CF | 进位标识(Carry Flag) |
1 | 1 | 保留(Reserved) |
2 | PF | 校验标识(Parity Flag) |
3 | 0 | 保留(Reserved) |
4 | AF | 辅助进位标识(Auxiliary Carry Flag) |
5 | 0 | 保留(Reserved) |
6 | ZF | 零标识(Zero Flag) |
7 | SF | 符号标识(Sign Flag) |
8 | TF | 陷阱标识(Trap Flag) |
9 | IF | 中断使能标识(Interrupt Enable Flag) |
10 | DF | 方向标识(Direction Flag) |
11 | OF | 溢出标识(Overflow Flag) |
12-13 | IOPL | I/O特权级别标识(I/O Privilege Level) |
14 | NT | 嵌入任务标识(Nested Task) |
15 | 0 | 保留(Reserved) |
16 | RF | 恢复标识(Resume Flag) |
17 | VM | 虚拟8086标识(Virtual-8086 Mode) |
18 | AC | 对齐检查/访问控制标识(Alignment Check / Access Control) |
19 | VIF | 虚拟中断标识(Virtual Interrupt Flag) |
20 | VIP | 虚拟中断挂起标识(Virtual Interrupt Pending) |
21 | ID | 身份标识(ID Flag) |
22-63 | 0 | 保留(Reserved) |
2.6 控制寄存器
2.6.1 控制寄存器CR0
位 | 标识 | 描述 |
0 | PE | 保护模式使能标识(Protected Mode Enable) |
1 | MP | 监控协处理器(Monitor Co-Processor) |
2 | EM | 枚举标识(Emulation) |
3 | TS | 任务切换标识(Task Switched) |
4 | ET | 扩展标识(Extension Type) |
5 | NE | 数字错误标识(Numeric Error) |
6-15 | 0 | 保留(Reserved) |
16 | WP | 写入保护标识(Write Protect) |
17 | 0 | 保留(Reserved) |
18 | AM | 对齐掩码标识(Alignment Mask) |
19-28 | 0 | 保留(Reserved) |
29 | NW | 非直写标识(Not-Write Through) |
30 | CD | 缓存禁用标识(Cache Disable) |
31 | PG | 分页标识(Paging) |
32-63 | 0 | 保留(Reserved) |
请注意,该寄存器是唯一可以通过 2 种方式读写的控制寄存器,而其他控制寄存器只能通过 MOV 指令访问
2.6.2 控制寄存器CR2
该控制寄存器包含触发页面错误的线性(虚拟)地址,可在页面错误的中断处理程序中使用。
2.6.3 控制寄存器CR3
位 | 标识 | 标述 | 条件 | |
0-11 | 0-2 | 0 | 保留(Reserved) | CR4.PCIDE = 0 |
3 | PWT | 页级直写(Page-Level Write Through) | ||
5 | PCD | 页级缓存禁用(Page-Level Cache Disable) | ||
5-11 | 0 | 保留(Reserved) | ||
0-11 | PCID | CR4.PCIDE = 1 | ||
12-63 | PML4的物理基地址(Physical Base Address of the PML4) |
请注意,这必须是页面对齐的
2.6.4 控制寄存器CR4
位 | 标识 | 描述 |
0 | VME | 虚拟8086模式扩展(Virtual-8086 Mode Extensions) |
1 | PVI | 保护模式虚拟中断(Protected Mode Virtual Interrupts) |
2 | TSD | 仅0环时间戳启用(Time Stamp enabled only in ring 0) |
3 | DE | 调试扩展(Debugging Extensions) |
4 | PSE | 分页扩展(Page Size Extension) |
5 | PAE | 物理地址扩展(Physical Address Extension) |
6 | MCE | 主机检查异常(Machine Check Exception) |
7 | PGE | 分页全局使能(Page Global Enable) |
8 | PCE | 性能监控计数使能(Performance Monitoring Counter Enable) |
9 | OSFXSR | 操作系统支持fxsave 和fxrstor 指令(OS support for fxsave and fxrstor instructions) |
10 | OSXMMEXCPT | 操作系统支持未屏蔽的simd浮点异常(OS Support for unmasked simd floating point exceptions) |
11 | UMIP | 用户模式指令预防(User-Mode Instruction Prevention (SGDT, SIDT, SLDT, SMSW, 和STR在用户模式是禁用的)) |
12 | 0 | 保留(Reserved) |
13 | VMXE | 虚拟机扩展使能(Virtual Machine Extensions Enable) |
14 | SMXE | 更安全的模式扩展使能(Safer Mode Extensions Enable) |
15 | 0 | 保留(Reserved) |
17 | PCIDE | PCID 使能PCID Enable) |
18 | OSXSAVE | XSAVE 和处理器扩展状态使能(XSAVE And Processor Extended States Enable) |
19 | 0 | 保留(Reserved) |
20 | SMEP | 监督模式执行保护使能(Supervisor Mode Executions Protection Enable) |
21 | SMAP | 监督模式访问保护使能(Supervisor Mode Access Protection Enable) |
22 | PKE | 用户模式分页使能保护密钥(Enable protection keys for user-mode pages) |
23 | CET | 控制流执行技术使能(Enable Control-flow Enforcement Technology) |
24 | PKS | 监督模式分页使能保护密钥(Enable protection keys for supervisor-mode pages) |
25-63 | 0 | 保留(Reserved) |
2.6.5 控制寄存器CR8
CR8是64位模式下的一个使用REX前缀可访问的新的寄存器。CR8用于优秀处理外部中断,并且被称为是任务优先级寄存器(Task-priority register,简记为TPR。AMD64架构允许软件定义最多15个外部中断优先类。优先分类标号从1到15,其中,1是最低级优先级分类,15是最高优先级分类。CR8使用低序4位来指定任务优先级,而将其余60位保留且必须都置为0。系统软件可以使用 TPR 寄存器临时阻止低优先级中断去中断高优先级任务。这是通过将对应的要被阻止的最高优先级中断的值载入TPR来达成的。例如,将一个值9(对应的二进制是1001)载入TPR屏蔽所有中断优先级小于等于9的所有中断,而允许中断优先级大于等于10的中断被识别。将0载入TPR则允许所有外部中断。将15(对应二进制1111)载入TPR则禁止所有外部中断。复位时,TPR被置为0。
位 | 目的 |
0-3 | 优先极 |
4-63 | 保留 |
2.6.6 控制寄存器CR1,CR5-7, CR9-15
保留,当试图访问这些寄存器的时候,CPU将抛出一个#ud异常。
2.7 模式指定寄存器(MSRs)(Model Specific Registers)
2.7.1 IA32 EFER寄存器
扩展特征使能寄存器(EFER)(Extend Feature Enable Register)是AMD K6处理器中加入的模式指定寄存器,允许启用SYSCALL/SYSRET指令,而后是为了进入和退出长模式(long mode),该寄存器在AMD64中成为体系结构,被已被Intel采用。它的它的 MSR 编号是 0xC0000080。
位 | 标识 | 描述 |
0 | SCE | 系统调用扩展(System Call Extensions) |
1-7 | 0 | 保留 |
8 | LME | 长模式使能(Long Mode Enable) |
10 | LMA | 长模式激活(Long Mode Active) |
11 | NXE | 非执行使能(No-Execute Enable) |
12 | SVME | 安全虚拟机使能(Secure Virtual Machine Enable) |
13 | LMSLE | 长模式段限制使能(Long Mode Segment Limit Enable) |
14 | FFXSR | 快速FXSAVE/ FXRSTOR( Fast FXSAVE/FXRSTOR) |
15 | TCE | 翻译缓存扩展(Translation Cache Extension) |
16-63 | 0 | 保留 |
2.7.2 FS.base, GS.base
地址为 0xC0000100(FS)和 0xC0000101(GS)的 MSR 包含 FS 和 GS 段寄存器的基地址。 这些寄存器通常用于用户代码中的线程指针和内核代码中的 CPU 本地指针。 安全地包含任何内容,因为使用段不会赋予用户代码额外的权限。
在较新的 CPU 中,这些寄存器也可以使用任何特权级别的 WRFSBASE 和 WRGSBASE 指令编写。
2.7.3 内核GSBase
MSR地址为0xC0000102。 基本上是一个在执行swapgs指令后与 GS.base 交换的缓冲区。 通常用于分隔内核和用户使用的GS寄存器。
2.8 调试寄存器(Debug Registers)
2.8.1 DR0-DR3寄存器
包括最多多4个断点的线性地址。假如启用了分页机制,它们将被转换为物理地址。
2.8.2 DR6寄存器
允许调试器确定那一个调试条件触发了调试。当启用了调试异常,在进入调试异常处理之前,低次序的0-3位将被设置。
2.8.3 DR7寄存器
位 | 描述 |
0 | 局部DR0断点(Local DR0 Breakpoint) |
1 | 全局DR0断点(Global DR0 Breakpoint) |
2 | 局部DR1断点(Local DR1 Breakpoint) |
3 | 全局DR1断点(Global DR1 Breakpoint) |
4 | 局部DR2断点(Local DR2 Breakpoint) |
5 | 全局DR2断点(Global DR2 Breakpoint) |
6 | 局部DR3断点(Local DR3 Breakpoint) |
7 | 全局DR3断点(Global DR3 Breakpoint) |
16-17 | DR0触发条件(Conditions for DR0) |
18-19 | DR0断点大小(Size of DR0 Breakpoint) |
20-21 | DR1触发条件(Conditions for DR1) |
22-23 | DR1断点大小(Size of DR1 Breakpoint) |
24-25 | DR2触发条件(Conditions for DR2) |
26-27 | DR2断点大小(Size of DR2 Breakpoint) |
28-29 | DR3触发条件(Conditions for DR3) |
30-31 | DR3断点大小(Size of DR3 Breakpoint) |
局部断点位在硬件任务切换时停用,而全局则不会。 00b 条件表示执行中断,01b 表示写观察点,11b 表示 R/W 观察点。 10b 为 I/O R/W 保留(不支持)。
2.9 测试寄存器(Test Registers)
名称 | 说明 |
TR3 - TR5 | 无证(Undocumented) |
TR6 | 测试命令寄存器(Test Command Register) |
TR7 | 测试数据寄存器(Test Data Register) |
2.10 保护模式寄存器(Protected Mode Registers)
2.10.1 全局描述符表寄存器(GDTR)(Global Descriptor Table Registers)
操作数大小 | 标识 | 描述 | |
64位 | 32位 | ||
0-15位 | Limit | GDT大小 | |
16-79位 | 16-47位 | Base | GDT起始地址 |
2.10.2 局部描述符表寄存器(LDTR)(Local Descriptor Table Registers)
存储局部描述符表的段选择子。
2.10.3 任务寄存器(TR)(Task Registers)
存储任务状态段TSS(Task Status Segment) 段选择子。
2.10.4 中断描述符表寄存器(IDTR)(Interrupt Descriptor Table Registers)
操作数大小 | 标识符 | 描述 | |
64-bit | 32-bit | ||
0-15位 | Limit | IDT大小 | |
16-79位 | 16-47位 | Base | IDT起始地址 |
3. X64架构调用约定
与X86调用约定不同,C/C++编译器在64位平台上仅支持一种调用约定。这种调用约定利用了64位平台上可获得的新增寄存器数量:
(1)前4个整数或者指针参数依次通过rcx,rdx,r8和r9传递。
(2)前4个浮点参数通过通过前4个SSE寄存器xmm0-xmm3传递。
(3)由调用者为寄存器中的参数传递保留栈上的空间(至少在运行栈上分配32字节的阴影空间(shadow space))。被调用函数可以访问这个栈空间来,将寄存器中的内容写回栈空间。
(4) 任何多余4个参数的其它参数都使用栈来传递,并按照从左到右的次序(即,从第5个参数开始,使用栈传递参数)。
(5) 任何调用返回的整数或者指针值都放在rax寄存器中(调用完成执行返回动作时放在rax寄存器中,例如,调用ret指令时),而浮点数的返回值放在寄存器xmmO中。
(6) rax,rcx,rdx,r8-r11寄存器是易失性的(volatile)。
(7) rbx,rbp,rdi,rsi,r12-r15 寄存器是非易失性的(nonvolatile)。
这些调用约定与C++非类似:指针默认作为第一个参数传递,其它三个参数利用余下的3个寄存器,多出4个的参数则使用栈传递。
(8) call指令从rsp(堆栈指针)寄存器中减去 8,表示空出8字节的栈空间用于存放返回值,因为地址是64位长(8字节)。
(9) 当调用一个子过程(subroutine)的时候,规定指令指针(rip)必须在一个16字节的边界对齐(也就是128位,即16的倍数,这可能是在设计CPU时综合性能考量)。call指令将一个8字节的返回地址压入堆栈中,因此,调用程序必须从堆栈指针中减去8,除了32,它已经减去了阴影空间。
4. X64架构寻址模式
X64架构的寻址模式与X86类似,但不完全等同:
(1)引用 64 位寄存器的指令以 64 位精度自动执行。例如:
mov rax, [rbx] 将rbx中的8个字节移动动rax中,8个字节即64位。
(2)64位立即常量或常量地址已加入了一种特殊形式的 mov 指令。 对于其他所有指令,立即常量或常量地址仍然是 32 位。
(3)X64架构提供了一种新的rip相对寻址模式(rip-relative),引用单常量地址的指令被编码为基于rip的偏移量(offsets)。例如:
mov rax, [addr] 指令移动以 addr + rip为起始地址的8字节内容到rax寄存器。
(4)隐式引用指令指针和堆栈指针的指令(例如 jmp、call、push 和 pop)将它们视为 X64 上的 64 位寄存器。
参考资料:
Intel和AMD官方文档
微软开发文档:x64 Architecture - Windows drivers | Microsoft Docs
其它网络资源: