You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何入栈xPSR?ARM汇编条件执行结果保留问题咨询

解决ARM汇编中保存xPSR的问题

你遇到的问题很典型——ARM的xPSR属于特殊功能寄存器,不能像R0-R15这类通用寄存器一样直接用PUSH/POP操作,这就是汇编器报错“bad register symbol”的原因。不过ARM架构提供了专门的指令来读写特殊寄存器,完美解决你的需求。

核心思路:用MRS/MSR中转通用寄存器

要保存xPSR的状态(其实你只需要CMP后的条件标志位,也就是APSR里的NZCV位),必须先把特殊寄存器的值转到通用寄存器,再保存到栈;恢复时反向操作即可。

修改后的代码示例

这里以保存APSR(xPSR中负责条件标志的部分)为例,比保存整个xPSR更安全,避免干扰其他状态位:

CMP R1, R2
; 保存条件标志位到栈
MRS R3, APSR       ; 将APSR(含NZCV标志)的值读到R3
PUSH {R3}          ; 把R3压栈保存

BLEQ SUBROUTINE1   ; 调用子程序,即使它修改了PSR也没关系

; 恢复之前的条件标志位
POP {R3}           ; 从栈中恢复R3的值
MSR APSR_nzcvq, R3 ; 只把NZCV等标志位写回APSR,不修改其他状态

ADDEQ R4, #5       ; 现在这条指令会正确依赖最初CMP R1,R2的结果

细节说明

  1. 为什么选APSR而非xPSR?
    xPSR是APSR(应用状态寄存器)、IPSR(中断状态寄存器)、EPSR(执行状态寄存器)的整合体。你只需要CMP后的条件判断标志(Z位是否为1),所以直接操作APSR的nzcvq域(对应负、零、进位、溢出标志)就足够,避免误改中断/执行状态。

  2. 寄存器选择的注意事项
    示例中用了R3,如果你遵循ARM的ATPCS调用规范,R0-R3属于调用者保存寄存器——子程序可能会修改它们,但我们在调用前已经把R3压栈,所以不会有问题。你也可以用其他不被子程序破坏的寄存器(比如R12,即IP寄存器),只要确保栈操作对应就行。

  3. 特权级限制(如果有)
    如果你的代码运行在用户模式下,直接写整个xPSR会被拒绝,但写APSR的nzcvq域是允许的,这也是我们推荐只恢复标志位的另一个原因。

这样修改后,SUBROUTINE1对PSR的修改就不会影响ADDEQ的执行条件了。

内容的提问来源于stack exchange,提问作者muyustan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:25:24