| |||
| Home > ARM Instruction Reference > ARM memory access instructions > LDR and STR, words and unsigned bytes | |||
Load register and store register, 32-bit word or 8-bit unsigned byte. Byte loads are zero-extended to 32 bits.
Both LDR and STR have four possible
forms:
zero offset
pre-indexed offset
program-relative
post-indexed offset.
The syntax of the four forms, in the same order, are:
op{cond}{B}{T}Rd, [Rn]
op{cond}{B}Rd, [Rn,FlexOffset]{!}
op{cond}{B}Rd,label
op{cond}{B}{T}Rd, [Rn],FlexOffset
where:
opis either LDR (Load Register)or STR (Store
Register).
condis an optional condition code (see Conditional execution).
Bis an optional suffix. If B is
present, the least significant byte of is transferred.
If Rd is opLDR,
the other bytes of are
cleared.Rd
Otherwise, a 32-bit word is transferred.
Tis an optional suffix. If T is
present, the memory system treats the access as though the processor
was in User mode, even if it is in a privileged mode (see Processor mode). T has
no effect in User mode. You cannot use T with
a pre-indexed offset.
Rdis the ARM register to load or save.
Rnis the register on which the memory address is based.
must
not be the same as Rn,
if the instruction:Rd
is
pre-indexed with writeback (the ! suffix)
is post-indexed
uses the T suffix.
FlexOffsetis a flexible offset applied to the value in (see Flexible offset syntax).Rn
labelis a program-relative expression. See Register-relative and program-relative expressions for more information.
must
be within ±4KB of the current instruction.label
!is
an optional suffix. If ! is present, the address
including the offset is written back into .
You cannot use the Rn! suffix if is
r15.Rn
The offset is applied to the value in before
the data transfer takes place. The result is used as the memory
address for the transfer. If the Rn! suffix
is used, the result is written back into . Rn must
not be r15 if the Rn!suffix is used.
This is an alternative version of the pre-indexed form. The
assembler calculates the offset from the PC for you, and generates
a pre-indexed instruction with the PC as .Rn
You cannot use the ! suffix.
The value in is
used as the memory address for the transfer. The offset is applied
to the value in Rn after
the data transfer takes place. The result is written back into Rn. Rn must
not be r15.Rn
Both pre-indexed and post-indexed offsets can be either of the following:
#expr
{-}Rm{, shift}
where:
-is an optional minus sign. If - is
present, the offset is subtracted from . Otherwise,
the offset is added to Rn.Rn
expris an expression evaluating to an integer in the range –4095 to +4095. This is often a numeric constant (see examples below).
Rmis a register containing a value to be used as the
offset. must
not be r15.Rm
shiftis an optional shift to be applied to .
It can be any one of:Rm
ASR narithmetic shift right bits.
1 = n = 32.n
LSL nlogical shift left bits.
0 = n = 31.n
LSR nlogical shift right bits.
1 = n = 32.n
ROR nrotate right bits.
1 = n = 31.n
RRXrotate right one bit, with extend.
In most circumstances, you must ensure that addresses for 32-bit transfers are 32-bit word-aligned.
If your system has a system coprocessor (cp15), you can enable alignment checking. Non word-aligned 32-bit transfers cause an alignment exception if alignment checking is enabled.
If your system does not have a system coprocessor (cp15), or alignment checking is disabled:
For STR, the specified
address is rounded down to a multiple of four.
For LDR:
The specified address is rounded down to a multiple of four.
Four bytes of data are loaded from the resulting address.
The loaded data is rotated right by one, two or three bytes according to bits [1:0] of the address.
For a little-endian memory system, this causes the addressed byte to occupy the least significant byte of the register.
For a big-endian memory system, it causes the addressed byte to occupy:
bits[31:24] if bit[0] of the address is 0
bits[15:8] if bit[0] of the address is 1.
A load to r15 (the program counter) causes a branch to the instruction at the address loaded.
Bits[1:0] of the value loaded:
are ignored in ARM architecture v3 and below
must be zero in ARM architecture v4.
In ARM architecture v5 and above:
bits[1:0]
of a value loaded to r15 must not have the value 0b10
if bit[0] of a value loaded to r15 is set, the processor changes to Thumb state.
You cannot use the B or T suffixes
when loading to r15.
In general, avoid saving from r15 if possible.
If you do save from r15, the value saved is the address of the current instruction, plus an implementation-defined constant. The constant is always the same for a particular processor.
If your assembled code might be used on different processors, you can find out what the constant is at runtime using code like the following:
SUB R1, PC, #4 ; R1 = address of following STR instruction
STR PC, [R0] ; Store address of STR instruction + offset,
LDR R0, [R0] ; then reload it
SUB R0, R0, R1 ; Calculate the offset as the difference
If your code is to be assembled for a particular processor,
the value of the constant is available in armasm as {PCSTOREOFFSET}.
These instructions are available in all versions of the ARM architecture.
In T variants of ARM architecture v5 and above, a load to r15 causes a change to executing Thumb instructions if bit[0] of the value loaded is set.
LDR r8,[r10] ; loads r8 from the address in r10.
LDRNE r2,[r5,#960]! ; (conditionally) loads r2 from a word
; 960 bytes above the address in r5, and
; increments r5 by 960.
STR r2,[r9,#consta-struc] ; consta-struc is an expression evaluating
; to a constant in the range 0-4095.
STRB r0,[r3,-r8,ASR #2] ; stores the least significant byte from
; r0 to a byte at an address equal to
; contents(r3) minus contents(r8)/4.
; r3 and r8 are not altered.
STR r5,[r7],#-8 ; stores a word from r5 to the address
; in r7, and then decrements r7 by 8.
LDR r0,localdata ; loads a word located at label localdata