如何在 Linux asm 中正确返回双精度值

How to properly return a double in linux asm

本文关键字:返回 双精度 Linux asm      更新时间:2023-10-16

当我调用函数时,它返回 0.0000,而它应该返回 25.0000

我尝试寻找类似的问题,但我找不到。我尝试查看英特尔的手册,但到目前为止没有任何效果。

我通过 c++ 调用函数

double t=floatingPointTest(5);
printf("%fn",t);

asm 函数:

floatingPointTest:
push    rbx
push    rbp
mov     rbp,rsp
cvtsi2sd    xmm0,rdi
cvtsi2sd    xmm1,rdi
mulsd       xmm0,xmm1
mov     rsp,rbp
pop     rbp
pop     rbx
ret

即使 rdi 是 0.0000,我也得到 5

您没有向我们展示关键信息 - 您使用的函数floatingPointTestC++原型是什么。有几件事可能会导致这种行为。

  • 您声明floatingPointTestfloatdouble作为函数的第一个参数,而它应该是整数。程序集代码使用以下指令:

    cvtsi2sd    xmm0,rdi
    

    我们可以推断第一个参数(在RDI中(应该是有符号long因为您使用RDI作为源操作数,并且具有 64 位寄存器的cvtsi2sd会将有符号四字整数从 64 位寄存器转换为目标 XMM 寄存器中的双精度浮点值。

  • 您的原型被声明为返回类型为float而不是double。由于您的汇编代码仅执行数学运算,因为标量双精度,因此您需要从函数返回一个double

C++的正确原型可以写成:

extern "C" double floatingPointTest(long val);

观察

您的代码不使用RBX,因此无需保存/还原它。您实际上不需要堆栈帧,您可以通过将相同的寄存器作为源和目标传递给mulsd来单独乘以数字。这段代码将执行相同的操作:

floatingPointTest:
cvtsi2sd    xmm0, rdi
mulsd       xmm0, xmm0
ret