问题描述
我目前正在研究按值传递结构。 我有以下代码:
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页描述了参数的分类。
聚集(结构和数组)和联合类型的分类如下:
- 如果对象的大小大于四个八字节,或者它包含未对齐的字段,则它具有MEMORY类。 (
S2
的大小为2*sizeof(double)+sizeof(int)=24
,因此少于32个字节。)
...跳过2,因为它指的是C ++。...
- 如果聚合的大小超过一个八字节,则将每个分类。每个八字节初始化为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;
然后如何传递每个参数:
- 如果该类是INTEGER,则使用%rdi,%rsi,%rdx,%rcx,%r8和%r9序列的下一个可用寄存器
- 如果类是SSE,则使用下一个可用的向量寄存器,这些寄存器的顺序为%xmm0到%xmm7。
所以我对寄存器分配的建议如下:
xmm0: d1
xmm1: d2
rsi: a
这显然是错误的,如编译器所显示的那样,它使用堆栈来传递参数。
我的错误在哪里?我错过了什么细节?
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)