3.2 寄存器
x86-64 架构提供了 16 个通用寄存器,每个 64 位宽。寄存器是 CPU 内部最快的存储层次,在指令执行中扮演核心角色。
16 个通用寄存器
| 64位 | 32位 | 16位 | 8位 | 用途 |
|---|---|---|---|---|
%rax | %eax | %ax | %al | 返回值 |
%rbx | %ebx | %bx | %bl | 被调用者保存 |
%rcx | %ecx | %cx | %cl | 第 4 个参数 |
%rdx | %edx | %dx | %dl | 第 3 个参数 |
%rsi | %esi | %si | %sil | 第 2 个参数 |
%rdi | %edi | %di | %dil | 第 1 个参数 |
%rbp | %ebp | %bp | %bpl | 基址指针(被调用者保存) |
%rsp | %esp | %sp | %spl | 栈指针(特殊管理) |
%r8 | %r8d | %r8w | %r8b | 第 5 个参数 |
%r9 | %r9d | %r9w | %r9b | 第 6 个参数 |
%r10 | %r10d | %r10w | %r10b | 调用者保存 |
%r11 | %r11d | %r11w | %r11b | 调用者保存 |
%r12 | %r12d | %r12w | %r12b | 被调用者保存 |
%r13 | %r13d | %r13w | %r13b | 被调用者保存 |
%r14 | %r14d | %r14w | %r14b | 被调用者保存 |
%r15 | %r15d | %r15w | %r15b | 被调用者保存 |
寄存器的子集访问
x86-64 兼容早期 x86 架构,允许通过不同名称访问同一个寄存器的低字节部分:
# 以下操作都影响 %rax,但操作宽度不同
movq $0x123456789ABCDEF0, %rax # 写入全部 64 位
movl $0xFFFFFFFF, %eax # 写入低 32 位,高 32 位清零!
movw $0xFFFF, %ax # 写入低 16 位,不影响高位
movb $0xFF, %al # 写入低 8 位,不影响高位重要:
movl写入 32 位寄存器时,会自动将高 32 位清零(%eax→%rax高 32 位置零)。这是 x86-64 的约定行为。
寄存器的核心用途
函数参数传递
前 6 个整数/指针参数按顺序通过寄存器传递:
- 第一个参数 →
%rdi - 第二个参数 →
%rsi - 第三个参数 →
%rdx - 第四个参数 →
%rcx - 第五个参数 →
%r8 - 第六个参数 →
%r9
栈管理
%rsp:始终指向当前栈帧的栈顶,由 push/pop/call/ret 指令隐式修改%rbp:可选作为栈帧基址指针,用于访问局部变量和参数
函数返回值
%rax:保存函数返回值%rdx:在某些返回 128 位结果的场景中与%rax配合使用
寄存器保存约定
详见 :
- 调用者保存(caller-saved):
%rax,%rcx,%rdx,%rsi,%rdi,%r8~%r11- 调用者若需在函数调用后保留其值,必须在
call之前自行保存
- 调用者若需在函数调用后保留其值,必须在
- 被调用者保存(callee-saved):
%rbx,%rbp,%r12~%r15- 被调函数若使用这些寄存器,必须在返回 之前 恢复原始值
寄存器 vs 内存
| 特性 | 寄存器 | 内存 |
|---|---|---|
| 访问延迟 | ~0.5-1 ns | ~50-100 ns (主存) |
| 容量 | 16 × 8 = 128 字节 | GB 级别 |
| 地址 | 无地址(通过名称访问) | 有地址(指针访问) |
编译器会尽可能将频繁使用的变量分配到寄存器中,称为寄存器分配(register allocation)。
相关笔记
-
- 寄存器作为操作数的用法
-
- 参数在寄存器中的传递规则
-
- 寄存器保存约定详解
-
- %rsp 与栈的关系