| |||
| Home > Writing ARM and Thumb Assembly Language > Loading constants into registers > Loading with LDR Rd, =const | |||
The LDR Rd,= pseudo-instruction
can construct any 32-bit numeric constant in a single instruction.
Use this pseudo-instruction to generate constants that are out of
range of the constMOV and MVN instructions.
The LDR pseudo-instruction generates the most
efficient code for a specific constant:
If
the constant can be constructed with a MOV or MVN instruction,
the assembler generates the appropriate instruction.
If the constant cannot be constructed with a MOV or MVN instruction,
the assembler:
places the value in a literal pool (a portion of memory embedded in the code to hold constant values)
generates an LDR instruction with a
program-relative address that reads the constant from the literal
pool.
For example:
LDR rn, [pc, #offset to literal pool]
; load register n with one word
; from the address [pc + offset]
You must ensure that there is a literal pool within range
of the LDR instruction generated by the assembler.
Refer to Placing literal pools for
more information.
Refer to LDR ARM pseudo-instruction for a description
of the syntax of the LDR pseudo-instruction.
The assembler places a literal pool at the end of each section.
These are defined by the AREA directive at the start
of the following section, or by the END directive at
the end of the assembly. The END directive at the end
of an included file does not signal the end of a section.
In large sections the default literal pool can be out of range
of one or more LDR instructions. The offset from the
pc to the constant must be:
less than 4KB in ARM state, but can be in either direction
forward and less than 1KB in Thumb state.
When an LDR Rd,=const pseudo-instruction requires
the constant to be placed in a literal pool, the assembler:
Checks if the constant is available and addressable in any previous literal pools. If so, it addresses the existing constant.
Attempts to place the constant in the next literal pool if it is not already available.
If the next literal pool is out of range, the assembler generates
an error message. In this case you must use the LTORG directive
to place an additional literal pool in the code. Place the LTORG directive
after the failed LDR pseudo-instruction, and within
4KB (ARM) or 1KB (Thumb). Refer to LTORG for a detailed description.
You must place literal pools where the processor does not attempt to execute them as instructions. Place them after unconditional branch instructions, or after the return instruction at the end of a subroutine.
Example 2.5 shows how this works in practice. The instructions listed as comments are the ARM instructions that are generated by the assembler. Refer to Code examples for instructions on how to assemble, link, and execute the example.
Example 2.5.
AREA Loadcon, CODE, READONLY
ENTRY ; Mark first instruction to execute
start BL func1 ; Branch to first subroutine
BL func2 ; Branch to second subroutine
stop MOV pc, lr ; Return to caller
;...
func1
LDR r0, =42 ; => MOV R0, #42
LDR r1, =0x55555555 ; => LDR R1, [PC, #offset to
; Literal Pool 1]
LDR r2, =0xFFFFFFFF ; => MVN R2, #0
MOV pc, lr
LTORG ; Literal Pool 1 contains
; literal Ox55555555
func2
LDR r3, =0x55555555 ; => LDR R3, [PC, #offset to
; Literal Pool 1]
; LDR r4, =0x66666666 ; If this is uncommented it
; fails, because Literal Pool 2
; is out of reach
MOV pc, lr
LargeTable
SPACE 4200 ; Starting at the current location,
; clears a 4200 byte area of memory
; to zero
END ; Literal Pool 2 is empty