2

我有一个使用 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 条件内返回它?(更新:这已通过在函数末尾添加返回来解决)

笔记:

  1. 这个函数是一个虚拟函数,只是为了重现问题,所以不要考虑重写它。
  2. 构建标志是: 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=Cort​​ex-M0 -g3 -Os -mthumb -ffunction-sections -fdata-sections -MMD -MP -MF"xyz.d" -MT"xyz .o"
4

0 回答 0