在Assembler中,我可以使用MUL命令获得64位结果EAX:EDX, 我怎么能在C中做同样的事情? http://siyobik.info/index.php?module=x86&id=210
我使用uint64_t并移动结果的方法不起作用^^
感谢您的帮助(=
我
答案 0 :(得分:3)
当被问到时,任何体面的编译器都会执行此操作。
例如,使用VC ++ 2010,代码如下:
unsigned long long result ;
unsigned long a = 0x12345678 ;
unsigned long b = 0x87654321 ;
result = (unsigned long long)a * b ;
生成以下汇编程序:
mov eax,dword ptr [b]
mov ecx,dword ptr [a]
mul eax,ecx
mov dword ptr [result],eax
mov dword ptr [a],edx
答案 1 :(得分:1)
发布一些代码。这对我有用:
#include <inttypes.h>
#include <stdio.h>
int main(void) {
uint32_t x, y;
uint64_t z;
x = 0x10203040;
y = 0x3000;
z = (uint64_t)x * y;
printf("%016" PRIX64 "\n", z);
return 0;
}
答案 2 :(得分:0)
看看你是否可以为编译器获得等效的__emul or __emulu(或者如果你有一个MS编译器就使用它)。虽然64位乘法应该自动工作,除非你坐在一些限制或其他有趣的问题(如_aulmul)
答案 3 :(得分:0)
您的意思是将两个32位数相乘以获得64位结果?
这在C中本身没有预见到,要么你在uint32_t
中拖了32位,那么结果宽度相同。或者你之前施放到uint64_t
但是你失去了特殊(和快速)乘法的优势。
我看到的唯一方法是使用内联汇编程序扩展。 gcc相当不错,你可以生成相当优秀的代码。但是在不同版本的编译器之间不可移植。 (许多公共域编译器采用gcc,但我认为)
答案 4 :(得分:0)
#include
/* The name says it all. Multiply two 32 bit unsigned ints and get
* one 64 bit unsigned int.
*/
uint64_t mul_U32xU32_u64(uint32_t a, uint32_t x) {
return a * (uint64_t)b; /* Note about the cast below. */
}
这会产生:
mul_U32xU32_u64:
movl 8(%esp), %eax
mull 4(%esp)
popl %ebp
ret
编译时使用:
gcc -m32 -O3 -fomit-frame-pointer -S mul.c
使用mul
指令(此处称为mull
为乘法长,这是x86的gnu汇编程序喜欢它的方式)。
在这种情况下,其中一个参数直接从堆栈中提取而不是放在寄存器中(4(%esp)
表示堆栈指针上方4个字节,跳过的4个字节是返回地址)因为数字被传递到函数中并且已经被压入堆栈(根据x86 ABI(应用程序二进制接口))。
如果您在代码中内联函数或只是在其中进行了数学计算,那么在很多情况下很可能会导致使用mul
指令,尽管优化编译器也可以用更简单的代码替换一些乘法,如果它们可以的话告诉它它会起作用(例如,如果已知一个或多个参数,它可以将其转换为一个转换,甚至是常量)。
在C代码中,至少有一个参数必须转换为64位值,以便编译器产生64位结果。即使编译器必须使用在乘以32位值时产生64位结果的代码,它也可能没有考虑它的上半部分是重要的,因为根据C操作的规则通常会产生具有相同类型的值作为其组成部分中具有最大范围的值(除非您有时可能认为这并不完全是它所做的)。
答案 5 :(得分:0)
你不能在C中做到这一点,即你不能将两个N位值相乘并获得2N位值作为结果。 C乘法的语义与机器乘法的语义不同。在C中,乘法运算符始终应用于相同类型T
的值(所谓的通常的算术转换处理它)并生成相同类型T
的结果。
如果在乘法运行时遇到溢出,则必须为操作数使用更大的类型。如果没有更大的类型,那你就不走运了(也就是你别无选择,只能使用大型乘法的库级实现)。
例如,如果您平台的最大整数类型是64位类型,那么在计算机的汇编级别,您可以访问mul
操作,从而生成正确的128位结果。在语言级别,您无法访问此类乘法。