HomeARM CourseDay 10
DAY 10 · THE INSTRUCTION SET

Load/Store & Addressing Modes

By EcrioniX · Updated Jun 6, 2026

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.

1. The load/store rule, revisited

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:

LDR r0, [r1] ; 1. load: r0 = memory at address in r1 ADD r0, r0, #1 ; 2. compute: in a register STR r0, [r1] ; 3. store: write it back to memory

The square brackets [ ] mean "the memory at this address." The register inside (here r1) is the base address.

2. Sizes: word, byte, halfword

Matching the data sizes from Day 4, each comes in size variants:

LoadStoreSize
LDRSTRword (32-bit)
LDRBSTRBbyte (8-bit, zero-extended)
LDRHSTRHhalfword (16-bit, zero-extended)
LDRSB / LDRSHsigned byte / halfword (sign-extended)

Use the signed loads (LDRSB, LDRSH) when a small value is a signed number, so the upper bits fill correctly.

3. Addressing modes — the elegant part

How do you compute the actual address? ARM offers three families, and they make array/pointer code clean.

Offset (base + offset, base unchanged)

LDR r0, [r1, #4] ; address = r1 + 4 (r1 unchanged) LDR r0, [r1, r2] ; address = r1 + r2 (register offset) LDR r0, [r1, r2, LSL #2] ; address = r1 + r2*4 (scaled — barrel shifter!)

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.

Pre-indexed (update base before access)

Add the ! and the base register is updated to the new address:

LDR r0, [r1, #4]! ; r1 = r1 + 4, THEN load from new r1

Post-indexed (use base, then update)

The base is used as-is for the access, then incremented afterwards:

LDR r0, [r1], #4 ; load from r1, THEN r1 = r1 + 4

Post-indexed is the perfect array walker — load an element and advance the pointer, all in one instruction:

; sum an array of n words at r1 into r0 MOV r0, #0 loop: LDR r3, [r1], #4 ; grab element, bump pointer to next ADD r0, r0, r3 SUBS r2, r2, #1 ; count down (S sets Z at zero) BNE loop ; branch back while not zero (Day 12)

4. Loading constants — PC-relative

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:

LDR r0, =0x12345678 ; assembler: load from a literal pool via PC-relative LDR

This is why LDR Rd, =value is the idiomatic way to get any 32-bit constant into a register.

5. Moving many registers at once: LDM / STM

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:

STM r0, {r4-r7} ; store r4,r5,r6,r7 to memory at r0 LDM r0, {r4-r7} ; load them back

With writeback and the stack-style suffixes, these become PUSH and POP — which is exactly where Day 14 (the stack) picks up.

✅ The mental model

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.

🎯 Day 10 takeaways

Quick check

  1. Which two instructions are the only way to access memory on ARM?
  2. What's the difference between [r1, #4]! and [r1], #4?
  3. Write the load that fetches the r2-th word of a word-array based at r1.

FAQ

What is a load/store architecture?

One where only dedicated load/store instructions touch memory; all compute happens in registers. ARM is load/store.

Pre-indexed vs post-indexed?

Pre-indexed adds the offset before the access (with ! it writes the base back); post-indexed uses the base first, then adds the offset.

What are LDM/STM?

Load/Store Multiple — transfer a list of registers to/from consecutive memory in one instruction; the basis of PUSH/POP.

Previous
← Day 9: The barrel shifter

← Back to the full course roadmap