首页 > 解决方案 > 当我们将结构传递给函数时会发生什么?

问题描述

假设我们将一个结构传递给一个函数:

struct rect {
    long llx;
    long lly;
};

long test() {

    struct rect oldRect;
    oldRect.llx = 1;
    oldRect.lly = 2;

    struct rect newRect = make_double(oldRect);
    return newRect.llx * newRect.lly;
}

struct rect make_double(struct rect r) {
    r.llx *= 2;
    r.lly *= 2;
    return r;
}

为了更深入地了解传递结构变量时实际发生的情况,我将 C 代码编译为程序集,如下所示:

// remove some directives that affects readibility
test:
   subq $56, %rsp
   movl $1, %edi     
   movl $2, %esi    
   call make_double
   imulq    %rdx, %rax
   addq $56, %rsp
   ret

make_double:
   leaq (%rsi,%rsi), %rdx
   leaq (%rdi,%rdi), %rax
   ret

有趣的是,当传递 struct 时oldRect,gcc 实际上将其成员复制到寄存器中,这些寄存器将用作函数中的参数make_double。所以我的问题是:

Q1-只是确认当传递一个结构变量时,编译器会获取结构的所有成员并将它们复制到寄存器,我的理解/观察是否正确?

Q2-由于编译器oldRect通过递减堆栈指针为 分配内存空间,但编译器实际上并没有分别将 1 和 2 分别推送到oldRect.llxoldRect.lly如果是这种情况,编译器甚至不需要首先递减堆栈指针?

Q3-我对这条指令有点困惑:

 subq   $56, %rsp

为什么我们必须将堆栈指针减 56?的大小struct rect是16,不需要填充,为什么不需要

subq   $16, %rsp

标签: cassemblystructx86-64calling-convention

解决方案


推荐阅读