☰
ARM 汇编比较指令:只修改标志位的底层逻辑与实战用法
2026/10/18 4:54:20 网站建设 项目流程

前言

初学 ARM 汇编时,CMP、CMN、TST、TEQ 四条比较指令总会让人产生困惑:指令内部完成了减法、加法、按位与、异或运算,却不保存运算结果,仅仅刷新 CPSR 程序状态寄存器的标志位。

课堂上仅记住 “指令会影响标志位” 这一结论,却不清楚这套设计的底层目的;直到上机实操搭配条件跳转后,才理清比较指令、标志位、条件指令三者不可分割的联动关系。本文从底层原理出发,结合代码实例拆解四条比较指令的用法。

一、核心底层逻辑:汇编判断分为两步拆分设计

高级语言中一条if语句即可完成 “数值对比 + 分支跳转”,但 ARM 汇编将该逻辑拆分为两个独立环节,分工明确:

  1. 比较指令:负责运算,留下判断依据CMP/CMN/TST/TEQ 执行内部运算后,直接丢弃运算结果,唯一输出是更新 CPSR 中的 N(负标志)、Z(零标志)、C(进位 / 借位标志)、V(溢出标志)。该指令不会修改任何通用寄存器,也不会主动跳转程序,仅把对比结果以标志位的形式保存下来。 单独书写比较指令没有任何实际效果,标志位更新后无指令读取判断,程序仍顺序执行,对比操作等同于无效。
  2. 条件指令:读取标志,执行分支动作所有带条件后缀的指令(条件跳转 BXX、条件运算 MOVXX/ADDXX)本身无法完成数值对比,仅读取上一条指令刷新的标志位,匹配预设条件后决定是否执行。 二者必须配对使用,固定执行流程:比较指令更新标志位 → 条件指令读取标志完成逻辑判断。

二、四大比较指令运算原理与适用场景

1. CMP 减法比较指令

语法:CMP Rn, operand底层运算:Rn - operand,完整更新 N/Z/C/V 全部标志位 核心用途:判断两个数值大小,区分有符号、无符号数对比,是循环、区间判断最常用指令。 标志判断规则:

  • Z=1:两数相等;
  • C=1:无符号数 Rn ≥ operand;
  • N == V:有符号数 Rn ≥ operand。

示例:判断 R0 是否大于 100,大于则跳转

CMP R0, #100 BGT R0_Greater ; 有符号数大于跳转 BHI R0_Greater_U ; 无符号数大于跳转

2. CMN 负数比较指令

语法:CMN Rn, operand底层运算:Rn + operand,等价执行CMP Rn, #-operand核心用途:快速判断寄存器数值是否等于某个负数,无需手动取负运算。 标志判断规则:Z=1 时,代表Rn = -operand。

示例:判断 R0 是否等于 - 20

CMN R0, #20 BEQ Equal_Neg20 ; R0 = -20 跳转

3. TST 位测试指令

语法:TST Rn, operand底层运算:Rn & operand,仅依靠 Z 标志判断特定位状态 核心用途:硬件寄存器、IO 引脚位检测,快速查看某一 bit 是否置 1。 标志判断规则:Z=0,掩码对应 bit 为 1;Z=1,掩码对应 bit 全为 0。

示例:检测 R0 第 0 位是否为高电平

TST R0, #0x01 BNE Bit0_Set ; bit0=1 跳转

4. TEQ 等值测试指令

语法:TEQ Rn, operand底层运算:Rn ^ operand,仅更新 N、Z 标志,不改动进位 C 核心用途:单纯校验两数是否完全相等,不会破坏进位标志,适合连续等值判断场景。 标志判断规则:Z=1,两数数值完全一致。

示例:判断 R0 与 R1 数值是否相同

TEQ R0, R1 BEQ Value_Same

三、实战拓展:不止跳转,所有指令均可加条件后缀

标志位不仅服务于 B 系列跳转指令,MOV、ADD、SUB 等常规运算指令都支持条件后缀,可省去多余分支,精简代码。 需求:R0 大于 50 时,将 R1 赋值为 100

CMP R0, #50 MOVGT R1, #100 ; 满足GT(有符号大于)才执行赋值

四、总结

  1. 比较指令 “只改标志位、不存结果” 是硬件分层设计:分离 “对比运算” 和 “逻辑判断”,简化 CPU 指令架构;
  2. 四条指令各司其职:CMP 判大小、CMN 判负数、TST 测比特、TEQ 判等值;
  3. 标志位是连接比较指令与条件指令的桥梁,二者必须搭配使用,单独书写比较指令无业务逻辑意义;
  4. 条件后缀适用于全部 ARM 基础指令,灵活运用可简化分支代码,提升汇编执行效率。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询