carmembeddedarm-none-eabi-gcc

Disassembled arm code seems to have off by one error


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?


Solution

  • 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.