X86-64 体系结构上 C语言的函数参数的传递

函数参数的传递用的是通用寄存器或堆栈,是可以由编译器来决定的,不过一般都会遵守特定规则,以GCC为例,看一下其在X86和X64上是什么情况

测试代码:

int test6(int p1, int p2, int p3, int p4, int p5, int p6)
{
        return p1+p2+p3+p4+p5+p6;
}
int test7(int p1, int p2, int p3, int p4, int p5, int p6, int p7)
{
        return p1+p2+p3+p4+p5+p6+p7;
}
int main()
{
        test6(301,302,303,304,305,306);
        test7(301,302,303,304,305,306,307);
}

在X64平台上,生成的部分汇编文件:

main:
.LFB2:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        movl    $306, %r9d
        movl    $305, %r8d
        movl    $304, %ecx
        movl    $303, %edx
        movl    $302, %esi
        movl    $301, %edi
        call    test6
        pushq   $307
        movl    $306, %r9d
        movl    $305, %r8d
        movl    $304, %ecx
        movl    $303, %edx
        movl    $302, %esi
        movl    $301, %edi
        call    test7
        addq    $8, %rsp
        movl    $0, %eax
        leave
        .cfi_def_cfa 7, 8
        ret

可以看到,对于六个参数的函数,依次用了edi, esi, edx, ecx, r8d, r9d六个寄存器实现参数传递。而对于七个参数的函数,最后一个参数用栈来传递。

在32位结构上,情况却不太相同:

main:
.LFB2:
        .cfi_startproc
        pushl   %ebp
        .cfi_def_cfa_offset 8
        .cfi_offset 5, -8
        movl    %esp, %ebp
        .cfi_def_cfa_register 5
        call    __x86.get_pc_thunk.ax
        addl    $_GLOBAL_OFFSET_TABLE_, %eax
        pushl   $306
        pushl   $305
        pushl   $304
        pushl   $303
        pushl   $302
        pushl   $301
        call    test6
        addl    $24, %esp
        pushl   $307
        pushl   $306
        pushl   $305
        pushl   $304
        pushl   $303
        pushl   $302
        pushl   $301
        call    test7
        addl    $28, %esp
        movl    $0, %eax
        leave
        .cfi_restore 5
        .cfi_def_cfa 4, 4
        ret

所有的参数都用栈来传递。

了解函数参数的传递方式,对于程序调试和bug的分析,可以提供一定帮助。

猜你喜欢

转载自www.cnblogs.com/yuanjianye/p/9301978.html