Flags and CMP
Condition Flags
ARM64 uses condition flags to make decisions. These four flags, stored in the NZCV register, are the foundation of all conditional logic -- from simple if/else to complex loops.
The NZCV Flags
| Flag | Name | Set when... | Example |
|---|---|---|---|
| N | Negative | Result bit 63 = 1 | 5 - 10 sets N=1 |
| Z | Zero | Result is zero | 5 - 5 sets Z=1 |
| C | Carry | Unsigned overflow | 0xFFFFFFFF + 1 sets C=1 |
| V | oVerflow | Signed overflow | 0x7FFFFFFF + 1 sets V=1 |
Important: Regular
ADDandSUBdo not set flags. Only flag-setting instructions (CMP,ADDS,SUBS) modify NZCV. This means you can safely do arithmetic without accidentally changing flags set by a previous comparison.
Condition flags are the sensor readings of the CPU -- after every comparison, they report the status of your last operation, just like the Enterprise's sensors report conditions ahead.
CMP -- Compare
CMP is the primary comparison instruction. It subtracts its second operand from its first, sets the flags, and discards the subtraction result:
CMP X0, #10 // Computes X0 - 10, sets flags, result discarded
CMP X0, X1 // Computes X0 - X1, sets flags, result discarded
After CMP X0, X1:
- Z=1 if X0 == X1 (the subtraction is zero)
- N=1 if X0 < X1 (signed -- the result is negative)
- C=1 if X0 >= X1 (unsigned -- no borrow occurred)
Internally, CMP X0, X1 is encoded as SUBS XZR, X0, X1 -- a subtraction into the zero register with flag-setting.
CMN -- Compare Negative
CMN adds its operands and sets flags. It is useful when comparing against a negative value:
CMN X0, #5 // Computes X0 + 5, sets flags
ADDS and SUBS
These are flag-setting versions of ADD and SUB that keep the result:
ADDS X0, X1, X2 // X0 = X1 + X2, AND sets flags
SUBS X0, X1, X2 // X0 = X1 - X2, AND sets flags
Use these when you need both the result and the flags.
Your Task
Write a program that compares two values (15 and 15). If they are equal, print EQ\n. If not, print NE\n. Use CMP and a conditional branch (B.NE, which we will cover in the next lesson -- but use it here as a preview).
Hint: After CMP X0, X1, use B.NE not_equal to skip to a different label if they are not equal.