I'm compiling some test code for an embedded ARM chip using a test C file.
test.c
is as follows:
int main(){
*(int*)0xFFFFF400 = 7;
}
I compile the file with the following command
arm-none-eabi-gcc -march=armv4 -mtune=arm7tdmi -specs=nosys.specs -Wall -o test test.c
Which compiles without complaint, then I examine the assembly with
arm-none-eabi-objdump -d ./test
Which produces a long output with the following main()
section:
00008018 <main>:
8018: e3e03000 mvn r3, #0
801c: e3a02007 mov r2, #7
8020: e3a00000 mov r0, #0
8024: e5032bff str r2, [r3, #-3071] ; 0xfffff401
8028: e1a0f00e mov pc, lr
Why does it say 0xfffff401 instead of 0xfffff400? Why is it subtracting 3071 instead of 3072?
The mvn
instruction writes the bitwise inverse of its operand to a register. The bitwise inverse of 0 is all 1 bits, which, in two’s complement, represents −1. Then the address [r3, #-3071]
is −1 + −3071 = −3072.
I do not know why the compiler is choosing to base its addressing off −1 rather than 0.