You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ARM编译器栈填充:栈指针指向内容与变量间隙技术问询

ARM栈相关问题分析与解答

原函数代码

#include <string.h>

void  func1(char *s)
{
  char buffer[4];
  strcpy(buffer, s);
}

编译命令与版本

$ arm-linux-gnueabi-gcc -g -fno-stack-protector  func1.c -c -o func1.o
$ arm-linux-gnueabi-gcc --version
arm-linux-gnueabi-gcc (Ubuntu 13.2.0-4ubuntu3) 13.2.0

反汇编结果

$ arm-linux-gnueabi-objdump  --disassemble=func1 -S func1.o
void  func1(char *s)
{
    0:   e92d4800        push    {fp, lr}
    4:   e28db004        add     fp, sp, #4
    8:   e24dd010        sub     sp, sp, #16
    c:   e50b0010        str     r0, [fp, #-16]
  char buffer[4];
  strcpy(buffer, s);
    10:   e24b3008        sub     r3, fp, #8
    14:   e51b1010        ldr     r1, [fp, #-16]
    18:   e1a00003        mov     r0, r3
    1c:   ebfffffe        bl      0 <strcpy>
}
    20:   e1a00000        nop                     @ (mov r0, r0)
    24:   e24bd004        sub     sp, fp, #4
    28:   e8bd8800        pop     {fp, pc}

栈内容分析(调用strcpy()后,指令0x20处)

|---+---+---+---|
fp - 20  |   ?????????   | <- current $sp
         |---+---+---+---|
fp - 16  |   char * s    | <- $r1
         |---+---+---+---|
fp - 12  |   ?????????   |
         |---+---+---+---|
fp - 8   | char buffer[] | <- $r0, $r3
         |---+---+---+---|
fp - 4   |   prev $fp    | <- $sp after push
         |---+---+---+---|
         |      $lr      | <- $fp
         |---+---+---+---|
         |   |   |   |   | <- $sp that had the calling function
         |---+---+---+---|
                 .
                 .
                 .

         ^
         | descending addresses

问题解答

  1. ARM满递减栈模式下$sp指向的内容
    在ARM满递减(Full Descending, FD)栈模式中,$sp指向当前栈帧里最后一个被分配、已标记为占用的栈空间位置(即栈图中的fp - 20处)。这个空间属于当前函数的栈帧范围,但属于未初始化的空白区域,没有存放有效业务数据;按照ARM调用约定,被调用函数不会主动使用该位置,只会使用自身分配的栈空间或约定的栈区域。

满递减栈的核心行为是:压栈时先将$sp递减,再写入数据;出栈时先读取$sp指向的数据,再递增$sp,因此$sp始终指向栈中已占用的最低地址(最高偏移)位置。

  1. 局部变量间未使用空间的原因
    这是栈对齐规则导致的填充空间。ARM EABI(应用二进制接口)要求栈指针必须保持8字节或16字节的对齐(此处GCC遵循标准ARM EABI的8字节对齐要求),未对齐的内存访问可能触发硬件异常,或导致处理器性能下降,因此编译器会自动填充空隙以满足对齐要求。

在当前函数中:

  • 压入fp和lr占用8字节,此时栈处于对齐状态;
  • 执行sub sp, sp, #16分配16字节局部空间,维持栈的对齐;
  • 局部变量buffer[4]和参数s总共仅占用8字节,剩余的4字节(fp - 12处)就是为满足栈对齐要求而填充的空隙。

内容的提问来源于stack exchange,提问作者Isidro Arias

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 13:26:03