i386/x86_64 向けの GCC/Clang のインラインアセンブラで "i" 制約によって定数を埋め込む時、AT&T 記法の場合だと $ プレフィックスが付きます。 AT&T 記法の場合は即値にプレフィックスを付けることになっているので、この挙動は妥当です。即値にプレフィックス付けなくてもアセンブルはできるようですが。(今試して気づいた)

    asm volatile(
        "movl    %0, %%eax\n"
    :: "i"(42));

これは次のように置き換えられます。

    asm volatile(
        "movl    $42, %%eax\n"
    ::);

一方、メモリアクセス時など、数値を書くところでプレフィックスなしにするべきところもいくつかあります。これらの箇所でプレフィックスを付けた場合、シンボル(ラベル)として扱われるか、エラーとして扱われます。(GCC と Clang とでここの挙動が微妙に違ったりする)

    asm volatile(
        "movl    100(%%ebx), %%eax\n"
        "movl    (%%ebx,%%ecx,4), %%eax\n"
        ".equ    hoge, 200\n"
        "movl    hoge, %%eax\n"
    ::);

で、プレフィックスなしの数値を埋め込むにはどうしたらいいかですが、次のようにします。

    asm volatile(
        "movl    %c0(%%ebx), %%eax\n"
        "movl    (%%ebx,%%ecx,%c1), %%eax\n"
        ".equ    hoge, %c2\n"
        "movl    hoge, %%eax\n"
    :: "i"(100), "i"(4), "i"(200));

こうした場合、 AT&T 記法でもプレフィックスなしの数値になります。もちろん Intel 記法の場合でもプレフィックスなしです。

ちなみにシンボル名で埋め込みを記述している場合は以下のようにします。

    asm volatile(
        "movl    %c[hoge](%%ebx), %%eax\n"
    :: [hoge]"i"(100));

これらのことは GCC のマニュアルの Extended Asm の x86 Operand Modifiers のところに書いてあってターゲット依存の機能のように読めるのですが、少なくとも aarch64 (ARM の 64bit)でも受け付けられるようです。ただし、aarch64 の場合は即値を埋め込んでもプレフィックスは元々付かないので、エラーにならないだけで利点は特にありません。他のターゲットは環境が手元にないので分かりません。

Trackback

no comment untill now

Add your comment now