在程序集ia32上进行imull操作

时间:2015-10-18 09:47:52

标签: assembly ia-32

我想在汇编中进行imull操作并将结果返回给C.

我的函数的签名是'long long multiplicar(void)',代码是:

multiplicar:
    movl op1, %eax
    imull op2, %eax
    adcl $0, %edx

    ret

我的op2是3.当我的op1是399时运行良好(给出1197)。但是当我的op1是-399时,我得到了4294966093并且不知道为什么。我必须使用cdc?

我的op1和op2是long long类型。 感谢

1 个答案:

答案 0 :(得分:0)

当给定32位操作数时,imul指令执行带符号的32x32位乘法。这会产生高达64位的结果,但是在两个/三个操作数形式中,只有最低有效字保持溢出通过进位指示。

请注意,进位只是用于错误检测的单位标志,不能携带将多个扩展精度乘法链接在一起所需的信息。

在这种情况下,在最新的编辑之后,似乎目标是将两个64位变量相乘并获取截断的64位结果。使用32x32 =&gt; 64位原语实现这一点需要将四次乘法链接到等级学校方法的数量。那是(a<<32|b) * (c<<32|d) = (a*c<<64) + (a*d<<32) + (b*c<<32) + (b*d<<0)a*c这个术语可以在这里删除,因为我们只需要结果中最不重要的64位。

虽然在理论上这在理论上是直截了当的,但保持临时性和直接使用汇编语言是微妙且容易出错的。一个额外的皱纹是操作是签名的,我的建议是建立一个基本的无符号乘法基元并分别调整符号。

幸运的是,如果我们改为使用8087浮点单元,那么CPU 实际上支持64位乘法。请注意,为避免舍入错误,浮点控制字必须设置为完整的64位精度(_controlfp(_PC_64,_MCW_PC)),而不是通常使用的53位。

multiply: ;int64_t __cdecl multiply(int64_t lhs, int64_t rhs)
        fildq 4(%esp)
        fildq 12(%esp)
        fmul
        fistpq 4(%esp)
        movl 4(%esp),%eax
        movl 8(%esp),%edx
        ret

但是请注意,要求完全128位精度而不是的溢出会产生正确截断的64位结果,并且问题不会处理状态溢出。