C 为什么两个double的结构通过寄存器传递,而三个double的结构通过堆栈传递?
以下代码:C 为什么两个double的结构通过寄存器传递,而三个double的结构通过堆栈传递?,c,struct,calling-convention,cdecl,C,Struct,Calling Convention,Cdecl,以下代码: struct Double2{ 双a; 双b; }; 结构双重3{ 双a; 双b; 双c; }; double double2(结构double2 x){ 返回x.a+x.b; } double double3(结构double3 x){ 返回x.a+x.b+x.c; } 双双参数(双a、双b、双c){ 返回a+b+c; } 编译成 double2: addsd xmm0, xmm1 ret double3: movsd xm
struct Double2{
双a;
双b;
};
结构双重3{
双a;
双b;
双c;
};
double double2(结构double2 x){
返回x.a+x.b;
}
double double3(结构double3 x){
返回x.a+x.b+x.c;
}
双双参数(双a、双b、双c){
返回a+b+c;
}
编译成
double2:
addsd xmm0, xmm1
ret
double3:
movsd xmm0, QWORD PTR [rsp+8]
addsd xmm0, QWORD PTR [rsp+16]
addsd xmm0, QWORD PTR [rsp+24]
ret
double_args:
addsd xmm0, xmm1
addsd xmm0, xmm2
ret
在Linux上,x86-64和GCC 9.2以及-O3()
为什么两个双精度(Double2
)的结构通过寄存器xmm0
和xmm1
传递,而三个双精度(Double3
)的结构通过堆栈传递double_args()
说明编译器至少能够通过寄存器传递三个double
这是C调用约定的一部分吗?相关规则是什么?您需要找到所使用的实现的(ABI)。调用约定依赖于实现,C规范对此没有任何说明。这是编译器开发人员的决定。显然,对于三个双精度的结构,没有足够的寄存器。@user3386109我想你是对的。它可能在这个文件中的某个地方被指定:例如,查看[System V ABI[draft version]](System V ABI[draft version]),一个三重结构有三个SSE类成员(第19页),然后,由于结构超过了“两个八字节”,后两个不在SSEUP类中,整个参数被传递到内存中(第21页第5项)。但是我已经有一段时间没有阅读/使用/解释这个ABI了,所以我可能会离开。你需要找到你正在使用的实现的(ABI)。调用约定依赖于实现,C规范对此没有任何说明。这是编译器开发人员的决定。显然,对于三个双精度的结构,没有足够的寄存器。@user3386109我想你是对的。它可能在这个文件中的某个地方被指定:例如,查看[System V ABI[draft version]](System V ABI[draft version]),一个三重结构有三个SSE类成员(第19页),然后,由于结构超过了“两个八字节”,后两个不在SSEUP类中,整个参数被传递到内存中(第21页第5项)。但是我已经有一段时间没有阅读/使用/解释这个ABI了,所以我可能会离开。