| |||
| Home > Basic Assembly Language Programming > 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 registernwith 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.
Refer to Chapter 5 Assembler in
the ARM Software Development Toolkit Reference Guide for a description of the syntax
of the LDR pseudo-instruction.
The assembler places a literal pool at the end of each area.
These are defined by the AREA directive at the start
of the following area, or by the END directive at the
end of the assembly. The END directives at the ends
of included files do not signal the end of areas.
In large areas the default literal pool may be out of range
of one or more LDR instructions:
in ARM state, the offset from the pc to the constant must be less than 4KB
in Thumb state, the offset from the pc to the constant must be less than 1KB.
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 Chapter 5 Assembler in
the ARM Software Development Toolkit Reference Guide for a detailed description
of the LTORG directive.
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 5.5 shows how
this works in practice. It is supplied as loadcon.s in
the examples\asm subdirectory of the toolkit.
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 5.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 r0, #0x18 ; angel_SWIreason_ReportException LDR r1, =0x20026 ; ADP_Stopped_ApplicationExit SWI 0x123456 ; Angel semihosting ARM 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 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 % 4200 ; Starting at the current location, ; clears a 4200 byte area of memory ; to zero. END ; Literal Pool 2 is empty.