我想在汇编中进行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类型。 感谢
答案 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位结果,并且问题不会处理状态溢出。