Gravitational plate of three masses and a slashed discABC0Static engraved plate. Three-dimensional view is unavailable or reduced motion is requested.

← back to fieldarchive

archiveFeb 10, 2021

ARM: loading constants into registers

Why you cannot load an arbitrary 32-bit immediate in one ARM instruction, and how MOV and MVN cover the common cases without a separate memory load.

Loading a constant into a register

You cannot load an arbitrary 32-bit constant into a register with a single instruction unless you also load from memory. ARM instructions are only 32 bits wide. Thumb has a similar limit.

You can load a full 32-bit value with a data load, but many common constants have a cheaper path. Plenty of them can also sit directly as operands inside data-processing instructions, with no separate load at all.

Direct loading with MOV and MVN

MOV

MOV can load any 8-bit constant in the range 0x00xFF (0–255). Those values can also be rotated by an even amount.

MVN

MVN can load the bitwise complement of those same values. Numerically that is -(n+1).

You do not need to compute the rotation by hand — the assembler does. You also do not need to choose between MOV and MVN; the assembler picks the right one. That matters when the value is an assembly-time variable.

If you write an immediate the assembler cannot encode, you get:

Immediate n out of range for this operation.

related

  1. Feb 10, 2021/archiveARM: Loading Addresses into Registers
  2. Feb 10, 2021/archiveARM Data Transfer: Pre/Post-Index and STR/LDR
  3. Feb 10, 2021/archiveARM LDR Rd, =const

graphfeed