GCC:为什么常量数据在我的函数中填充,而不是在开始时填充?

GCC:为什么常量数据在我的函数中填充,而不是在开始时填充?,c,gcc,assembly,arm,constants,C,Gcc,Assembly,Arm,Constants,我想对我的系统上不同机器指令使用的周期数进行基准测试(本例为ARM Cortex-M4)。所以我使用一个宏,它重复目标指令多次,在这之前和之后,我读取控制器的周期计数器。在asm转储中,我看到在某个位置填入常量数据(我的循环计数器寄存器的地址)(位置8003140到8003150,用“>”标记): REP宏有点长。这只会增加900个电话 c = __QADD(a,b) 编译器调用: arm-atollic-eabi-gcc -c -mthumb -mcpu=cortex-m4

我想对我的系统上不同机器指令使用的周期数进行基准测试(本例为ARM Cortex-M4)。所以我使用一个宏,它重复目标指令多次,在这之前和之后,我读取控制器的周期计数器。在asm转储中,我看到在某个位置填入常量数据(我的循环计数器寄存器的地址)(位置8003140到8003150,用“>”标记):

REP宏有点长。这只会增加900个电话

    c = __QADD(a,b)
编译器调用:

    arm-atollic-eabi-gcc -c -mthumb -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 -std=gnu90 -DDEBUG=1 -I../Inc -I../CoreSupport -I../DeviceSupport -Ofast -ffunction-sections -fdata-sections -g -Wall -o Application\Main.o ..\Application\Main.c

编译器已使用ldr指令生成代码,ldr指令的地址与PC相对。这些指令只有5位可存储相对地址,因此它们只能访问距离当前程序计数器位置0-124字范围内的数据。这就是编译器把数据放在代码中间的原因。这是拇指的说明


有几种方法可以避免这种情况。可以用使用不同寻址模式的手写程序集替换宏。可以用常量替换变量,避免完全寻址。可以减少调用宏的次数。您可以删除-mthumb标志以生成32位指令,这些指令具有更多位用于寻址。这实际上取决于您想在测试中评估什么。

您忘了发布C源代码……还忘了给出编译命令。因此,请编辑您的问题以改进它!顺便说一句,您可以使用
gcc-fverbose asm-S-O
,也请告诉我们您担心的指令地址。代码/数据在内存中的顺序根本不重要。它是“在开始时填充的”因为这些文字是由前几个指令加载的——文字池通常会放在函数后面,但对于16位ldr/str编码来说,这太远了,无法寻址,所以它只是被转储到它所在的位置并跳过。不同的优化选项可能会更改指令选择,以允许不同的文字池放置。另外,你知道吗?Cortex-M4只支持Thumb指令集,所以drop-mthumb不是一个解决方案。
    c = __QADD(a,b)
    arm-atollic-eabi-gcc -c -mthumb -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 -std=gnu90 -DDEBUG=1 -I../Inc -I../CoreSupport -I../DeviceSupport -Ofast -ffunction-sections -fdata-sections -g -Wall -o Application\Main.o ..\Application\Main.c