反汇编的arm代码好像错了一个错误

问题描述

我正在使用测试 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。