在ARM模式下,任何一条数据处理指令可以选择是否根据操作的结果来更新CPSR寄存器中的ALU状态标志位。在数据处理指令中使用S后缀来实现该功能。

不要在CMP,CMN,TST或者TEQ指令中使用S后缀。这些比较指令总是会更新标志位。

在Thumb模式下,所有数据处理指令都更新CPSR中的标志位。有一个例外就是:当一个或更多个高寄存器被用在MOV和ADD指令时,此时MOV和ADD不能更新状态标志.

几乎所有的ARM指令都可以根据CPSR中的ALU状态标志位来条件执行。参见条件执行后缀表。

在ARM模式下,你可以:

  • 根据数据操作的结果更新CPSR中的ALU状态标志;
  • 执行其他几种操作,但不更新状态标志;
  • 根据当前状态标志,决定是否执行接下来的指令。

在Thumb模式,大多数操作总是更新状态标志位,并且只能使用条件转移指令(B)来实现条件执行。该指令(B)的后缀和在ARM模式下是一样的。其他指令不能使用条件执行。

ALU状态标志

CPSR寄存器包含下面的ALU状态标志:

标志含义
N Set when the result of the operation was Negative
ZSet when the result of the operation was Zero
CSet when the operation result in a Carry(发生进位,或借位)
VSet when the operation caused oVerflow(操作造成溢出)
QARM architecture v5E only sticky flag

N,Z,C,V相关的条件码后缀如下表所列:


  • 示例1
  ADD  r0, r1, r2       ; r0 = r1 + r2, 不更新标志位
  ADDS  r0, r1, r2      ; r0 = r1 + r2, 后缀S表示更新标志位
  ADCSS  r0, r1, r2     ; If C 标志为1,则执行r0 = r1 + r2, 且更新标志,
  CMP  r0, r1           ; CMP指令肯定会更新标志. 
  • 示例2

求最大公约数

gcd
  CMP r0, r1    
  BEQ end       ; r0 = r0 结束程序
  BLT less      ; r0 < r1 跳转至 less
  SUB r0, r0, r1  ; r0 > r1时 r0 = r0 - r1
  B gcd           ; 条件都不满足是继续循环
less
  SUB r1, r1, r0  ; r0 < r1 r1 = r1 - r0
  B gcd
end

-示例3

MAIN
  mov r1, #1
  mov r2, #1
  cmp r1, r2
  beq FUNC          ;if(eq) b FUNC => 实质:if(z == 1) b FUNC
  bne FUNC          ;实质:if(z == 0) b FUNC
  mov r3, #3
  mov r4, #4
FUNC
  mov r5, #5
  mov r6, #6

via: ARM指令集——条件执行、内存操作指令、跳转指令