0
votes

I don't get why I can't write mov r1, #5000. Why I have to use ldr instead? R1 is 32 bit register and 5000 fits in range. And as I discovered I can mov r1, #255 but can't mov r1, #256. It seems weird for me.

2
This question has already been asked dozen of times. See: Contants on ARM blog.artless noise

2 Answers

4
votes

read the documentation on the instructions, in this context the instructions are fixed length, so you dont have room for both the instruction information (opcode, etc) and a 32 bit immediate in the 16 or 32 bit instruciton, not possible so some limitation on the immediate is required. With x86 for example it is variable instruction length so they can have long instructions, but it is easy to argue that doing a pc-relative load or a few fixed length instructions of the same size have no significant extra cost with a pipeline. so six of one half dozen of another. The mips fixed instruction length move immediate solution has its strengths and weakness and for each of the arm instruction sets each has its own solution with strengths and weaknesses.

for arm the assemblers (certainly gcc, probably arms toolchain, keil, etc) there is a shortcut you can do and the assembler will choose the simpler path

ldr r1,=immediate

if it cant encode it into a single instruction (note there are some move negative, math with the program counter and other tricks it can play that you might not be thinking of at the time or not knowing the pc might not be able to use), if it cannot then it may encode it as multiple instructions mov immediate then an orr, or encode it as a pc relative load.

The specific limitations for each instruction sets mov immediate is well documented in the arm architectural reference manuals, you can just get the armv7 one and it has all the encodings for that and prior architecture versions. with that knowledge you should be able to determine yourself whether or not the mov will work before having the assembler tell you.

1
votes

In ARM Cortex-M3 MOV is 16bit instruction with following definition MOV<c>{<q>} <Rd>, #<imm8> Immediate values are stored as part of opcode in arm instructions

opc[15:11]='b00100 =>which identifies instruction.
opc[10:8]=<register no>
opc[7:0]=<imm8 value>

So, with above instruction you can have 2^8 -1 =>255 as maximum immediate value

Though by specifying instruction specifier .W you can force assembler to pick32 bit encoding for MOV, but that will only have 11bit of immediate value

You can use T3 version of MOV having 16bit of immediate value support where you can move 0 to 65535 to a register

So instead of mov r1, #5000 you can use following instruction to load any value to a register from 0 to 65535

MOVW r1, #5000