ALU Flags N, Z, C, V - MarekBykowski/readme GitHub Wiki
ALU Flags Cheat Sheet β N, Z, C, V
The Four Flags
Every arithmetic operation sets these flags in the CPU status register (CPSR on ARM):
| Flag | Name | Set when |
|---|---|---|
| N | Negative | MSB of result = 1 |
| Z | Zero | result = 0 |
| C | Carry | unsigned overflow (carry out or borrow) |
| V | oVerflow | signed overflow (result mathematically wrong) |
Binary Addition β bit by bit rules
0 + 0 = 0 (no carry)
0 + 1 = 1 (no carry)
1 + 0 = 1 (no carry)
1 + 1 = 10 (result=0, carry=1)
1 + 1 + 1 = 11 (result=1, carry=1)
Example: 1111 + 0001
1111
+ 0001
ββββββ
bit 0: 1+1 = 10 β result=0, carry=1
bit 1: 1+0+1 = 10 β result=0, carry=1
bit 2: 1+0+1 = 10 β result=0, carry=1
bit 3: 1+0+1 = 10 β result=0, carry=1
bit 4: carry out β C=1
result: 10000 β kept: 0000 C=1 N=0 Z=1 V=0
Binary Subtraction β bit by bit rules
0 - 0 = 0 (no borrow)
1 - 0 = 1 (no borrow)
1 - 1 = 0 (no borrow)
0 - 1 = 1, borrow! (borrow from next bit, add 2 to current)
0 - 1 - 1(borrow) = 0, borrow! (add 2: 2-1-1=0)
π‘ When you borrow, the current bit becomes
10(binary) = 2. Then apply the rules above.
Example: 0010 - 0110 (2 - 6)
0010
- 0110
ββββββ
bit 0: 0-0 = 0 result=0, borrow=0
bit 1: 1-1 = 0 result=0, borrow=0
bit 2: 0-1 = borrow! β 2-1=1 result=1, borrow=1
bit 3: 0-0-1(borrow) = borrow! β 2-0-1=1 result=1, borrow=1
bit 4: 0-0-1(borrow) = borrow! β 2-0-1=1 result=1, borrow=1
bit 5: 0-1-1(borrow) = borrow! β 2-1-1=0 result=0, borrow=1
bit 6: 0-0-1(borrow) = borrow! β 2-0-1=1 result=1, borrow=1
bit 7: 0-0-1(borrow) = borrow! β 2-0-1=1 result=1, borrow=1
result: 1111 1100 = 0xFC C=0 (borrow out) N=1 Z=0 V=0
β οΈ On ARM: C=0 after subtraction = borrow occurred (ARM inverts borrow β carry convention)
C Flag β Carry / Borrow (unsigned)
Addition: C=1 means carry OUT (result wrapped upward past 2βΏ)
Subtraction: C=0 means borrow (result wrapped downward below 0)
Detect in C code (no direct flag access):
// Unsigned overflow on addition
uint32_t result = a + b;
if (result < a) { /* carry β wrapped */ }
// Unsigned underflow on subtraction
if (b > a) { /* borrow β would wrap */ }
// Safe elapsed time even across wraparound
uint32_t elapsed = tick_now - tick_last; // always correct for uint32_t
V Flag β oVerflow (signed)
Hardware rule:
V = carry_into_MSB XOR carry_out_of_MSB
If they match β V=0 (carry flowed through cleanly) If they differ β V=1 (carry got trapped in sign bit β sign corrupted)
Intuitive rule β two impossible results:
+ + + = β β V=1 (two positives cannot sum to negative)
β + β = + β V=1 (two negatives cannot sum to positive)
+ + β = any β V=0 (mixed signs can never overflow)
β + + = any β V=0 (result always lands between operands)
Example: 0111 + 0001 (+7 + +1)
0111 (+7)
+ 0001 (+1)
ββββββ
1000 (-8 β WRONG, should be +8)
carry into bit 3 = 1
carry out of bit 3 = 0
V = 1 XOR 0 = 1 β
Example: 1001 + 1001 (-7 + -7)
1001 (-7)
+ 1001 (-7)
ββββββ
0010 (+2 β WRONG, should be -14)
carry into bit 3 = 0
carry out of bit 3 = 1
V = 0 XOR 1 = 1 β
All Four Flags β complete examples
Example 1: 1111 + 0001 (unsigned 15+1 / signed -1+1)
result: 0000 carry out
N=0 MSB=0
Z=1 result=0
C=1 carry out (unsigned 15+1=16 overflowed)
V=0 carry in=1, carry out=1 β 1 XOR 1 = 0 (signed -1+1=0, correct)
Example 2: 0111 + 0001 (unsigned 7+1 / signed +7+1)
result: 1000 no carry out
N=1 MSB=1
Z=0 resultβ 0
C=0 no carry out (unsigned 7+1=8, fits in 4 bits)
V=1 carry in=1, carry out=0 β 1 XOR 0 = 1 (signed +8 doesn't fit)
Example 3: 0010 - 0110 (2 - 6)
result: 1100 borrow out
N=1 MSB=1
Z=0 resultβ 0
C=0 borrow (ARM: C=0 = borrow)
V=0 signed 2-6=-4, fits in range
C vs V β key distinction
| C flag | V flag | |
|---|---|---|
| Catches | unsigned overflow | signed overflow |
| Addition trigger | result > 2βΏ-1 | pos+pos=neg or neg+neg=pos |
| Subtraction trigger | b > a (borrow) | pos-neg=neg or neg-pos=pos |
| ARM branch | BCS / BCC |
BVS / BVC |
| C code equivalent | result < a after add |
no direct equivalent |
| Can fire together? | yes β independently | yes β independently |
ARM Branch Instructions Using Flags
| Instruction | Flags checked | Meaning |
|---|---|---|
BEQ |
Z=1 | equal |
BNE |
Z=0 | not equal |
BCS / BHS |
C=1 | unsigned >= (no borrow) |
BCC / BLO |
C=0 | unsigned < (borrow) |
BMI |
N=1 | negative |
BPL |
N=0 | positive or zero |
BVS |
V=1 | signed overflow |
BVC |
V=0 | no signed overflow |
BGT |
Z=0 and N=V | signed > |
BLT |
Nβ V | signed < |
BGE |
N=V | signed >= |
BLE |
Z=1 or Nβ V | signed <= |
Hex Mental Arithmetic β practical shortcuts
0xFF + 0x01 = 0x100 β 0x00, C=1
0x80 - 0x01 = 0x7F (sign bit clears)
0xFFFFFFFF = -1 (signed 32-bit)
0x80000000 = INT_MIN
0x7FFFFFFF = INT_MAX
Two's complement shortcut (negate x):
flip all bits, add 1
0x06 β 0xF9 + 1 = 0xFA (-6 in 8-bit)
Subtraction via two's complement:
a - b = a + (~b + 1)
2 - 6 = 0x02 + 0xFA = 0xFC β
Generated during prep session Β· Swarmer Integration Engineer Β· 2026