結論から言うと、インラインアセンブラ部分の先頭に .intel_syntax noprefix と書く(だけ)。 -masm=intel オプションは付けなくてもいいが、GCC との互換性を考えると付けるべき、となります。(Clang しか考えないなら付けなくてもいい)。

以下経過と詳細な挙動。環境は CentOS 7 + Clang 3.5.2 です。

Clang でも GCC と同様の構文でインラインアセンブラが使えます。

[umezawa@devcent7:pts/0 ~]$ cat att.c
int main(void)
{
        int ret;
        asm volatile(
                "movl   $0, %%eax"
                : "=a"(ret) );
        return ret;
}
[umezawa@devcent7:pts/0 ~]$ clang -o att att.c
[umezawa@devcent7:pts/0 ~]$ ./att; echo $?
0

で、 GCC でインラインアセンブラにおいて Intel 記法を使う場合は -masm=intel オプションを付けます。 Clang ではどうでしょうか。

[umezawa@devcent7:pts/0 ~]$ cat intel.c
int main(void)
{
        int ret;
        asm volatile(
                "mov    eax, 0"
                : "=a"(ret) );
        return ret;
}
[umezawa@devcent7:pts/0 ~]$ clang -o intel -masm=intel intel.c
intel.c:5:3: error: unknown use of instruction mnemonic without a size suffix
                "mov    eax, 0"
                ^
:1:2: note: instantiated into assembly here
        mov     eax, 0
        ^
1 error generated.

あれれ…

仕方ないなぁ、AT&T 記法しかサポートしてないのかー、と思ったのですが、試行錯誤している最中に以下のように打ち間違えてしまいました。

[umezawa@devcent7:pts/0 ~]$ clang -masm=intel -S -o - att.c
        .text
        .file   "att.c"
        .globl  main
        .align  16, 0x90
        .type   main,@function
main:                                   # @main
        .cfi_startproc
# BB#0:                                 # %entry
        push    rbp
.Ltmp0:
        .cfi_def_cfa_offset 16
.Ltmp1:
        .cfi_offset rbp, -16
        mov     rbp, rsp
.Ltmp2:
        .cfi_def_cfa_register rbp
        mov     dword ptr [rbp - 4], 0
        #APP
        mov     eax, 0
        #NO_APP
        mov     dword ptr [rbp - 8], eax
        mov     eax, dword ptr [rbp - 8]
        pop     rbp
        ret
.Ltmp3:
        .size   main, .Ltmp3-main
        .cfi_endproc


        .ident  "clang version 3.5.2 (tags/RELEASE_352/final)"
        .section        ".note.GNU-stack","",@progbits

えっ!? AT&T 記法で書いたアセンブリプログラムが Intel 記法で出てきました。

どういうこっちゃ、と思いつつ、ふと思いついて GCC で -masm=intel 付きで出力したアセンブリソースの頭の方に出てくる .intel_syntax noprefix を書いたらどうなるか試してみました。

[umezawa@devcent7:pts/0 ~]$ cat intel2.c
int main(void)
{
        int ret;
        asm volatile(
                ".intel_syntax noprefix\n"
                "mov    eax, 0"
                : "=a"(ret) );
        return ret;
}
[umezawa@devcent7:pts/0 ~]$ clang -masm=intel -S -o - intel2.c
        .text
        .file   "intel2.c"
        .globl  main
        .align  16, 0x90
        .type   main,@function
main:                                   # @main
        .cfi_startproc
# BB#0:                                 # %entry
        push    rbp
.Ltmp0:
        .cfi_def_cfa_offset 16
.Ltmp1:
        .cfi_offset rbp, -16
        mov     rbp, rsp
.Ltmp2:
        .cfi_def_cfa_register rbp
        mov     dword ptr [rbp - 4], 0
        #APP

        mov     eax, 0
        #NO_APP
        mov     dword ptr [rbp - 8], eax
        mov     eax, dword ptr [rbp - 8]
        pop     rbp
        ret
.Ltmp3:
        .size   main, .Ltmp3-main
        .cfi_endproc


        .ident  "clang version 3.5.2 (tags/RELEASE_352/final)"
        .section        ".note.GNU-stack","",@progbits
[umezawa@devcent7:pts/0 ~]$ clang -o intel2 intel2.c
[umezawa@devcent7:pts/0 ~]$ ./intel2; echo $?
0

やったぜ

そして、 -masm=intel を付けないでアセンブリソースを出力させると、Intel 記法で書いたインラインアセンブリソースが AT&T 記法になって出てきます。そういうことか。

[umezawa@devcent7:pts/0 ~]$ clang -S -o - intel2.c
        .text
        .file   "intel2.c"
        .globl  main
        .align  16, 0x90
        .type   main,@function
main:                                   # @main
        .cfi_startproc
# BB#0:                                 # %entry
        pushq   %rbp
.Ltmp0:
        .cfi_def_cfa_offset 16
.Ltmp1:
        .cfi_offset %rbp, -16
        movq    %rsp, %rbp
.Ltmp2:
        .cfi_def_cfa_register %rbp
        movl    $0, -4(%rbp)
        #APP

        movl    $0, %eax
        #NO_APP
        movl    %eax, -8(%rbp)
        movl    -8(%rbp), %eax
        popq    %rbp
        retq
.Ltmp3:
        .size   main, .Ltmp3-main
        .cfi_endproc


        .ident  "clang version 3.5.2 (tags/RELEASE_352/final)"
        .section        ".note.GNU-stack","",@progbits

つまり、 Clang の挙動としては、 -masm=intel-S オプションを付けた時に出力されるアセンブリソースの記法を指定するだけの効果しかなく、インラインアセンブリで Intel 記法を使いたい場合はインラインアセンブリ部分の先頭に .intel_syntax noprefix と書く必要があり、さらに両者は独立した効果を持つ、ということになります。ちなみに -S を付けていない場合に -masm=intel を付けてもエラーも警告もありません。

世の中 Clang ばっかりではないので GCC とも互換性のある書き方をすべきですが、 GCC の場合は -masm=intel で両方の効果を持ち、さらに -masm=intel が付いている場合に .intel_syntax noprefix と書いても特に副作用はないようなので、両方やりましょう、ということになります。

Trackback

only 1 comment untill now

  1. Clang のインラインアセンブラで Intel 記法を使う (その2)

    その1の続き 一つ重要なテストを忘れていました。 Extended Asm の Input Operand です。 [umezawa@metis:ttys002 ~]$ cat intel.c int main(int argc, char** argv) { int ret; asm volatile( “.intel_syntax\n” “mov eax, %1\n” : “=a”(ret…

Add your comment now