【ARM-day03】
压栈:
stmfd sp!, {r0-r12, lr} ; 最常见的写法,保存寄存器并更新SP
其核心动作是:按寄存器编号升序存储数据到内存(地址递增),然后递减栈指针 SP
STMFD
最典型的用途是在一个函数的开头,用于保存调用者(父函数)可能还在使用的寄存器(称为“现场保护”或“保存上下文”),以便当前函数(子函数)可以自由使用这些寄存器,并在返回前恢复它们。sp!
:指定基址寄存器是栈指针SP
,并且!
表示在存储操作完成后要回写更新后的基址寄存器值(即执行SP = SP - 4 * N
)。{r0-r3, r12, lr}
:指定要存储的寄存器列表。寄存器之间用逗号分隔,连续的寄存器可以用-
表示范围。lr
(Link Register) 通常保存着函数的返回地址,保存它是为了在函数内部可能调用其他函数(会覆盖lr
)后,能正确返回到父函数。
出栈:
LDMFD
是与 STMFD
配对的数据块加载指令,主要用于函数结束时从栈上恢复之前保存的寄存器状态(即“出栈”操作)。
LDMFD
指令的含义是:从内存中加载多个寄存器的值,操作方式符合“满递减栈”的规则。
ldmfd sp!, {r0-r12, pc} ; 最常见的写法,恢复寄存器、更新SP并返回
- 加载顺序: 寄存器按照列表中的编号从小到大依次加载。内存地址从低到高(栈顶向栈底方向)读取数据。
- 栈指针更新:
!
符号(或在POP
中隐含)确保了SP
在加载操作后递增(SP = SP + 4 * N
),将恢复的数据从栈中移除(弹出)。 - 函数返回: 通过将保存的返回地址(最初在
lr
中)直接加载到pc
来实现函数返回。 - 与 STMFD 对称:
LDMFD
是STMFD
的逆操作。STMFD
先存储(地址递增)后递减SP
;LDMFD
先加载(地址递增)后递增SP
。
str指令
寻址模式:
- 立即数偏移:
STR R1, [R2, #8] ; 将 R1 的值存储到地址为 (R2 + 8) 的内存中。
; R2 本身的值不变。
- 寄存器偏移
STR R1, [R2, R3] ; 将 R1 的值存储到地址为 (R2 + R3) 的内存中。
; R2 和 R3 本身的值不变。
- 前变址
STR R1, [R2, #4]! ; 先将 R2 的值更新为 R2 + 4,
; 然后将 R1 的值存储到新的 R2 指向的内存地址。
; R2 的值被修改了(加了 4)。
- 后变址(相当于c语言的*p++)
STR R1, [R2], #4 ; 先将 R1 的值存储到 R2 当前指向的内存地址,
; 然后将 R2 的值更新为 R2 + 4。
; R2 的值被修改了(加了 4)。
MRS指令
功能: 将系统寄存器的当前值读取到一个通用寄存器中。
MRS <Rd>, <system_register>
<Rd>
:目标通用寄存器(例如R0
,R1
),用于接收从系统寄存器读取的值。<system_register>
:要读取的系统寄存器名称。最常见的两个是:CPSR
(Current Program Status Register):包含当前处理器的状态信息(条件标志位、中断使能位、处理器模式位等)。SPSR
(Saved Program Status Register):在发生异常(如中断)时,会自动将CPSR
的值保存到当前模式对应的SPSR
中。用于异常返回时恢复状态。
例如:
MRS R0, CPSR ; 将当前 CPSR 的值读取到通用寄存器 R0 中
MSR指令
功能: 将一个通用寄存器或立即数的值写入到系统寄存器(或其指定的字段)。
MSR <system_register>{_<fields>}, <Op>
用途:
- 修改条件标志: 直接设置或清除
N
,Z
,C
,V
标志位(使用MSR CPSR_f, ...
)。 - 改变处理器模式: 切换到不同的特权模式(如从 User 切换到 SVC 模式调用系统调用)或返回用户模式(使用
MSR CPSR_c, ...
)。 - 使能/禁用中断: 设置
CPSR
的I
(IRQ 中断) 和F
(FIQ 中断) 位(使用MSR CPSR_c, ...
)。 - 恢复状态: 在异常处理程序(如中断服务程序)结束时,将
SPSR
的值写回CPSR
以恢复之前的处理器状态和标志(通常使用MSR CPSR_cxsf, SPSR
或等效操作)。 - 上下文切换: 在操作系统加载新任务时,将其保存的
CPSR
值写回。
MRS
用于读取系统寄存器(主要是 CPSR
/SPSR
)的值到通用寄存器。MSR
用于写入通用寄存器或立即数的值到系统寄存器(或其指定字段)。
arm内核中有几种异常,分别是什么,会使内核切换到那种工作模式?
ARM 内核设计里有 7 种异常类型,对应不同的触发场景,每种异常都会让内核切换到特定的工作模式:
-
Reset(复位异常)
-
触发条件:芯片上电或复位信号有效。
-
切换模式:进入 Supervisor 模式(SVC)。
-
-
Undefined Instruction(未定义指令异常)
-
触发条件:CPU 取到无法识别或不支持的指令。
-
切换模式:进入 Undefined 模式(UND)。
-
-
Software Interrupt(软中断 SWI)
-
触发条件:程序执行
SWI
指令。 -
切换模式:进入 Supervisor 模式(SVC)。
-
-
Prefetch Abort(预取中止异常)
-
触发条件:取指阶段访问到无效指令地址或存储器异常。
-
切换模式:进入 Abort 模式(ABT)。
-
-
Data Abort(数据中止异常)
-
触发条件:执行访存指令时访问到非法或受保护的地址。
-
切换模式:进入 Abort 模式(ABT)。
-
-
IRQ(普通中断请求)
-
触发条件:外设产生的普通中断信号。
-
切换模式:进入 IRQ 模式。
-
-
FIQ(快速中断请求)
-
触发条件:外设产生的快速中断信号(优先级比 IRQ 高)。
-
切换模式:进入 FIQ 模式。
-