On Day 1 we learned the golden rule: ARM only computes on registers. So how does data get between registers and memory? Through exactly two instructions — LDR and STR — and a rich set of addressing modes that make walking through memory elegant.
ARM is a load/store architecture: the only instructions that touch memory are loads and stores. To add 1 to a value in memory you must:
The square brackets [ ] mean "the memory at this address." The register inside (here r1) is the base address.
Matching the data sizes from Day 4, each comes in size variants:
| Load | Store | Size |
|---|---|---|
| LDR | STR | word (32-bit) |
| LDRB | STRB | byte (8-bit, zero-extended) |
| LDRH | STRH | halfword (16-bit, zero-extended) |
| LDRSB / LDRSH | — | signed byte / halfword (sign-extended) |
Use the signed loads (LDRSB, LDRSH) when a small value is a signed number, so the upper bits fill correctly.
How do you compute the actual address? ARM offers three families, and they make array/pointer code clean.
That last one is gorgeous: with the barrel shifter from Day 9, [r1, r2, LSL #2] indexes the r2-th word of an array based at r1 — array indexing in a single instruction.
Add the ! and the base register is updated to the new address:
The base is used as-is for the access, then incremented afterwards:
Post-indexed is the perfect array walker — load an element and advance the pointer, all in one instruction:
Remember from Day 8 that not every 32-bit constant fits in an instruction. The fix is a PC-relative load: the assembler stashes the constant in a nearby literal pool and loads it relative to the PC:
This is why LDR Rd, =value is the idiomatic way to get any 32-bit constant into a register.
Copying a block or saving several registers one-by-one is wasteful. LDM (load multiple) and STM (store multiple) transfer a list of registers to/from consecutive memory in a single instruction:
With writeback and the stack-style suffixes, these become PUSH and POP — which is exactly where Day 14 (the stack) picks up.
Only LDR/STR cross the register–memory boundary. The address comes from a base register + offset, where the offset can be an immediate, a register, or a scaled register. Pre/post-indexing updates the base so you can walk arrays in one instruction, and LDM/STM move whole register lists at once.
[r1,#4], scaled [r1,r2,LSL#2], pre-indexed [r1,#4]!, post-indexed [r1],#4.[r1, #4]! and [r1], #4?r2-th word of a word-array based at r1.One where only dedicated load/store instructions touch memory; all compute happens in registers. ARM is load/store.
Pre-indexed adds the offset before the access (with ! it writes the base back); post-indexed uses the base first, then adds the offset.
Load/Store Multiple — transfer a list of registers to/from consecutive memory in one instruction; the basis of PUSH/POP.