FLD指令x64位

问题描述 投票:5回答:3

我在x64位中的FLD指令有一点问题...想要将st0加载到st0寄存器中的堆栈指针FPU,但它似乎是不可能的。在Delphi x32中,我可以使用以下代码:

function DoSomething(X:Double):Double;
asm

  FLD    X
   // Do Something ..
  FST Result

end;

不幸的是,在x64中,相同的代码不起作用。

delphi assembly x86-64 fpu basm
3个回答
4
投票

在x64模式下,浮点参数在xmm寄存器中传递。因此,当Delphi尝试编译FLD X时,它变为FLD xmm0,但是没有这样的指令。首先需要将其移动到内存中。

结果相同,应该在xmm0中传回。

试试这个(未经测试):

function DoSomething(X:Double):Double;
var
  Temp : double;
asm
  MOVQ qword ptr Temp,X
  FLD Temp
  //do something
  FST Temp
  MOVQ xmm0,qword ptr Temp
end;

5
投票

德尔福继承了qazxsw poi。因此,如果函数/过程的参数是float / double,则它们将在XMM0L,XMM1L,XMM2L和XMM3L寄存器中传递。

但您可以在参数之前使用Microsoft x64 Calling Convention作为解决方法,如:

var

0
投票

您不需要在x86-64代码中使用旧版x87堆栈寄存器,因为SSE2是基线,是x86-64 ISA的必需部分。你可以而且应该在XMM寄存器上使用function DoSomething(var X:Double):Double; asm FLD qword ptr [X] // Do Something .. FST Result end; addsdmulsd等进行标量FP数学运算。 (或sqrtsd浮动)

Windows x64调用约定在XMM0..3中传递float / double FP args,如果它们是函数的前四个args之一。 (即,如果它是FP,则第3个总arg以xmm2为单位,而不是以xmm2为单位的第3个FP arg。)它返回XMM0中的FP值。

如果您的功能内部确实需要80位精度,则仅使用x87。 (像addssfsin这样的指令并不快,通常也可以通过使用SSE / SSE2指令的普通数学库来完成。

fyl2x

存储到内存并重新加载到x87寄存器会花费大约10个周期的延迟而没有任何好处。 SSE / SSE2标量指令与x87等效指令一样快或更快,更容易编程和优化,因为你从不需要function times2(X:Double):Double; asm addsd xmm0, xmm0 // upper 8 bytes of XMM0 are ignored ret end ;它是一个扁平寄存器设计而不是基于堆栈的设计。 (fxch)。此外,您有15个XMM寄存器。


当然,您通常根本不需要内联asm。如果编译器不为您执行此操作,则可能对手动矢量化很有用。

© www.soinside.com 2019 - 2024. All rights reserved.