結論から言うと、インラインアセンブラ部分の先頭に .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
と書いても特に副作用はないようなので、両方やりましょう、ということになります。
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…