ARM 汇编指令:ERET
本文来自于我关于 ARM 汇编指令系列文章。欢迎阅读、点评与交流~
1、汇编指令在不同架构中的联系与区别
2、ARM 汇编指令:MOV
3、ARM 汇编指令:LDR
4、ARM 汇编指令:STR
5、ARM 汇编指令:MRS 和 MSR
6、ARM 汇编指令:ORRS
7、ARM 汇编指令:BEQ
8、ARM 汇编指令:TST
9、ARM 汇编指令:B
10、ARM 汇编指令:BX
11、ARM 汇编指令:ERET
ERET 是 ARM 架构中一个非常重要的特权指令,全称是 Exception Return。它用于从异常(或中断)处理程序返回到发生异常之前的状态。
主要功能和作用
- 从异常返回 :当处理器处理完一个异常(如 IRQ、FIQ、SVC、Data Abort 等)后,需要使用
ERET指令返回到被异常打断的程序。 - 恢复处理器状态:它不仅仅是一条简单的跳转指令,它会执行一系列关键操作来完全恢复异常发生前的上下文。
执行的操作
ERET 指令会原子性地执行以下操作:
- 从
ELR_ELx恢复PC:将异常链接寄存器 中的地址加载到程序计数器 中。这个地址就是在异常发生时,处理器自动保存的、本应执行的下一条指令的地址(即返回地址)。x代表当前的异常级别(如 EL1, EL2, EL3)。
- 从
SPSR_ELx恢复PSTATE:将保存的程序状态寄存器 中的值恢复到当前程序状态寄存器。这包括:- 恢复条件标志位(N, Z, C, V)。
- 恢复中断使能位。
- 恢复处理器运行状态(如从 AArch64 的 EL1 回到 EL0)。
- 恢复执行状态(如果支持 AArch32,则可能从 AArch64 状态切换回 AArch32 状态)。
使用场景和示例
ERET 几乎总是出现在操作系统内核或固件的异常/中断处理程序的末尾。
一个简化的 AArch64 中断处理流程示例:
assembly
// 假设当前处于 EL1(内核态),处理一个来自 EL0(用户态)的同步异常或中断
my_exception_handler:
// 1. 保存被中断现场的通用寄存器(通常压入栈)
STP X0, X1, [SP, #-16]!
// ... 保存其他需要的寄存器
// 2. 处理异常(例如,系统调用、页面故障等)
BL do_handle_exception
// 3. 恢复之前保存的通用寄存器
LDP X0, X1, [SP], #16
// ... 恢复其他寄存器
// 4. 使用 ERET 返回到被中断的 EL0 程序
ERET // 关键步骤:原子性地跳转到 ELR_EL1 的地址,并恢复 SPSR_EL1 的状态
重要细节
- 特权指令 :
ERET只能在异常级别 EL1 及以上执行,在非特权级别(EL0)执行会产生异常。 - 寄存器依赖 :它的行为完全由当前异常级别的
ELR_ELx和SPSR_ELx系统寄存器决定。在调用ERET之前,必须确保这两个寄存器已被正确设置。- 对于某些可重入的异常,在异常处理程序中可能会修改
ELR_ELx(例如,实现信号处理或修改返回地址)。
- 对于某些可重入的异常,在异常处理程序中可能会修改
- 原子性:恢复 PC 和 PSTATE 的操作是原子的,这对于保证处理器状态的一致性至关重要。
- 模式切换 :如果
SPSR_ELx中的状态指示了不同的执行状态或异常级别,ERET会执行相应的模式切换。例如,从 AArch64 的 EL1 内核态返回到 AArch32 的 EL0 用户态。
相关系统寄存器
ELR_ELx:保存着异常返回地址。SPSR_ELx:保存着异常发生时处理器的状态。
与普通返回指令的区别
RET:用于从普通子程序调用返回。它只是从链接寄存器LR中加载地址到PC,不涉及处理器状态(PSTATE)或异常级别的更改。ERET:用于从异常/中断返回。它会恢复PC和完整的处理器状态/特权级别,是用于上下文切换的核心指令。
总结来说,ERET 是 ARM 架构中用于退出异常或中断、并恢复之前执行环境的专用指令,是操作系统实现特权级别切换和异常处理的基础。