MOV
This instruction can take many forms, depending on the value needed to be moved. And it changes if the value is a register or if it is an immediate. If it is in a register, then it produces an ORR
instruction (ORR <Xd>, XZR, <Wm>
)*. If it is using the SP
(Stack Pointer) it produces an ADD
instruction (ADD <Xd|XSP>, <Xn|XSP>, #0
)*. If moving an immediate, then it is one of the MOVZ, MOVK or MOVN instructions.
*These are the 64-bit prototypes.
XZR
is the zero register and its value is always zero. The XZR
and the SP
share are identified by the same number (31), that is why an ORR
instruction cannot be used when the SP
is the destination or an operand. Instead the ADD
instruction is used.
MOVZ and MOVK
These two instructions are sometimes used one after the other.
And they are used to move immediate values.
MOVZ
moves an immediate value (16-bit value) to a register, and all the other bits outside the immediate value are set to Zero. The immediate can be shifted to the left 0
, 16
, 32
or 48
. MOVK
moves an immediate value but leaves the other bits of the register untouched (the K
is for keep). For example, let's say you need to move this value 0x7fb7fb1f88
to register x0
. First, you will move the first 16 bits (bits 0 to 15) with a MOVZ
instruction, so the rest bits of the register are set to zero. And then you will move the second 16 bits (bits 16 to 31) with a MOVK
instruction, so the value moved before (the first 16 bits) remains in the register, and you do the same with the other resting bits.
instruction value of x0
mov x0, #0x1f88 | 0x1f88
movk x0, #0xb7fb, lsl #16 | 0xb7fb1f88
movk x0, #0x7f, lsl #32 | 0x7fb7fb1f88
MOVN
MOVN
is usually used for moving bitmasks, here the N
stands for negated. Let's say you want to move the bitmask 0xffffffff0000ffff
to x0.
Then you will move 0xffff
shifted to the left 16, that will make the value 0x00000000ffff0000
. Negating this values becomes 0xffffffff0000ffff.
Here is an example:
instruction value of x0
MOVN x0, 0xFFFF, lsl 16 | 0xffffffff0000ffff