arm的v8r中汇编指令CMN的详细用法
ARMv8-R 架构中的 CMN(Compare Negative)指令用于将一个寄存器中的值与另一个操作数的负值进行比较。它本质上是执行一个加法操作,并根据加法的结果设置当前程序状态寄存器(CPSR 或 APSR)中的条件标志位(Condition Flags),但不会存储加法的结果。这条指令常用于判断一个值是否等于某个特定的负数,或者更直观地进行某些边界检查。
📌 指令格式
CMN 指令的基本语法格式如下:
CMN{<cond>} <Rn>, <operand2>
{<cond>}:这是一个可选的条件码后缀。如果使用,指令将在指定条件满足时才执行。例如,CMNEQ R1, R2表示仅在相等(Equal)条件下执行比较。如果省略,指令将无条件执行。<Rn>:第一个操作数,是存放要进行比值的源数据的寄存器。<operand2>:第二个操作数,可以是一个立即数(Immediate value)或一个寄存器, optionally with shift applied。对于CMN,指令实际比较的是Rn和-operand2。
⚙️ 操作与标志位
CMN 指令执行的操作可以表示为:
status = Rn + operand2
CMN Rn, Operand2 相当于将寄存器 Rn 的值加上 Operand2 的值,根据加法的结果更新状态寄存器中的条件标志位,但不保存加法结果。
其结果会影响 CPSR(Current Program Status Register)或 APSR(Application Program Status Register)中的以下条件标志位:
| 标志位 | 全称 | 含义 | 设置条件 | 
|---|---|---|---|
| N (Negative) | Negative | 表示结果的符号(最高位) | 若结果最高位为1(负数),则置1;否则清0。 | 
| Z (Zero) | Zero | 表示结果是否为零 | 若结果为0,则置1;否则清0。 | 
| C (Carry) | Carry | 表示加法操作是否发生了无符号溢出(进位) | 若加法产生进位(无符号溢出),则置1;否则清0。 | 
| V (oVerflow) | Overflow | 表示加法操作是否发生了有符号溢出 | 若有符号溢出发生,则置1;否则清0。 | 
需要注意的是:CMN 指令是依据 Rn + operand2 的结果来设置这些标志位的。这些标志位随后可以被后续的条件指令(如 BGT, BLE, BEQ 等)用来控制程序流程。
🖥️ 使用示例
1. 判断寄存器值是否为 -1
CMN  R0, #1          @ 计算 R0 + 1,并根据结果设置标志位
                     @ 如果结果为零(即 R0 + 1 == 0),则 Z 标志置 1
                     @ 这意味着如果 R0 == -1,则 Z=1;否则 Z=0。
BEQ  target_is_neg_one @ 如果 Z 标志为 1(相等),则跳转到 target_is_neg_one
2. 与另一个寄存器的负值进行比较
CMN  R1, R2          @ 计算 R1 + R2,并根据结果设置标志位
                     @ 这相当于比较 R1 和 -R2
BGT  target_if_greater @ 如果 R1 > -R2(从有符号数的角度看),则跳转
3. 检查寄存器值是否小于等于 -100
CMN  R3, #100        @ 计算 R3 + 100,设置标志位
                     @ 如果 R3 <= -100,那么 R3 + 100 <= 0
BLE  target_if_less_or_equal @ 如果结果为负或零(有符号数比较),则跳转
💡 应用场景与注意事项
- 主要用途:
CMN指令常用于与一个负的立即数进行比较的场景。例如,判断一个值是否等于 -1,使用CMN R0, #1比用CMP R0, #-1更直观,因为 ARM 汇编中对立即数的取值有一定限制,有时直接使用CMP与一个负的立即数可能会遇到立即数合法性问题。 - 结果不保存:切记 
CMN只修改条件标志位,不保存加法结果到任何寄存器。如果你需要加法的结果,应该使用ADD或ADDS指令。 - 条件执行:可以利用条件码 
{cond}让CMN指令仅在特定条件下执行,这可以提高代码效率。 - 与 
CMP的区别:CMP Rn, Operand2执行的是Rn - Operand2。CMN Rn, Operand2执行的是Rn + Operand2(即比较Rn和-Operand2)。- 例如,
CMP R0, #-1和CMN R0, #1想要达到的比较目的是相似的(判断 R0 是否等于 -1),但内部操作不同。 
 
🔍 进一步理解
CMN 指令将寄存器 Rn 中的值加上 operand2 表示的数值,根据加法的结果设置 CPSR 中相应的条件标志位。寄存器 Rn 中的值加上 operand2 的操作结果对 CPSR 中条件标志位的影响,与寄存器 Rn 中的值减去 operand2 的操作结果的相反数对 CPSR 中条件标志位的影响有细微差别。当第二个操作数为 0 或者为 0x80000000 时二者结果不同。例如:
CMP Rn, #0  @ 执行 Rn - 0,若 Rn >= 0 (无符号),通常C(进位)标志置1
CMN Rn, #0  @ 执行 Rn + 0,若 Rn + 0 产生进位(无符号溢出),C标志置1;否则清0。对于非零的Rn,两者的C标志位状态可能不同。
📚 相关指令
CMP:比较指令。执行减法操作 (Rn - Operand2) 并设置标志位。TST:测试位指令。执行按位与操作 (Rn & Operand2) 并设置标志位(常用于测试特定位是否为0或1)。TEQ:测试等价指令。执行按位异或操作 (Rn EOR Operand2) 并设置标志位(常用于比较两个值是否相等,且不影响C标志)。
希望这些解释和示例能帮助你更好地理解和使用 ARMv8-R 架构中的 CMN 指令。
                    
                
                
            
        
浙公网安备 33010602011771号