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

x86-64栈传递多余参数大小及int参数8字节占用疑问

技术问询
  1. 栈传递的多余参数的大小是多少?

C代码

int f(int a, int b, int c, int d, int e, int f, int g, int h, int i) {f = 8; g = 3; h=9; i = 12; return g;}

int main() {
        f(1,2,3,4,5,6,7,8,9);
        return 0;
}

编译后的x86-64汇编(Intel语法)

该代码通过gcc -S -masm=intel sth.c编译为如下汇编:

.file   "passord.c"
        .intel_syntax noprefix
        .text
        .globl  f
        .type   f, @function
f:
.LFB0:
        .cfi_startproc
        push    rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        mov     rbp, rsp
        .cfi_def_cfa_register 6
        mov     DWORD PTR -4[rbp], edi
        mov     DWORD PTR -8[rbp], esi
        mov     DWORD PTR -12[rbp], edx
        mov     DWORD PTR -16[rbp], ecx
        mov     DWORD PTR -20[rbp], r8d
        mov     DWORD PTR -24[rbp], r9d
        mov     DWORD PTR -24[rbp], 8
        mov     DWORD PTR 16[rbp], 3 ; HERE
        mov     DWORD PTR 24[rbp], 9 ; HERE
        mov     DWORD PTR 32[rbp], 12
        mov     eax, DWORD PTR 16[rbp]
        pop     rbp
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE0:
        .size   f, .-f
        .globl  main
        .type   main, @function
main:
.LFB1:
        .cfi_startproc
        push    rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        mov     rbp, rsp
        .cfi_def_cfa_register 6
        push    9
        push    8
        push    7
        mov     r9d, 6
        mov     r8d, 5
        mov     ecx, 4
        mov     edx, 3
        mov     esi, 2
        mov     edi, 1
        call    f
        add     rsp, 24
        mov     eax, 0
        leave
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE1:
        .size   main, .-main
        .ident  "GCC: (Debian 12.2.0-14) 12.2.0"
        .section        .note.GNU-stack,"",@progbits

疑问聚焦

关注如下汇编片段:

mov     DWORD PTR 16[rbp], 3
        mov     DWORD PTR 24[rbp], 9

第7个参数与第8个参数的地址差为8字节,而由寄存器传递的参数存入局部内存时为4字节值,但所有参数均为int类型。为何栈传递的参数使用8字节空间?目前已查阅《System V ABI》第17页,但仍不确定原因,特此问询。


解答

栈传递的每个参数占用8字节空间,这是x86-64 System V ABI的强制规定,核心原因有两点:

  1. 维护栈对齐要求
    x86-64 System V ABI明确规定,调用函数前栈指针rsp必须保持16字节对齐。执行call指令会压入8字节的返回地址,进入函数后rsp变为16n-8;再执行push rbp后,rsp变为16n-16,此时rbp指向的栈帧基址是16字节对齐的。栈参数从rbp+16开始分配,每个参数占8字节,确保后续所有栈操作始终符合对齐规范,避免因对齐错误导致的性能问题或硬件异常。

  2. 简化栈操作逻辑
    统一使用8字节的参数槽位,不管参数本身的大小(哪怕是4字节的int),可以让调用者和被调用者的栈偏移计算更简单,无需根据参数类型调整分配空间,降低了编译和运行时的复杂度。

结合你的代码验证:

  • main函数中传递3个栈参数后,用add rsp,24恢复栈指针,24字节正好对应3个8字节的参数槽位;
  • 函数f中第7个参数g的地址是rbp+16,第8个参数h是rbp+24,间隔8字节,完全符合ABI规定的栈参数布局。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 14:24:53