arm v8r中自动设置CPSR寄存器中的条件标志位的汇编指令
好的,这是一个非常专业且深入的问题,涉及到 ARM 架构中条件标志位设置的细节。
在 ARM v8-R 架构(以及其前身 ARMv7-A/R)中,其 A-profile 和 R-profile 保留了经典的 APSR/CPSR 寄存器。有一大类算术和逻辑指令,即使不在指令助记符中加上 S 后缀(如 ADDS),它们也会自动设置条件标志位(N, Z, C, V)。
这些指令的核心特征是:它们的主要目的就是进行比较和测试,而不是为了产生一个存储结果。因此,设置标志位是它们存在的唯一意义。
以下是这些会自动设置条件标志位的指令类别和具体示例:
1. 比较指令
这些指令执行减法操作来比较两个数,但不存储结果,只根据结果设置标志位。
- 
CMP Rn, <Op2>(Compare)- 执行操作:
APSR flags = SetFrom(Rn - Op2) - 这是最常用的比较指令。
Op2可以是一个寄存器或立即数。 - 示例:
CMP R0, R1/CMP R0, #10 
 - 执行操作:
 - 
CMN Rn, <Op2>(Compare Negative)- 执行操作:
APSR flags = SetFrom(Rn + Op2) - 实际上是与一个负数进行比较,用于快速判断 
Rn是否等于-Op2。 - 示例:
CMN R0, #1// 判断 R0 是否等于 -1 
 - 执行操作:
 
2. 测试指令
这些指令执行逻辑“与”操作来测试位,但不存储结果,只根据结果设置标志位。
- 
TST Rn, <Op2>(Test)- 执行操作:
APSR flags = SetFrom(Rn & Op2) - 用于测试 
Rn中的某些位是否被设置(非零)。通常后跟BNE(位非零则跳转)或BEQ(位全零则跳转)指令。 - 示例:
TST R0, #0x80// 测试 R0 的第 7 位是否为 1 
 - 执行操作:
 - 
TEQ Rn, <Op2>(Test Equivalence)- 执行操作:
APSR flags = SetFrom(Rn EOR Op2) - 用于测试两个数是否相等,而不影响 Carry 标志。它比 
CMP更适用于测试逻辑相等(尤其是当Op2是一个立即数掩码时)。 - 示例:
TEQ R0, R1// 如果 R0 == R1,则 Z 标志置位 
 - 执行操作:
 
3. 直接操作标志位的指令
这些指令的唯一功能就是直接修改标志位。
MSR APSR_nzcvq, <Op>- 显式地将通用寄存器的内容写入 APSR 的标志位域。这是直接设置,而不是“根据运算结果”设置,但效果一样。
 
MRS Rd, APSR- 将 APSR 的状态读入通用寄存器。
 
总结与对比
| 指令 | 操作 | 是否存储结果 | 主要目的 | 
|---|---|---|---|
CMP Rn, Op2 | 
Rn - Op2 | 
否 | 比较大小 | 
CMN Rn, Op2 | 
Rn + Op2 | 
否 | 比较负值 | 
TST Rn, Op2 | 
Rn & Op2 | 
否 | 测试位 | 
TEQ Rn, Op2 | 
Rn EOR Op2 | 
否 | 测试相等 | 
ADDS Rd, Rn, Op2 | 
Rd = Rn + Op2 | 
是 | 加法并设置标志 (需要 S 后缀) | 
SUBS Rd, Rn, Op2 | 
Rd = Rn - Op2 | 
是 | 减法并设置标志 (需要 S 后缀) | 
关键结论:
对于 v8-R 架构,所有不产生目标寄存器结果的算术/逻辑指令(如 CMP, CMN, TST, TEQ),其存在的唯一目的就是设置条件标志位,因此无需也不允许使用 S 后缀。它们总是会更新 CPSR/APSR 中的条件标志。
而对于会产生结果的指令(如 ADD, SUB, AND, ORR 等),如果你想让它设置条件标志,必须显式地加上 S 后缀(例如 ADDS, SUBS)。如果不加 S,则不会更新条件标志。
这种设计是 ARM 指令集一个非常清晰和一致的特点。
                    
                
                
            
        
浙公网安备 33010602011771号