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



我试图基本上从以下得到结果…

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:EDX中的完整64位结果,但是我不确定如何使用内联汇编器将其传递回GCC。

试一试,但要仔细测试:

#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;
}

除了编译器将折叠常量并在可能的情况下使用移位而不是乘法指令。也就是说,在很多情况下,它会更快地生成代码。

所以我假设有一些原因你总是想要发出imull指令。这是经历内联汇编痛苦的唯一明确原因。

最新更新