Calling Convention of Floats in Nasm

二次信任 提交于 2020-01-17 03:43:06

问题


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 doubles in memory on the call-stack, they take twice as much space as integers / pointers / floats. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!