式の置き換えを行う .equ ディレクティブの扱いが異なることがあるようです。

int main(void)
{
    int ret;
    asm volatile(
        ".intel_syntax noprefix\n"
        ".equ hoge, eax\n"
        "mov hoge, 42\n"
    : "=a"(ret));
    return ret;
}

これを GCC でコンパイルすると、mov hoge, 42mov eax, 42 に置き換わり、eax レジスタに 42 を mov する意味になります。

一方、Clang でコンパイルすると、eax はレジスタではなく変数(メモリの位置)だと解釈され、mov dword ptr [eaxという変数のアドレス], 42 に置き換わります(64bit 環境なら qword ptr になる)。そんな変数は無いのでリンクエラーになります。

ただ、これは Clang の方が適切な動作のようにも思えます。なぜならレジスタとしての eax はアセンブリ言語における式 (expression) ではないからです。

代わりに以下のようなコードだとどちらでも OK です。 .irp ではマクロ展開と同じく文字列として置き換えを行うからです。

int main(void)
{
    int ret;
    asm volatile(
        ".intel_syntax noprefix\n"
        ".irp hoge, eax\n"
        "mov \hoge, 42\n"
        ".endr\n"
    : "=a"(ret));
    return ret;
}

ただ、 .irp には対応する .endr が必要であるため、複数個定義すると .endr がたくさん出てきて見た目が残念なことになります。

Trackback

no comment untill now

Add your comment now