Loading and Storing
To load the value stored in r0 into r1, we do this:
ldr r1, r0
But to load the data in the address stored in r0, we can do this instead.
ldr r1, [r0]
The square brackets indicate that we access the value at the address stored.
To store a value from r2 to the address in r3, we can do this.
str r2, [r3]
Offsets
Very often you will want to access a location that is at a fixed distance from a base pointer or that is computed from another register. ARM gives you several addressing modes for this.
Immediate offsetsÂ
str r2, [r1, #2] @ offset: [r1+2] = r2 (r1 unchanged)
str r2, [r1, #4]! @ pre-indexed: [r1+4] = r2 (r1 = r1+4)
ldr r3, [r1], #4 @ post-indexed: r3 = [r1] (r1 = r1+4)
Register offsets
str r2, [r1, r3] @ address = r1 + r3
Scaled register offsets
str r2, [r1, r3, LSL #2] @ offset = r3 << 2 (multiply by 4)
str r2, [r1, r3, LSL #2]! @ pre-indexed (updates r1)
ldr r4, [r1], r3, LSL #2 @ post-indexed
Multiple Read and Writes
You can also use the instructions ldm and stm to load/store multiple values to registers at the same time. ldmia increments after the first is loaded, but ldmib increments before. ldmda and ldmdb do the same but decrement.
ldmia r0, {r3-r6} @ load four words: r3 r4 r5 r6 to [r0 … r0+12]
stmdb r1, {r2-r4} @ store three words: r2 r3 r4 to [r1-12 … r1-4] and r1 = r1-12
Stack Handling
The push instruction decreases the sp by 4 bytes, before storing the info to the new address.
push {r0}
pop is the reverse, as the value in the SP address is loaded to a register, and the sp increases by 4 bytes.
pop {r0}
Conditional execution
The cmp code subtracts its second operand from the first, discards the result, and updates the CPSR flags. These flags can then be used by condition codes to provide conditional execution, such as loops using the b code.
| Code | Meaning | Trigger |
|---|---|---|
eq | equal / zero | Z = 1 |
ne | not equal | Z = 0 |
cs / hs | carry set / unsigned ≥ | C = 1 |
cc / lo | carry clear / unsigned < | C = 0 |
mi | minus | N = 1 |
pl | plus | N = 0 |
vs | overflow set | V = 1 |
vc | overflow clear | V = 0 |
loop:
ldr r0, [r1], #4
cmp r0, #0 @ set Z if element == 0
beq done @ branch equal → element was zero
b loop @ otherwise keep scanning
done: