3

我在 Xcode (4.5.2) 中有一个使用 Debug 配置构建良好的项目。但是,既然我已经切换到构建 Release 配置,我遇到了一个问题:我的一个内联汇编函数得到了 error 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 中 - 可能是由于优化吗?

4

1 回答 1

13

使用本地标签,例如1:and 2:, and jxx 1for jxx 1b。跳跃的方向(f向前或b向后)是必需的。所以你的代码应该是这样的:

__asm__ __volatile__ (
    "mov    %4,     %%ecx   \n"
    "mov    %1,     %%eax   \n"
    "mull   %2              \n"
    "cmp    $0,     %%ecx   \n"
    "jl     1f              \n"
    "addl   %%ecx,  %%eax   \n"
    "adc    $0,     %%edx   \n"
    "jmp    2f              \n"
"1:                         \n"   
    "neg    %%ecx           \n"
    "subl   %%ecx,  %%eax   \n"
    "sbb    $0,     %%edx   \n"
"2:                         \n"   
    "divl   %3              \n"
    "mov    %%eax,  %0      \n"
)

纯粹由数字组成的符号是“函数的局部”。由于“内联”意味着代码在物理上是重复的,因此您获得多个符号定义的原因是您的符号确实以“全局”方式定义了多次。

当然,如果你有一个调试版本,它通常意味着“没有内联”,所以内联函数不是内联的,符号只声明一次,它“工作”。

[我对这个与编译器自己会做什么的效率有点怀疑——我认为至少考虑对某些输入使用寄存器会使其更有效]。

于 2013-01-24T16:38:49.337 回答