在纳斯姆召集浮动公约

时间:2016-12-01 17:08:34

标签: assembly x86 nasm x86-64

最近我们学习了浮点运算,并将一些问题作为家庭作业 其中之一是:

  

“记下单精度浮点数的调用约定!”。

所以我知道xmm个寄存器,并且知道在双精度时,第一个输入进入xmm0,依此类推。
我在谷歌上查了一下这个话题,却找不到答案。如果有人可以帮我解决这个问题,那就太好了。

1 个答案:

答案 0 :(得分:1)

我熟悉的每个调用约定处理单个floatdouble相同。 (并非所有调用约定都处理它们,只是在一个调用约定中,没有差异)。

有些(如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调用约定类似但不同。请参阅代码wiki中指向ABI文档的链接。 (例如,Windows x64在xmm3中传递第3个arg,即使它是第一个FP arg,而早期的args是整数)。

请注意,printf等可变函数的C规则意味着调用者将float args提升为doubleWhy does printf() promote a float to a double?。单精度没有%转换,只有doublelong doubleHow to print a single-precision float with printf(在asm中)。

请注意,在调用堆栈的内存中传递double的32位调用约定中,它们占用的空间是整数/指针/ float的两倍。因此double占用两个堆栈插槽。

它也可能具有导致填充的8B对齐要求。但他们仍然不是特别的"因为这样:我认为任何其他具有8B对齐要求的8B对象(例如带有alignas(8)成员的结构)都将被视为相同。