加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Delphi 64位asm编译错误

发布时间:2020-12-15 04:17:33 所属栏目:大数据 来源:网络整理
导读:以下函数不使用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 Erro
以下函数不使用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支持的10字节扩展类型,而不是SSE.这里情况不同.

现在,移植到SSE单元并不像将操作码转换为SSE等价物那么简单.那是因为SSE浮动单元的内置功能要少得多.例如,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;

注意事项:

> x64 ABI表示输入参数到达xmm0.我们无法将其直接加载到x87单元中.所以我们必须从堆栈中的xmm0转移到暂存内存,然后从那里加载到x87单元中.
>返回值时我们必须做类似的事情.该值以xmm0返回,由ABI指定.所以我们需要移出x87单元,刮开堆栈内存,然后加载到xmm0.
>我们完全忽略了浮点控制字:异常屏蔽,精度和舍入控制等.如果你要这样做,你需要组建一个机制来确保x87单元的控制字以理智的方式处理.

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读