結論から言うと、インラインアセンブラ部分の先頭に .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…