返回结构时的陌生人编译器行为

问题描述

我是C和汇编代码的新手,只是一个关于返回结构的问题,下面是我的代码

// c code
struct MyObj{
   int x,y,z;
};

struct MyObj foo(){
    struct MyObj foo_a;
    foo_a.x = 1;
    foo_a.y = 2;
    foo_a.z = 3;

    return foo_a;
}        

int main () {
    struct MyObj main_a = foo();

    printf("value is %d\n",main_a.x);
    return 0;
}
//assembly code
foo:
        movl    $1,-20(%rsp)  //<----- allocate 20 bytes on the stack?
        movl    $2,-16(%rsp)
        movq    -20(%rsp),%rax
        movl    $3,%edx
        ret
.LC0:
        .string "value is %d\n"
main:
        subq    $24,%rsp       // <----allocate 24 bytes on stack by decrementing stack pointer by 24
        movl    $0,%eax
        call    foo
        movl    %eax,%esi
        movl    $.LC0,%edi
        movl    $0,%eax
        call    printf
        movl    $0,%eax
        addq    $24,%rsp
        ret

以下是我的问题:

Q1-您可以看到,在foo方法的堆栈中,似乎为foo_a分配了20个字节。对于大多数功能,gcc通常在ret之前先取消分配栈,例如

somefunc:
   subq $16,%rsp
   ...
   addq $16,%rsp
   ret
   

但是ret中的foo指令之前没有取消分配堆栈指令,为什么?编译器是否故意这样做,因为它释放了foo的堆栈,那么我们无法将struc返回给函数?如果是出于这个目的,那么我就能理解为什么foo中没有栈的重新分配。

Q2-似乎堆栈上foo_a的内部结构是3|2|1而不是1|2|3,为什么编译器会以错误的方式处理问题?

为什么要在movl $3,%edx方法中使用foo?不应该是movl $3,-12(%rsp)吗?可能是我没有在foo_a.z中引用main但在foo_a.y中也没有引用main且指令仍然是{{1}的原因之一}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...