反汇编的 arm 代码似乎有一个错误

Disassembled arm code seems to have off by one error

我正在使用测试 C 文件为嵌入式 ARM 芯片编译一些测试代码。

test.c如下:

int main(){
  *(int*)0xFFFFF400 = 7;
}

我用下面的命令编译文件

arm-none-eabi-gcc -march=armv4 -mtune=arm7tdmi -specs=nosys.specs -Wall -o test test.c

编译无怨无悔,然后我用

检查程序集
arm-none-eabi-objdump -d ./test

这会产生包含以下 main() 部分的长输出:

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

为什么说 0xfffff401 而不是 0xfffff400?为什么减去 3071 而不是 3072?

mvn 指令将其操作数的按位取反写入寄存器。 0 的按位取反是全 1 位,用二进制补码表示 -1。那么地址[r3, #-3071]就是−1 + −3071 = −3072.

我不知道为什么编译器选择基于 −1 而不是 0 进行寻址。