【问题标题】:Returning a 64-bit result from a 32-bit IMUL with inline assembly in GCC使用 GCC 中的内联汇编从 32 位 IMUL 返回 64 位结果
【发布时间】:2014-06-13 13:09:37
【问题描述】:

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

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。

【问题讨论】:

  • 您知道,如果您将 32 位整数转换为 64 位,将它们相乘,然后将它们存储在 64 位变量中,GCC 将为您完成所有这些工作。
  • 请注意您想要什么,这不是链接中的mul64 吗?请注意,正如@Sneftel 所说,确实没有理由为此使用 asm。

标签: c gcc assembly x86 inline-assembly


【解决方案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;
}

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

所以我假设您总是希望发出 imull 指令是有某种原因的。这是经历内联汇编痛苦的唯一明确原因。

【讨论】:

  • 特别需要约束"A",它在EDX:EAX寄存器对中指定一个64位值。
  • @ChrisDodd 谢谢。你是说我将"=A" 用于rtn 的方式不正确?
  • 不,它是正确的,它确实是 OP 在他的原始示例中缺少的唯一信息。
  • 但是这个mul64存在于他在问题中链接的头文件中(包括使用A约束)。
  • @Jester 谢谢。当我开始回答问题时,他没有问题中的链接!
猜你喜欢
  • 2016-03-31
  • 1970-01-01
  • 2011-01-31
  • 2010-11-08
  • 1970-01-01
  • 2017-12-23
  • 1970-01-01
  • 2019-04-15
  • 2011-10-09
相关资源
最近更新 更多