ARMv8 x0到x30 功能解释
在ARMv8架构中,通用寄存器x0-x30(64位)或w0-w30(32位)用于数据操作和函数调用,但部分寄存器在硬件或软件层面被赋予了特殊作用。以下是它们的详细分类和约定用途:
1. 通用寄存器(无特殊约定)
• x0-x7
• 作用:函数参数传递和返回值。
• 约定:
◦ `x0`:第一个参数,也用于函数返回值。
◦ `x1-x7`:第2到第8个参数(超出部分通过栈传递)。
◦ 函数返回时,`x0`保存返回值,`x1`可能用于第二个返回值(如64位除法的高位)。
• 示例:
```asm
mov x0, #42 ; 参数传递
bl my_function ; 调用函数,返回值存回x0
```
• x8-x15
• 作用:临时寄存器(调用者保存)。
• 约定:函数内部可自由使用,但若需保留值,调用者必须在调用前保存。
• 示例:
```asm
str x8, [sp, #-16]! ; 调用者保存x8
bl other_function
ldr x8, [sp], #16 ; 恢复x8
```
• x16-x17(IP0/IP1)
• 作用:内部过程调用临时寄存器(Intra-Procedure-call)。
• 约定:链接器或PLT(过程链接表)可能使用,避免在函数间调用时使用。
• x18
• 作用:平台保留寄存器。
• 约定:某些操作系统(如Linux)用于存储当前线程的TLS(线程本地存储)指针。
2. 特殊用途寄存器
• x19-x28
• 作用:被调用者保存寄存器(Callee-saved)。
• 约定:若函数修改这些寄存器,必须保存原始值并在返回前恢复。
• 示例:
```asm
my_function:
stp x19, x20, [sp, #-16]! ; 保存x19-x20
mov x19, #100 ; 使用x19
ldp x19, x20, [sp], #16 ; 恢复
ret
```
• x29(FP, Frame Pointer)
• 作用:帧指针,指向当前栈帧的基地址。
• 约定:用于调试和栈回溯(如GCC的-fno-omit-frame-pointer)。
• 示例:
```asm
func:
stp x29, x30, [sp, #-16]! ; 保存FP和LR
mov x29, sp ; 设置新帧指针
...
ldp x29, x30, [sp], #16 ; 恢复
ret
```
• x30(LR, Link Register)
• 作用:保存函数返回地址。
• 约定:BL指令将返回地址存入LR,RET指令从LR跳转。
• 示例:
```asm
bl my_function ; 下一条指令地址存入LR
ret ; 等价于 `br lr`
```
3. 零寄存器(xzr/wzr)
• 作用:硬编码为0的只读寄存器。
• 用途:清零操作或比较。
• 示例:
cmp x0, xzr ; 检查x0是否为0
mov x1, xzr ; x1 = 0
4. 寄存器在函数调用中的角色
| 寄存器 | 角色 | 保存责任 |
|---|---|---|
x0-x7 |
参数/返回值 | 调用者无需保存 |
x8-x15 |
临时寄存器 | 调用者保存 |
x19-x28 |
被调用者保存寄存器 | 被调用者保存 |
x29 |
帧指针(FP) | 被调用者保存 |
x30 |
返回地址(LR) | 被调用者保存 |
5. 典型场景示例
场景1:函数调用
; 调用者代码
mov x0, #1 ; 第一个参数
mov x1, #2 ; 第二个参数
bl add_numbers ; 调用函数
; x0现在保存返回值
add_numbers: ; 被调用者
add x0, x0, x1 ; x0 = x0 + x1
ret ; 返回到LR地址
场景2:保存临时寄存器
caller:
str x8, [sp, #-16]! ; 调用者保存x8
bl callee
ldr x8, [sp], #16 ; 恢复x8
ret
callee:
mov x8, #100 ; 修改x8
ret
场景3:帧指针使用
func:
stp x29, x30, [sp, #-16]! ; 保存FP和LR
mov x29, sp ; 设置新帧指针
...
ldp x29, x30, [sp], #16 ; 恢复
ret
总结
• x0-x7:参数传递和返回值(易失性)。
• x8-x15:临时寄存器,调用者需保存。
• x19-x28:需被调用者保存的寄存器。
• x29(FP):栈帧跟踪,调试关键。
• x30(LR):函数返回地址。
理解这些约定对编写正确的汇编代码和调试至关重要!

浙公网安备 33010602011771号