3

Xcode (4.5.2) でデバッグ構成を使用して正常にビルドするプロジェクトがあります。ただし、Release 構成のビルドに切り替えたので、問題が発生しています。インライン アセンブリ関数の 1 つでエラーが発生しています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

4

1 に答える 1

13

and 、and、orなどのローカルラベルを使用します。ジャンプの方向(前方または後方)が必要です。したがって、コードは次のようになります。1:2:jxx 1fjxx 1bfb

__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"
)

純粋に数字で構成される記号は、「関数に対してローカル」です。「インライン」はコードが物理的に複製されていることを意味するため、複数のシンボル定義を取得する理由は、シンボルが実際に「グローバル」な方法で複数回定義されているためです。

もちろん、デバッグビルドがある場合は、通常「インラインなし」を意味するため、インライン関数はインライン化されず、シンボルは1回だけ宣言され、「機能」します。

[これの効率とコンパイラ自体の動作については少し疑問があります。少なくとも、一部の入力にレジスタを使用すると効率が上がると考えていました]。

于 2013-01-24T16:38:49.337 に答える