+
+

版权归作者所有,如有转发,请注明文章出处:https://cyrus-studio.github.io/blog/

+
+

条件标志

+

在 ARM 指令集中,条件标志是控制指令执行的一种机制,它们用于实现条件分支、比较和其他逻辑操作。

+

我们平时使用 IDA 调试程序时,在 general registers 窗口中看到的条件标志 +image.png

+

ARM 处理器通常使用四个主要的条件标志,它们的状态影响指令的执行。这些条件标志包括:

+

1. N (Negative): 负标志,用于指示最后一次操作的结果是否为负值。若结果为负,则 N 被置为 1;否则为 0。

+

2. Z (Zero): 零标志,用于指示最后一次操作的结果是否为零。如果结果为零,则 Z 被置为 1;否则为 0。

+

3. C (Carry): 进位标志,用于指示加法操作是否产生了进位或减法操作是否没有借位。对于加法,若产生进位,则 C 被置为 1;对于减法,若没有借位,则 C 被置为 1。

+

4. V (Overflow): 溢出标志,用于指示最后一次算术操作是否发生了溢出。当两个有符号数相加或相减时,如果结果的符号与操作数的符号不一致,表示发生了溢出,V 被置为 1。

+

在 ARM 指令中,条件执行可以通过附加条件码实现,例如:

+
    +
  • +

    EQ (Equal): 当 Z = 1 时执行(相等)。

    +
  • +
  • +

    NE (Not Equal): 当 Z = 0 时执行(不相等)。

    +
  • +
  • +

    GT (Greater Than): 当 Z = 0 且 N = V 时执行(大于)。

    +
  • +
  • +

    LT (Less Than): 当 N ≠ V 时执行(小于)。

    +
  • +
  • +

    GE (Greater Than or Equal): 当 N = V 时执行(大于或等于)。

    +
  • +
  • +

    LE (Less Than or Equal): 当 Z = 1 或 N ≠ V 时执行(小于或等于)。

    +
  • +
+

这些条件标志和条件码使得 ARM 架构能够高效地进行复杂的控制流和决策逻辑,从而优化程序的执行效率。

+

条件标志如何影响指令的执行

+

下面以一段汇编代码解释条件标志的变化过程,以及如何通过条件码用于指令影响汇编指令的走向。

+
    .data
+a:  .word 5       // 定义变量 a,值为 5
+b:  .word 10      // 定义变量 b,值为 10
+max_value: .word 0 // 存储最大值的变量
+
+    .text
+    .global _start
+
+_start:
+    // 读取 a 和 b 的值
+    LDR R0, =a        // 将 a 的地址加载到 R0
+    LDR R1, [R0]      // 将 a 的值加载到 R1 (R1 = 5)
+
+    LDR R0, =b        // 将 b 的地址加载到 R0
+    LDR R2, [R0]      // 将 b 的值加载到 R2 (R2 = 10)
+
+    // 比较 a 和 b
+    CMP R1, R2        // 比较 R1 (a) 和 R2 (b)
+                       // 根据 R1 和 R2 的值,设置条件标志
+                       // 如果 R1 < R2:
+                       //   N = 1, Z = 0, C = 1, V = 0
+                       // 如果 R1 == R2:
+                       //   N = 0, Z = 1, C = 1, V = 0
+                       // 如果 R1 > R2:
+                       //   N = 0, Z = 0, C = 0, V = 0
+
+    // 根据比较结果设置最大值
+    BEQ a_equals_b    // 如果 Z = 1 (相等),跳转到 a_equals_b
+    BGT a_greater      // 如果 N = 0 且 Z = 0,(a > b),跳转到 a_greater
+    // 如果到这里,说明 b > a
+    STR R2, =max_value // b 是最大值,存储 b 的值
+
+    B end              // 跳转到 end
+
+a_equals_b:
+    // a 和 b 相等
+    STR R1, =max_value // 存储任一值,a 或 b 都可以
+
+    B end              // 跳转到 end
+
+a_greater:
+    // a 大于 b
+    STR R1, =max_value // 存储 a 的值
+
+end:
+    // 结束程序
+    MOV R7, #1        // 系统调用号,退出
+    SWI 0             // 触发系统调用
+

CMP 指令是如何影响条件标志

+

在 ARM 汇编中,CMP 指令用于比较两个寄存器的值。具体来说,CMP R1,R2 指令会将寄存器 R1 的值减去寄存器 R2 的值,但不会将结果存储在任何寄存器中。这一操作的主要目的是更新条件标志,以便后续的条件执行指令可以根据比较结果做出决策。

+

我们可以在执行比较 CMP R1, R2 时观察到条件标志的变化。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
步骤R1 (a)R2 (b)N (Negative)Z (Zero)C (Carry)V (Overflow)说明
读取 a 的值5-----加载 a 的值到 R1
读取 b 的值510----加载 b 的值到 R2
比较 R1 和 R25101010执行 CMP R1, R2 ,结果 5 - 10(借位)
BEQ 检查5101010Z = 0(不相等),不跳转到 a_equals_b
BGT 检查5101010N = 1,Z = 0(a 不大于 b),不跳转到 a_greater
存储最大值-101010存储 b 的值到 max_v
+ +