我有一个使用 GCC v6.3 编译的应用程序,当我使用 GCC v10.3 编译它时,我发现一些函数使用的堆栈大小比 GCC v6.3 使用的更大,例如,这个函数对 GCC v6.3 使用零堆栈但 GCC v10.3 使用 8 个字节
int func(int *x, int y, int z, int a)
{
switch (y) {
case 1:
*x = a;
y = z;
return y;
}
return 77; // UPDATE
}
GCC v6.3 程序集:
int func(int *x, int y, int z, int a)
{
switch (y) {
0: 2901 cmp r1, #1
2: d102 bne.n a <func+0xa>
case 1:
*x = a;
4: 6003 str r3, [r0, #0]
y = z;
return y;
6: 0010 movs r0, r2
}
return 77;
}
8: 4770 bx lr
return 77;
a: 204d movs r0, #77 ; 0x4d
c: e7fc b.n 8 <func+0x8>
和 GCC v10.3 程序集:
int func(int *x, int y, int z, int a)
{
0: b510 push {r4, lr}
2: 0004 movs r4, r0
*x = a;
y = z;
return y;
}
return 77;
4: 204d movs r0, #77 ; 0x4d
switch (y) {
6: 2901 cmp r1, #1
8: d101 bne.n e <func+0xe>
return y;
a: 0010 movs r0, r2
*x = a;
c: 6023 str r3, [r4, #0]
}
e: bd10 pop {r4, pc}
在 GCCv10.3 中,它推送 {r4, lr} 而在 GCC v6.3 中不是这种情况,为什么会发生这种情况?,它比旧编译器花费应用程序更多的堆栈区域,所以如何避免它以获得更少的堆栈尺寸?另外,虽然它是一个叶子函数,但为什么它会堆叠 lr ?另外,为什么它在所有情况下都返回 z 虽然 c 代码在 case 条件内返回它?(更新:这已通过在函数末尾添加返回来解决)
笔记:
- 这个函数是一个虚拟函数,只是为了重现问题,所以不要考虑重写它。
- 构建标志是: arm-none-eabi-gcc -O0 -c -std=c99 -fmessage-length=0 -fomit-frame-pointer -Wno-aggressive-loop-optimizations -Werror -Werror=strict-prototypes -pedantic-错误 -Wconversion -pedantic -Wall -Wextra -Wno-unused-function -Wextra -Wpointer-arith -Wsign-compare -Wswitch -Wno-maybe-uninitialized -fno-strict-aliasing -fshort-wchar -mfix-cortex-m3- ldrd -gdwarf-3 -gstrict-dwarf -mabi=aapcs -mthumb -mcpu=Cortex-M0 -g3 -Os -mthumb -ffunction-sections -fdata-sections -MMD -MP -MF"xyz.d" -MT"xyz .o"