【发布时间】:2013-01-08 11:49:38
【问题描述】:
我在 Xcode (4.5.2) 中有一个使用 Debug 配置构建良好的项目。然而,既然我已经切换到构建发布配置,我遇到了一个问题:我的一个内联汇编函数得到了错误Invalid symbol redefinition。谷歌搜索该错误消息会发现一些人遇到了该编译器错误,但没有关于其含义的信息。这是函数,错误行注释:
inline int MulDivAdd(int nNumber,
int nNumerator,
int nDenominator,
int nToAdd)
{
int nRet;
__asm__ __volatile__ (
"mov %4, %%ecx \n"
"mov %1, %%eax \n"
"mull %2 \n"
"cmp $0, %%ecx \n"
"jl __sub \n"
"addl %%ecx, %%eax \n"
"adc $0, %%edx \n"
"jmp __div \n"
"__sub: \n" // "Invalid symbol redefinition"
"neg %%ecx \n"
"subl %%ecx, %%eax \n"
"sbb $0, %%edx \n"
"__div: \n" // "Invalid symbol redefinition"
"divl %3 \n"
"mov %%eax, %0 \n"
: "=m" (nRet)
: "m" (nNumber),
"m" (nNumerator),
"m" (nDenominator),
"m" (nToAdd)
: "eax", "ecx", "edx"
);
return nRet;
}
我尝试将__sub 替换为__sbt,因为我认为__sub 可能是受保护的名称,但事实并非如此。我不明白为什么这只发生在 Release 中 - 可能是由于优化吗?
【问题讨论】:
-
如果你用 C 写这个(使用
int64_t)你会得到更好的代码生成。该分支是完全没有必要的(它应该是一个符号扩展和添加)。我还对使用带符号数据的无符号乘法指令 (mull) 感到困扰。虽然对于相关程序可能无关紧要,但它可能是一个错误。 -
@StephenCanon 那么这个俏皮话和这个问题有什么关系呢?
-
这不需要是
volatile。它只需要运行以产生输出。 (并且volatile并没有阻止它内联到多个地方,从而导致问题)。但是斯蒂芬是对的,这对于强制内存操作数的效率来说看起来很糟糕。在这里使用内联汇编的唯一原因是如果您知道 64b/32b => 32bdiv不会溢出商和错误。 gccl/clang 仍然不知道如何利用它并使用单个idiv而不是为 64b/64b 划分调用 libgcc 辅助函数。
标签: c++ assembly llvm clang gnu-assembler