For some reason, when I try to compile this bit of code, the compiler says syscall.s:72:invalid constant (0x172) after fixup:
.globl _mach_msg_trap$MACH
_mach_msg_trap$MACH:
stmfd sp!, {r4,r7}
mov r7, #370 /* this is line 72 */
svc 0
ldmfd sp!, {r4, r7}
bx lr
I don’t know why it’s doing it. When I put a smaller constant into r7, it works fine. But with higher numbers, it spits out this error. I’ve temporary fixed it by doing mov r7, #300 and add r7, #70, which achieves the desired effect. Still not sure what caused the error though.
The ARM Instruction Set, up to ARMv5, is only able to use a limited range of immediate values. The problem is that the value has to be encoded in the instruction itself. As all ARM Instructions are 32-bit wide, the original instruction-set up to ARMv5 only had a total of 8+4 bits to encode immediates. With the first 8-bit being able to load any 8-bit value in the range of 0-255 and the 4 bit being a right rotate in steps of 2 between 0 and 30.
So you can load values like:
But, #370 is not loadable with this scheme, it would require something like
#185 ror #31which is not possible.There are two ways to get your immediate value loaded.
ldr r7,=#370The assembler then will create a constant-pool and load the value from there via pc-relative addressing.Usually you should prefer to construct constants with up to 2 instructions, if thats not possible (or the value has to be relocatable) use ldr.
Starting with ARMv7 you can also use
movwto load any 16 bit value in the lower half of a register while zeroing the top-half andmovtto load another 16bit value to the upper half without touching the lower half.