【问题标题】:Adding floating point/double numbers in assembly在汇编中添加浮点数/双精度数
【发布时间】:2012-08-07 19:56:12
【问题描述】:

我正在尝试使用内联汇编,并尝试在内联汇编中添加十进制数(不,不是整数)。问题是,当我调用以下函数时:

inline double ADD(double num1, double num2) {
  double res;
_asm{

    push eax; push the former state of eax onto stack
    mov eax, num1;
    add eax, num2;
    mov res, eax;
    pop eax; restore the former state of eax now that we are done   
     }  return res;}

编译器抱怨内联汇编中的操作数大小不正确(所有汇编行,不包括 push 和 pop 指令行)。所以只好改成整数类型,比如unsigned long,然后就可以了,不过当然只支持整数类型;十进制结果四舍五入。

有没有办法在汇编中添加允许像 8.4 这样的小数结果?

【问题讨论】:

  • 注:二进制浮点数(floatdouble 等)不是十进制浮点数,不是实数(在数学意义上)。
  • 1.8 和 9.8 都不能完全表示为双精度。
  • @FredOverflow 引用的内容是您应该关心的众多原因之一(其他资源有大量资源,但它们进行了深入解释,因此需要大量数学和/或有点摆弄知识才能很好地理解,所以让我们把它留在那里)。遗憾的是,它在大多数情况下都会检查出来,但您在此类计算中遇到“奇怪的错误”,所以我想我会警告您。只需搜索 SO 即可查看数百个示例 - 这是最常见的问题之一。
  • 请不要push eax。这是唯一不需要保存的寄存器,因为它会返回结果。
  • 仅供参考,eax 为 32 位宽,但双精度为 64 位。那永远行不通。

标签: c assembly x86 x87


【解决方案1】:

我已经十年没有做过 x87 组装了,但应该是这样的:

fld num1   ; load num1 and push it onto the fpu stack
fld num2   ; load num2 and push it onto the fpu stack
faddp      ; pop two numbers, add them, push sum on the stack
fstp res   ; pop sum from the stack and store it in res

【讨论】:

  • 这些说明是什么意思?我只知道基本的组装说明。
  • 为了您的方便,我添加了 cmets。您可能应该阅读 x87,它是一个堆栈机器(而不是 x86,它是一个寄存器机器)。
  • 感谢 cmets。这有很大帮助,但是,它抱怨 faddp 被赋予了非法数量的操作数。我把它改成了fadd,它起作用了!我现在可以处理浮点数了!!!!!!耶!非常感谢! :D
  • fadd 会导致堆栈不平衡,请尝试以下变体:faddp st1,st0faddp st1,stfaddp st(1),st(0)
  • 我做了你显示的最后一个代替 fadd,它显示的结果与 fadd 完全相同,所以这很好,而且它显然不会像 fadd 那样损害堆栈 :) .谢谢珍。另外,我看到了它们是如何工作的,st(num) 引用了堆栈的某些区域。对我来说很好的学习经历:)。
【解决方案2】:

您可能想要的指令是 ADDSD,但我不确定。

这是英特尔指令集手册的链接。 http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html/

他们过去常常给你免费邮寄硬拷贝,但现在看来不再是这样了。

【讨论】:

  • +1 用于推荐 SSE2 而不是古老的 x87 指令。
【解决方案3】:

您需要一组不同的指令来操作浮点数。这是一个应该有帮助的介绍:x86 Assembly: Floating Point

【讨论】:

    【解决方案4】:

    试试这个:

    _asm{
    
    movq xmm0,[num1]
    addpd xmm0, [num2];
    movq [res],xmm0
    // sse2
     }
    

    【讨论】:

      【解决方案5】:

      上面的答案是,您必须将操作数压入 FP 堆栈并弹出结果是正确的。

      但是,“操作数大小不当”错误的直接原因是“扩展”寄存器“e__”(例如 eax)是 32 位的,而双精度浮点数是 64 位的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-02-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多