ARM中的汇编指令:MRS和MSR
在基于ARM Cortex-M (以及一些Cortex-A/R)系列处理器的开发中,MRS和MSR 是指令集中的一对核心汇编指令,用于在处理器状态寄存器 和通用寄存器之间传输数据。
它们是直接与CPU核心对话、进行最底层硬件控制的钥匙。
核心定义
-
MRS: Move to Register from System register
- 含义: 将系统寄存器 的值读取 到一个通用寄存器(如 R0, R1)中。
- 操作:
通用寄存器 ← 系统寄存器 - 目的: 读取CPU的当前状态和配置。
-
MSR: Move to System register from Register
- 含义: 将一个通用寄存器 的值写入 到系统寄存器中。
- 操作:
系统寄存器 ← 通用寄存器 - 目的: 修改/配置CPU的状态和行为。
关键概念解释
- 系统寄存器:
- 这是CPU内部一系列特殊的寄存器,用于控制和反映处理器的核心状态。
- 它们不能 像通用寄存器那样直接用
MOV指令访问,必须通过MRS/MSR这对专用指令来操作。 - 常见的系统寄存器包括:
- PSR (Program Status Register): 程序状态寄存器,包含条件标志位(N, Z, C, V)、中断状态等。
- CONTROL: 控制寄存器,用于定义特权级别(线程模式/Handler模式)、栈指针选择等。
- PRIMASK, FAULTMASK, BASEPRI: 中断屏蔽寄存器,用于全局或分级使能/禁止中断。
- APSR (Application PSR): PSR的一部分,仅包含条件标志位。
为什么它们在嵌入式中如此重要?
因为嵌入式开发(尤其是底层驱动、RTOS、启动代码)经常需要直接操纵硬件,而MRS/MSR是实现这种精确控制的基础:
-
中断管理:
-
在进入一个关键代码段前,需要关闭全局中断以防止被打断。
assemblyMRS R0, PRIMASK ; 读取当前中断使能状态到R0,用于后续恢复 MSR PRIMASK, #1 ; 将1写入PRIMASK,禁止所有可屏蔽中断(关中断) ; ... 执行关键代码 ... MSR PRIMASK, R0 ; 将之前保存的状态写回,恢复中断设置(开中断) -
-
上下文切换(RTOS核心):
- 当操作系统从一个任务切换到另一个任务时,必须保存当前任务的CPU状态(所有寄存器,包括系统寄存器),然后恢复下一个任务的状态。
MRS用于将PSR、CONTROL等寄存器的值保存到任务栈中。MSR用于从任务栈中恢复这些值。
-
模式切换:
- 在ARM处理器中,从用户级线程模式切换到特权级的Handler模式(例如响应中断),需要操作
CONTROL等寄存器,这离不开MSR。
- 在ARM处理器中,从用户级线程模式切换到特权级的Handler模式(例如响应中断),需要操作
-
读取状态:
-
判断上一次运算的结果(是正、负、零还是溢出)需要读取
APSR中的标志位。
assemblyMRS R0, APSR ; 将条件标志位读入R0 ANDS R0, R0, #(1 << 29) ; 检查V(溢出)标志位 BNE overflow_handler ; 如果溢出,跳转到处理程序 -
在C代码中的使用
在编写嵌入式C代码时,你通常不会直接写汇编。编译器提供了内联汇编 或内在函数来封装这些指令。
例如,在ARM CMSIS(Cortex Microcontroller Software Interface Standard)中:
c
// 使用CMSIS intrinsic functions
#include "cmsis_compiler.h"
void critical_function(void) {
uint32_t primask_state;
primask_state = __get_PRIMASK(); // 内部使用 MRS 指令
__disable_irq(); // 内部使用 MSR 指令设置PRIMASK
// ... 关键代码 ...
if (!primask_state) {
__enable_irq(); // 内部使用 MSR 指令清除PRIMASK
}
}
总结
在嵌入式系统(ARM架构)中:
| 指令 | 方向 | 功能 | 类比 |
|---|---|---|---|
MRS |
系统寄存器 → 通用寄存器 | "读取状态" | 像查看汽车的仪表盘(车速、转速)。 |
MSR |
通用寄存器 → 系统寄存器 | "改变配置" | 像操作汽车的控制杆(换挡、打转向灯)。 |
它们是嵌入式开发者进行最底层、最精确的处理器控制和状态管理的基石指令,是理解中断、任务调度、处理器模式等核心概念的关键。