按值传递结构时出现意外的程序集输出

问题描述

我目前正在研究按值传递结构。 我有以下代码:

typedef struct s2{
    double d1;
    double d2;
    int a;
}S2;

void f_(S2 s);//Some external function,only used for compiling,so I can see the passing of parameters.

void f(){
    S2 s=(S2){0.5,1.0,1};
    f_(s);
}

如果使用-Og -S -fno-asynchronous-unwind-tables进行编译,则会得到以下程序集输出:

f:
    subq    $48,%rsp
    movq    .LC0(%rip),%rax
    movq    %rax,8(%rsp)
    movq    .LC1(%rip),16(%rsp)
    movl    $1,24(%rsp)
    pushq   24(%rsp)
    pushq   24(%rsp)
    pushq   24(%rsp)
    call    f_@PLT
    addq    $72,%rsp
    ret
    .size   f,.-f
    .section    .rodata.cst8,"aM",@progbits,8
    .align 8
.LC0:
    .long   0
    .long   1071644672
    .align 8
.LC1:
    .long   0
    .long   1072693248

此汇编代码(即,通过堆栈传递)是非常意外的。 查看System V Application Binary Interface。在下面的第17页,概述了参数传递。

第18-19页描述了参数的分类。

聚集(结构和数组)和联合类型的分类如下:

  1. 如果对象的大小大于四个八字节,或者它包含未对齐的字段,则它具有MEMORY类。 (S2的大小为2*sizeof(double)+sizeof(int)=24,因此少于32个字节。)

...跳过2,因为它指的是C ++。...

  1. 如果聚合的大小超过一个八字节,则将每个分类。每个八字节初始化为NO_CLASS类。 (这是正确的。因此我们必须对每个类别进行分类)

一些定义:

_TEOL,char,short,int,long,long long和指针类型(有符号和无符号)的参数位于INTEGER类中。

float,double,_Decimal32,_Decimal64和__m64类型的参数在SSE类中。

每个成员的分类:

typedef struct s2{
    double d1;//SSE
    double d2;//SSE
    int a;//INTEGER
}S2;

然后如何传递每个参数:

  1. 如果该类是INTEGER,则使用%rdi,%rsi,%rdx,%rcx,%r8和%r9序列的下一个可用寄存器
  1. 如果类是SSE,则使用下一个可用的向量寄存器,这些寄存器的顺序为%xmm0到%xmm7。

所以我对寄存器分配的建议如下:

xmm0: d1
xmm1: d2
rsi:  a

这显然是错误的,如编译器所显示的那样,它使用堆栈来传递参数。

我的错误在哪里?我错过了什么细节?

解决方法

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

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

小编邮箱: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...