6. 比较指令

这些指令对两个参数执行算术或逻辑运算,丢弃结果但设置条件标志。它们通常用于在执行条件分支之前测试数据值而不改变它们。

6.1. 文档约定

记法:Rd, Rm, Rn 表示 ARM 寄存器 R0-R7。imm8 表示宽度为 8 位的立即数。

6.2. 应用程序状态寄存器(APSR)

它包含四个由条件分支指令测试的位。条件分支通常会测试多个位,例如 bge(LABEL)。条件码的含义可能取决于算术指令的操作数被视为有符号整数还是无符号整数。因此 bhi(LABEL) 假定处理的是无符号数,而 bgt(LABEL) 假定的是有符号操作数。

6.3. APSR 各位

  • Z(零)

如果运算结果为零,或比较的两个操作数相等,则此位被置位。

  • N(负)

如果结果为负,则被置位。

  • C(进位)

当结果从最高有效位(MSB)溢出时,加法会置位进位标志,例如 0x80000000 与 0x80000000 相加。由于二进制补码运算的特性,这一行为在减法中是相反的,借位由进位位被清零来表示。因此 0x10 - 0x01 实际是按 0x10 + 0xffffffff 执行的,这会置位进位位。

  • V(溢出)

如果将结果视为二进制补码数时,其相对于操作数有“错误”的符号,则溢出标志被置位。例如把 1 加到 0x7fffffff 上会置位溢出位,因为结果(0x80000000)作为二进制补码整数来看是负数。请注意,在这种情况下进位位并不会被置位。

6.4. 比较指令

这些指令会设置 APSR(应用程序状态寄存器)的 N(负)、Z(零)、C(进位)和 V(溢出)标志。

  • cmp(Rn, imm8) Rn - imm8

  • cmp(Rn, Rm) Rn - Rm

  • cmn(Rn, Rm) Rn + Rm

  • tst(Rn, Rm) Rn & Rm

6.5. 条件执行

itite 指令提供了一种无需标签即可有条件地执行随后一到四条指令的方法。

  • it(<condition>) If then(如果……则)

如果 <condition> 为真,则执行下一条指令:

cmp(r0, r1)
it(eq)
mov(r0, 100) # runs if r0 == r1
# execution continues here
  • ite(<condition>) If then else(如果……则……否则)

如果 <condition> 为真,则执行下一条指令,否则执行其后那一条。因此:

cmp(r0, r1)
ite(eq)
mov(r0, 100) # runs if r0 == r1
mov(r0, 200) # runs if r0 != r1
# execution continues here

这可以扩展到控制随后多达四条指令的执行:it[x[y[z]]],其中 x,y,z=t/e;例如 itt、itee、itete、ittte、itttt、iteee 等等。