インラインアセンブラと \n\t

小ネタ2。
GCCで複数行からなるインラインアセンブラを書くとき、

 __asm__ ("movl %0,r9\n\t"
          "movl %1,r10\n\t"
          "call _foo"
 :: "g" (from), "g" (to) :  "r9", "r10");

のように \n\t 区切りで書くひとと、\n\t のかわりにセミコロン区切りで書く*1ひとがいます。GCCのマニュアル上は、どちらでもOKよん、ということになってるんですが、世間では \n\t 派が多いです。...で、 ; の方が読みやすいだろうに、なぜ世間では\n\t派が多いのか、ちょっと前まで疑問でした。というわけで、\n\tの利点説明です。


gccコマンドが.cを食って一時ファイル(/tmp/ランダム文字列.s)を生成するとき、前者(\n\t)の書き方だと.sは

ラベル:
#APP
    movl %0,r9
    movl %1,r10
    call _foo
#NO_APP

のようになりますけど、後者(;)だと

ラベル:
#APP
    movl %0,r9;movl %1,r10;call _foo
#NO_APP

と一行になってしまい、(長〜い)インラインアセンブラ中にsyntax errorがあった場合などに、どこが間違っているのかgccのエラーメッセージ中の行番号からはさっぱりわからなくなってしまいます。全部同一の行番号ですから。前者なら、gcc -save-temps -c hoge.c として hoge.s を取り出し、行番号をもとに文法ミスを修正することができます。


以上、

  • __asm__ の中身はわりと単純に.sへブチ込まれるだけだということを(もう一度)思いだそう。
  • GCCの、 .c -> .s -> .o 完全分業体制は不便、うーん。

みたいな話でした。

*1:gas上、セミコロンがコメント開始を表さない環境を前提とします