C言語インラインアセンブリ 拡張構文 その1

Linux

インラインアセンブリ拡張構文

Linuxのコードでしばしば登場するこれ。
アセンブリなんだけど独特のルールがめんどくせぇ。
しっかり理解しておこう。

オペランド

__asm__()とやってカッコの中に命令を書き込んでいきます。
c言語では直接扱えないレジスタへの入出力が行えます。
以下のルールがあります。

__asm__ ( アセンブリテンプレート
        : 出力オペランド
        : 入力オペランド
        : 破壊するレジスタ
);	

アセンブラテンプレート

アセンブリ言語を記述しますが、少しだけ書き方が違います。
命令と始まりと終わりを””で囲み、一行の最後毎に;を置きます。
レジスタを使用する場合は先頭に%%を付けます。

int main() {
	int zero=0,one=1,out;
	asm volatile (
		"movl %1,%%eax"  /* zero(ebx)の値をeaxへ */
		"movl %2,%%eax"  /* one(ecx)の値をeaxへ */
		"movl %%eax,%0"  /* eaxの値をout(ジェネラルレジスタ)へ */
		
		: "=g"(out) /* 出力オペランドoutは%0 */
		: "b"(zero),"c"(one) /* 入力オペランドzeroは%1でoneは%2  */
		);
	return 0;
}

全く意味のないコードですが例として挙げておきます。

インラインアセンブリの外にc言語で書かれた変数も利用することができます。
その際は後述する出力オペランドと入力オペランドで指定しますが、指定された順に%0、%1…と番号で割り当てられます。

出力オペランド

:";=制約文字"(変数名)

で指定されます。
インライアセンブリの外に書いたc言語の変数にレジスタの値を保存したい時などに使用します。
=の後の制約文字には沢山の種類があり使用したいものに合わせて=を修飾します。

aeax
bebx
cecx
dedx
rレジスタが自動で割り当てられます
mメモリに割り当てられます
g汎用レジスタが割り当てられます。

他にもたくさんありますが基本的なものです。
頭文字で表されているので分かりやすいはずです。
変数名にはインライアセンブリの外側にc言語で書かれた変数を指定します。

:";=a"(var1)

のように設定すれば

入力オペランド

:™制約文字"(変数名)

出力オペランドの=が抜けたものです。

破壊オペランド

インラインアセンブリでは自由にレジスタを指定できますが、その過程で無関係の変数が割り当てられたレジスタを上書きしてしまう可能性があります。
それを防ぐために最後の行にインラインアセンブリで使用するレジスタを列挙します。
コンパイラーはそのレジスタのデータを破壊しないようなコードを出力します。

プログラミングおすすめ書籍

おすすめ書籍

なぜプログラムが動くのか。
平易な言葉で学べますが、初心者には難しいかもしれません。
でも読み終わった頃にはなんとなく理解しているでしょう。
初心者には家にあって損はありません。

UNIXの思想を学べます。
高尚なタイトルですが、コードはおろか難しい言葉も殆どありません。取っ掛かりに最適でその後のプログラミングに対する理解を一変させます。
なぜならこの思想はプログラミングそのものだからです。
一読の価値ありで、これは良書なので今後紹介したいと思っています。

まだまだありますがまたの機会に紹介したいと思います。

Linux コンピューター
スポンサーリンク
himazinをフォローする
私の頭の上の消しゴム

コメント

タイトルとURLをコピーしました