最近我们学习了浮点运算,并将一些问题作为家庭作业 其中之一是:
“记下单精度浮点数的调用约定!”。
所以我知道xmm
个寄存器,并且知道在双精度时,第一个输入进入xmm0
,依此类推。
我在谷歌上查了一下这个话题,却找不到答案。如果有人可以帮我解决这个问题,那就太好了。
答案 0 :(得分:1)
我熟悉的每个调用约定处理单个float
与double
相同。 (并非所有调用约定都处理它们,只是在一个调用约定中,没有差异)。
有些(如i386 System V)传递堆栈并返回x87 st(0)。
float foo(float x) { return 2.0f*x; }
; NASM implementation for i386 System V, or Windows cdecl
foo:
fld dword [esp+4] ; arg from the stack, above the return address
fadd st0 ; st0 += st0
ret ; return value = st0
XMM注册表中的一些传递/返回。 (例如x86-64 System V在xmm0..7中传递前8个FP args,并且在xmm0中返回FP返回值。这些XMM寄存器的高位字节不能保证为零,但是有标量像sqrtsd
这样的指令只能在低元素上运行。)
; x86-64 System V, and Windows x64
foo:
addss xmm0, xmm0 ; xmm0 += xmm0, scalar single-precision
ret ; returns in xmm0
(See the compiler-generated GAS .intel_syntax noprefix
versions of these on Godbolt。)
Windows调用约定类似但不同。请参阅x86代码wiki中指向ABI文档的链接。 (例如,Windows x64在xmm3中传递第3个arg,即使它是第一个FP arg,而早期的args是整数)。
请注意,printf
等可变函数的C规则意味着调用者将float
args提升为double
。 Why does printf() promote a float to a double?。单精度没有%
转换,只有double
或long double
。 How to print a single-precision float with printf(在asm中)。
请注意,在调用堆栈的内存中传递double
的32位调用约定中,它们占用的空间是整数/指针/ float
的两倍。因此double
占用两个堆栈插槽。
它也可能具有导致填充的8B对齐要求。但他们仍然不是特别的"因为这样:我认为任何其他具有8B对齐要求的8B对象(例如带有alignas(8)
成员的结构)都将被视为相同。