【发布时间】:2013-10-26 01:33:47
【问题描述】:
我有一个关于在 x86 汇编中实现 64 位乘法的问题。据我所知,我已经发布了代码。我不知道其他人做了什么(我可能在我已经做过的事情上犯了错误)。任何方向将不胜感激。
dest at %ebp+8
x at %ebp+12
y at %ebp+16
movl 16(%ebp), %esi //Move y into %esi
movl 12(%ebp), %eax //Move x into %eax
movl %eax, %edx //Move x into %edx
sarl $31, %edx //Shift x right 31 bits (only sign bit remains)
movl 20(%ebp), %ecx //Move the low order bits of y into %ecx
imull %eax, %ecx //Multiply the contents of %ecx (low order bits of y) by x
movl %edx, %ebx //Copy sign bit of x to ebx
imull %esi, %ebx //Multiply sign bit of x in ebx by high order bits of y
addl %ebx, %ecx //Add the signed upper order bits of y to the lower order bits (What happens when this overflows?)
mull %esi //Multiply the contents of eax (x) by y
leal (%ecx,%edx), %edx
movl 8(%ebp), %ecx
movl %eax, (%ecx)
movl %edx, 4(%ecx)
【问题讨论】:
-
将 2 个 32 位值相乘并不能真正算作 64 位乘法。以及如何在 20(%ebp) 处移动 long 移动 y 的任何位,除非 y 是 64 位值,但结果没有 64 位位置(dest 只有 32 位),除非它应该覆盖 x...
-
这会将一个有符号的 32 位整数与一个有符号的 64 位整数相乘,产生一个有符号的 64 位整数。以 2^32 为底,在纸上算出来。
-
顺便说一句,unsigned 32x64 乘法只需要
imul+mul和2 加(godbolt.org/g/VC6i9T):32 位输入的上半部分为零,不是 0 或 -1,所以x_h * y_h术语消失了。 (顺便说一句,gcc 在这里可以做得更好,用 cmov / sub 而不是实际乘以 x 的上半部分。它可以用cdq生成它。)实际的 64x64 乘法需要更少的指令(没有符号-延长上半部分)。