Time to write real instructions. The data-processing instructions are the ALU's everyday work — moving, adding, subtracting and logic. Learn their one shared format and you can read most ARM assembly.
Almost every data-processing instruction follows the same shape:
| Group | Instr | Meaning |
|---|---|---|
| Move | MOV Rd, Op2 | Rd = Op2 |
| MVN Rd, Op2 | Rd = NOT Op2 (bitwise invert) | |
| Arithmetic | ADD Rd, Rn, Op2 | Rd = Rn + Op2 |
| ADC Rd, Rn, Op2 | add with carry (for >32-bit) | |
| SUB Rd, Rn, Op2 | Rd = Rn − Op2 | |
| RSB Rd, Rn, Op2 | reverse subtract: Op2 − Rn | |
| Logic | AND Rd, Rn, Op2 | bitwise AND |
| ORR Rd, Rn, Op2 | bitwise OR | |
| EOR Rd, Rn, Op2 | bitwise XOR | |
| BIC Rd, Rn, Op2 | bit clear: Rn AND (NOT Op2) |
RSB (reverse subtract) exists because Operand2 is the flexible one — RSB r0, r1, #0 negates r1. BIC is the clean way to clear specific bits: BIC r0, r0, #0xF clears the low nibble.
By default, arithmetic/logic instructions compute a result and leave the CPSR flags untouched. Add S and they update N, Z, C, V (the flags from Day 3):
That SUBS is the classic loop counter: subtract 1, and the Z flag tells you when you've reached zero. The S is what connects computation to decision-making (Day 11).
Often you want to test values without keeping a result — just set the flags. That's CMP and TST:
| Instr | Does | Equivalent to |
|---|---|---|
| CMP Rn, Op2 | flags from Rn − Op2 | SUBS, result discarded |
| CMN Rn, Op2 | flags from Rn + Op2 | ADDS, discarded |
| TST Rn, Op2 | flags from Rn AND Op2 | ANDS, discarded |
| TEQ Rn, Op2 | flags from Rn EOR Op2 | EORS, discarded |
Because an ARM instruction is only 32 bits, the immediate field can't hold every possible 32-bit constant — it stores a limited pattern. Small/round constants work in MOV; arbitrary ones use a PC-relative load from a literal pool (we'll see it in Day 10) or the MOV/MOVT pair. The assembler's handy LDR r0, =0x12345678 picks the best method for you.
One format — OP{cond}{S} Rd, Rn, Operand2 — covers move, add, subtract and logic. Operand2 is the flexible part. S turns a calculation into something the next branch can react to. CMP/TST set flags without keeping a result.
OP{cond}{S} Rd, Rn, Operand2.ADD and ADDS?CMP instead of SUBS when you only want to compare?The ALU operations on registers — MOV/MVN, ADD/ADC/SUB/RSB, AND/ORR/EOR/BIC, and the compares CMP/CMN/TST/TEQ.
It makes the instruction update the N Z C V flags from its result. Without S, the flags stay unchanged.
SUB keeps the result; CMP does the same subtraction but only sets flags (result discarded) for comparing before a branch.