在GCC中使用内联汇编从32位IMUL返回64位结果

时间:2014-06-13 13:09:38

标签: c gcc assembly x86 inline-assembly

我试图从以下结果中获得结果......

Inputs EAX, EDX
IMUL EDX
Return EAX:EDX as full 64-bit result

我从https://gitorious.org/voxlap/voxlap/source/d467829d05294545ebb4cc088440421b57c7f38f:include/ksnippits.h#L281

看这个例子
static inline long mulshr16 (long a, long d)
{
#if defined(__GNUC__) && defined(__i386__) && !defined(NOASM)
__asm__ __volatile__
(
"imul %[d]\n"
"shrd $16, %%edx, %[a]\n"
: [a] "+a" (a)
: [d] "r" (d)
: "edx"
);
return a;
#else // C Default
return (long)(((int64_t)a * (int64_t)d) >> 16);
#endif
}

我只想要EAX中的完整64位结果:EDX,而不是移位结果,但是我不确定如何使用内联汇编程序将其传递回GCC。

1 个答案:

答案 0 :(得分:1)

尝试一下,但要仔细测试:

#include <stdio.h>

static inline long long mul64 (long a, long d)
{
  long long rtn;
  __asm__ __volatile__("imull %[d]\n" : 
                       [rtn] "=A" (rtn) : [a] "a" (a), [d] "rm" (d) );
  return rtn;
}

int main(void) 
{
  printf("%lld should be -1524157875019052100.", mul64(-1234567890, 1234567890));
  return 0;
}

正如其他人所说,以下定义产生了几乎相同的代码:

static inline long long mul64 (long a, long d)
{
  return (long long)a * d;
}

除了编译器将折叠常数并使用shift而不是乘法指令。即在许多情况下,它会生成更快的代码。

所以我假设你总是希望发出imull指令。这是经历内联装配痛苦的唯一明确理由。