gpt4 book ai didi

Delphi 64位asm编译错误

转载 作者:行者123 更新时间:2023-12-03 14:57:50 32 4
gpt4 key购买 nike

以下函数无法使用 64 位 Delphi XE2 编译器进行编译。 (这些错误都与 fld 指令有关。)

[dcc64 Error] Project1.dpr(12): E2116 Invalid combination of opcode and operands 
[dcc64 Error] Project1.dpr(13): E2116 Invalid combination of opcode and operands
[dcc64 Error] Project1.dpr(20): E2116 Invalid combination of opcode and operands

第 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;

最佳答案

为了移植到 x64,此代码的主要问题是它使用了错误的浮点单元。在 x64 上,浮点是在 SSE 单元上完成的。

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

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

现在,移植到 SSE 单元并不像将操作码转换为 SSE 等效项那么简单。这是因为 SSE float 单元的内置功能要少得多。例如,SSE 操作码中不包含三角函数。

因此,处理此问题的正确方法是改用 Pascal 代码。这些函数可以替换为 Math.ArcTan2Math.ArcSin分别。

<小时/>

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

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;

注意事项:

  1. x64 ABI 表示输入参数到达 xmm0。我们无法将其直接加载到 x87 单元中。因此,我们必须从 xmm0 传输到堆栈上的暂存内存,然后从那里加载到 x87 单元。
  2. 返回值时我们也必须做类似的事情。该值按照 ABI 的指定在 xmm0 中返回。因此我们需要移出 x87 单元,暂存堆栈内存,然后加载到 xmm0 中。
  3. 我们完全忽略了浮点控制字:异常屏蔽、精度和舍入控制等。如果你要这样做,你需要组合一个机制来确保 x87 单元的控制字在一个保持理智。

所以,也许这可以给 future 希望使用 x87 在 x64 下执行浮点运算的访客提供一个警告。

关于Delphi 64位asm编译错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20764125/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com