| |||
| Home > Writing ARM 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.
You can 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 single instruction for a specific constant:
If the constant can be constructed with a single MOV or MVN instruction,
the assembler generates the appropriate instruction.
If the constant cannot be constructed with a single 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.
See Placing literal pools for more information.
See LDR 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 or Thumb-2 code, but can be in either direction
forward and less than 1KB in pre-Thumb-2 Thumb code, or when using the 16-bit instruction in Thumb-2 code.
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, 32-bit Thumb-2) or in the range 0 to +1KB (pre-Thumb-2 Thumb,
16-bit Thumb-2). See 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.4 shows
how this works. It is supplied as loadcon.s in
the main examples directory .
See Code examples for instructions
on how to assemble, link, and execute the example.install_directory\RVDS\Examples
The instructions listed as comments are the ARM instructions generated by the assembler.
Example 2.4.
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 r0, #0x18 ; angel_SWIreason_ReportException
LDR r1, =0x20026 ; ADP_Stopped_ApplicationExit
SVC #0x123456 ; ARM semihosting (formerly SWI)
func1
LDR r0, =42 ; => MOV R0, #42
LDR r1, =0x55555555 ; => LDR R1, [PC, #offset to
; Literal Pool 1]
LDR r2, =0xFFFFFFFF ; => MVN R2, #0
BX 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
BX lr
LargeTable
SPACE 4200 ; Starting at the current location,
; clears a 4200 byte area of memory
; to zero
END ; Literal Pool 2 is empty