30.4.3. ARM MOV instruction

Move an immediate to a register, or a register to another register.

Cannot load from or to memory, since only the LDR and STR instruction families can do that in ARM as mentioned at: Section 30.3, “ARM load and store instructions”.

Since every instruction has a fixed 4 byte size, there is not enough space to encode arbitrary 32-bit immediates in a single instruction, since some of the bits are needed to actually encode the instruction itself.

The solutions to this problem are mentioned at:

Summary of solutions:

  • ARM movw and movt instructions

  • place it in memory. But then how to load the address, which is also a 32-bit value?

    • use pc-relative addressing if the memory is close enough

    • use ORR encodable shifted immediates

The blog article summarizes nicely which immediates can be encoded and the design rationale:

An Operand 2 immediate must obey the following rule to fit in the instruction: an 8-bit value rotated right by an even number of bits between 0 and 30 (inclusive). This allows for constants such as 0xFF (0xFF rotated right by 0), 0xFF00 (0xFF rotated right by 24) or 0xF000000F (0xFF rotated right by 4).

In software - especially in languages like C - constants tend to be small. When they are not small they tend to be bit masks. Operand 2 immediates provide a reasonable compromise between constant coverage and encoding space; most common constants can be encoded directly.

Assemblers however support magic memory allocations which may hide what is truly going on: https://stackoverflow.com/questions/14046686/why-use-ldr-over-mov-or-vice-versa-in-arm-assembly Always ask your friendly disassembly for a good confirmation.