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