Memory operands specify an effective address. A base register contains an address; an optional offset selects data relative to it. Writeback forms also update the base register.
| Instruction | Address accessed | X1 afterwards |
|---|---|---|
LDR X0, [X1] | 0x1000 | 0x1000 |
LDR X0, [X1, #8] | 0x1008 | 0x1000 |
LDR X0, [X1, #8]! | 0x1008 | 0x1008 |
LDR X0, [X1], #8 | 0x1000 | 0x1008 |
All four examples load eight bytes. Immediate offsets in assembly source are byte offsets. Some instruction encodings scale the stored immediate field; the assembler performs that encoding conversion. The programmer must not multiply #8 by eight again.
LDR X0, [X1, X2] // Address = X1 + X2 LDR X0, [X1, X2, LSL #3] // Eight-byte array element LDR W0, [X1, X2, LSL #2] // Four-byte array element LDP X0, X1, [X2, #32] // Reads X2+32 and X2+40
For a 64-bit register-offset LDR, the shift is zero or three. For its 32-bit counterpart it is zero or two. Register-offset addressing does not update the base. The LDP example reads two adjacent eight-byte values and leaves X2 unchanged.
Immediate operands in arithmetic instructions, such as ADD X0, X1, #8, are values rather than memory accesses. ADR forms a PC-relative address. LDR X0, =symbol is an assembler pseudo-instruction for obtaining an address or constant and must not be confused with loading the contents of [X0].
LD1 {V0.4S, V1.4S}, [X1], #32
ADD X9, X1, X2, LSL #4
LD1 {V2.4S}, [X9]
The first example loads 32 bytes and advances X1 by 32. The second example calculates a separate address before loading 16 bytes. LD1 does not support combining an arbitrary shifted register offset with an immediate post-increment in one memory operand.
An exclusive load/store pair can implement a read-modify-write loop. The store returns a 32-bit status: zero for success and nonzero for failure. Failure requires retrying the operation.
.Lretry:
LDXR X0, [X1]
ADD X0, X0, #1
STXR W2, X0, [X1]
CBNZ W2, .Lretry
This loop atomically increments an aligned 64-bit object. It provides no acquire/release ordering for other objects. A complete concurrent algorithm must choose the required memory ordering separately.
On processors with the Large System Extensions, the following operations are available. Assemble them for a target that supports LSE, for example with -march=armv8.2-a.
LDADD W0, W1, [X2] // Add W0 to memory; W1 receives old value SWP X3, X4, [X5] // Store X3 to memory; X4 receives old value CAS X0, X1, [X2] // Compare with X0, conditionally store X1
CAS returns the old memory value in X0 whether or not the comparison succeeds. All three instructions access the location given by the base register; LDADD does not store to a different address. Atomicity alone does not imply acquire/release ordering.
LDTR and STTR support accesses using unprivileged permission checks in the applicable privileged execution context. They are system-programming tools, not a way for an application to bypass memory protection.