Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 64位asm编译错误_Delphi_Assembly_Delphi Xe2_32bit 64bit_Fpu - Fatal编程技术网

Delphi 64位asm编译错误

Delphi 64位asm编译错误,delphi,assembly,delphi-xe2,32bit-64bit,fpu,Delphi,Assembly,Delphi Xe2,32bit 64bit,Fpu,以下函数不使用64位Delphi XE2编译器编译。(所有错误都与fld指令有关。) 第12行和第13行: fld Y fld X 第20行: fld X 不幸的是,我没有汇编技能,我正在使用这个第三方代码,我需要将其移植到64位。你能帮我让它同时在32位和64位上工作吗 function PartArcTan(Y, X: Extended): Extended; asm fld Y // st(0) = Y fld X // st

以下函数不使用64位Delphi XE2编译器编译。(所有错误都与
fld
指令有关。)

第12行和第13行:

fld Y
fld X
第20行:

fld X
不幸的是,我没有汇编技能,我正在使用这个第三方代码,我需要将其移植到64位。你能帮我让它同时在32位和64位上工作吗

function PartArcTan(Y, X: Extended): Extended;
asm
  fld Y              // st(0) = Y
  fld X              // st(0) = X
  fpatan             // st(0) = ArcTan(Y, X)
  fwait
end;

function ArcSin(X: Extended): Extended; // -1 <= X <= 1
asm
  fld X               // st(0) = X
  fld st(0)           // st(1) = X
  fmul st(0), st(0)   // st(0) = Sqr(X)
  fld1                // st(0) = 1
  fsubrp st(1), st(0) // st(0) = 1 - Sqr(X)
  fsqrt               // st(0) = Sqrt(1 - Sqr(X))
  fpatan              // st(0) = ArcTan(X, Sqrt(1 - X*X))
  fwait
end;
函数PartArcTan(Y,X:扩展):扩展;
asm
fld Y//st(0)=Y
fld X//st(0)=X
fpatan//st(0)=ArcTan(Y,X)
fwait
结束;

函数arcin(X:Extended):Extended;//-1该代码移植到x64的主要问题是使用了错误的浮点单元。在x64上,浮点运算在SSE单元上完成

是的,x87单元仍然存在,但相比之下速度较慢。另一个问题是x64 ABI假设您将使用SSE单元。参数到达SSE寄存器。浮点值在SSE寄存器中返回。在SSE和x87单元之间传输值是毫无意义的(更不用说相当辛苦和耗时)。此外,浮点控制、异常掩码都是为SSE单元初始化的,但您确定它们将为SSE单元正确设置

因此,鉴于所有这些,我强烈建议您确保所有浮点代码都在x64下的SSE单元上执行。我认为使用x87寄存器的唯一理由是需要10字节扩展类型的算法,该类型在x87上受支持,但在SSE上不受支持。这里的情况并非如此

现在,移植到SSE单元并不像将操作码转换为SSE等价物那么简单。这是因为苏格兰和南方能源公司的浮动机组的内置能力要小得多。例如,SSE操作码中不包含三角函数

因此,正确的处理方法是切换到使用Pascal代码。这些功能可以分别替换为和


为了详细说明这一点,让我们看看在x64下对x87单元进行计算所涉及的内容。
arcin
的代码如下:

function ArcSin(X: Double): Double;
// to be 100% clear, do **not** use this code
asm
  movq [rsp-8], xmm0     // X arrives in xmm0, move it to stack memory
  fld qword ptr [rsp-8]  // now load X into the x87 unit
  fld st(0)              // calculation code exactly as before
  fmul st(0), st(0)
  fld1
  fsubrp st(1), st(0)
  fsqrt
  fpatan
  fwait
  fstp qword ptr [rsp-8] // but now we need to move the return value
  movq xmm0, [rsp-8]     // back into xmm0, again via the stack
end;
注意事项:

  • x64 ABI表示输入参数到达xmm0。我们无法将其直接加载到x87单元中。因此,我们必须从xmm0传输到堆栈上的暂存内存,然后从那里加载到x87单元
  • 在返回值时,我们必须执行类似的操作。该值以xmm0的形式返回,由ABI指定。因此,我们需要移出x87单元,对堆栈内存进行擦除,然后加载到xmm0中
  • 我们完全忽略了浮点控制字:异常屏蔽、精度和舍入控制等。如果要这样做,您需要建立一种机制,以确保x87单元的控制字以正常的方式处理

  • 因此,这也许可以作为对希望使用x87在x64下执行浮点运算的未来访问者的警告。

    x64仍然支持经典浮点单元,但您需要调整代码以遵循不同的ABI

    x32/x64示例:

    function PartArcTan(X: double): double;
    asm
    {$IFDEF CPUX64}
            movq [rsp-8], xmm0
            fld    qword ptr [rsp-8]
    {$ELSE}
            fld    qword ptr X
    {$ENDIF}
            fld1
            fpatan
            fwait
    {$IFDEF CPUX64}
            fstp   qword ptr [rsp-8]
            movq   xmm0, [rsp-8]
    {$ENDIF}
    end;
    

    正如大卫在回答中提到的,可能重复使用和更正,应该是。根本不要使用asm。在64位Delphi XE2中有一个使用x87 FPU的第三方单元。编写它是为了在8字节(双精度)浮点类型不够的情况下重新启用10字节(扩展)数据类型进行计算。OTOH它的工作速度甚至比x86 DCC原生x87还要慢-因为编译器外的单元无法分析优化的代码流,必须在每条语句后插入
    FWAIT
    opcode。@Aroch Delphi编译器在浮点代码生成器中不进行优化,而是在每条语句后插入FWAIT。x87代码在x64下运行缓慢还有其他原因。但是80位精度是考虑在x64下使用x87操作码的唯一原因。在x64下运行时,x87单元的控制字处于什么状态?什么是“它被禁用”?@GJ.,我认为在asm中这样做毫无意义。使用RTL函数支持所有平台。在这里使用asm几乎没有什么好处(如果没有),只有困惑,这个答案似乎增加了一点。AFAICS问题中只有一个问题:“你能帮我让它在32位和64位上都工作吗?”@GJ.-很抱歉干预,这不是大卫的评论。我想指出的是,问题不是为什么会出现编译错误。好的,你说得对,我忘记将结果放入xmm0寄存器中了。:)@GJ。相反,Math.ArcTan2和Math.arcin适用于所有Delphi编译器,而不仅仅是两个Windows编译器。我回答中的asm代码演示了不应该做什么。我想这句话说得很清楚。
    function PartArcTan(X: double): double;
    asm
    {$IFDEF CPUX64}
            movq [rsp-8], xmm0
            fld    qword ptr [rsp-8]
    {$ELSE}
            fld    qword ptr X
    {$ENDIF}
            fld1
            fpatan
            fwait
    {$IFDEF CPUX64}
            fstp   qword ptr [rsp-8]
            movq   xmm0, [rsp-8]
    {$ENDIF}
    end;