问题
So recently we learned about floating point operations and got a few questions as a homework.
One of those is:
"Write down the calling convention of single precision floats!".
So i know about the xmm
registers and know that on double precision the first input goes into xmm0
and so on.
I looked up the topic on Google but couldn't find the answer. Would be nice if someone could help me on this question.
回答1:
Every calling convention I'm familiar with handles single float
the same as it does double
. (Not that all calling conventions handle them the same, just that within one calling convention there's no diff).
Some (like i386 System V) pass on the stack and return in 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
Some pass / return in XMM registers. (e.g. x86-64 System V passes the first 8 FP args in xmm0..7, and an FP return value is returned in xmm0. The upper bytes of those XMM registers isn't guaranteed to be zero, but there are scalar instructions like sqrtsd
that only operate on the low element.)
; 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 calling conventions are similar but different. See links to ABI docs in the x86 tag wiki. (e.g. Windows x64 passes the 3rd arg in xmm3, even if it's the first FP arg and the earlier args were integer).
Note that C rules for variadic functions like printf
mean that float
args are promoted to double
by the caller. Why does printf() promote a float to a double?. There is no %
conversion for single-precision, only double
or long double
. How to print a single-precision float with printf (in asm).
Note that in 32-bit calling conventions that pass double
s in memory on the call-stack, they take twice as much space as integers / pointers / float
s. So a double
takes up two stack slots.
It may also have an 8B alignment requirement leading to padding. But they're still not "special" because of this: any other 8B object with an 8B alignment requirement (e.g. a struct with an alignas(8)
member) would be treated the same, I think.
来源:https://stackoverflow.com/questions/40916438/calling-convention-of-floats-in-nasm