GCCの埋め込みコンパイルに関するまとめ

2396 ワード

最近はGCCの組み込みコンパイルを使うかもしれませんので、少しまとめて、皆さんに分かち合います。
参考のURLを皆さんに共有します。
http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html#s2
http://www.cnblogs.com/whutzhou/articles/2638498.html  この文章は前の文章に対する翻訳です。
https://gcc.gnu.org/onlinedocs/gcc.pdf
GCCでは、基本的な内連結アセンブリ文(baic inline asm statement)と拡張内連結アセンブリ文(exteded inline asm statement)があります。基本的なインラインコンパイルにはオペランドは含まれません。一方、インラインコンパイル文の1つまたは複数のオペランドは拡張されます。
まず、基本的な国内連合の編纂文の形式を見てみます。
asm("assembly code");
もう一つ簡単な例をあげます。
asm("movl %ecx %eax");
この例の形式は非常に簡単で、ecxの値をeaxに移すことです。上記の例を通して、基本的な内連結文はまず「_asm_u u」または「asm」のキーワードから始まります。括弧を通じて、アセンブリ文の範囲を指定します。二重引用符と「t」の方法で、アセンブリ文を分離します。形式は以下の通りです。
 __asm__ ("movl %eax, %ebx
\t" "movl $56, %esi
\t" "movl %ecx, $label(%edx,%ebx,$4)
\t" "movb %ah, (%ebx)");
上記のアセンブリ文を「;」で区切ることもできます。上記のアセンブリ文は以下のように書き換えられます。
 __asm__ ("movl %eax, %ebx;"
          "movl $56, %esi;"
          "movl %ecx, $label(%edx,%ebx,$4);"
          "movb %ah, (%ebx);");
しかし、上記のコンパイラ文は使用中に問題があります。一つの主要な問題はGCCがレジスタの値の変化を知らないことです。特にコンパイラがコードを最適化するとき、コンパイラは変数を格納するレジスタは、それを変えずに自分の最適化を継続します。このような状況を避けるために、レジスタの値を変えないか、あるいは、レジスターの値を変えないようにします。アセンブリ関数が戻る前に、レジスタの使用前の値を還元したり、コードの崩壊を待っています。 
上記の問題があるからこそ、私達の次のテーマを引き出しました。
まず拡張されたコンパイル文の形式を見ます。
<pre name="code" class="cpp"><pre name="code" class="cpp">    asm ( assembler template   
        : output operands                  /* optional */  
        : input operands                   /* optional */  
        : list of clobbered registers      /* optional */  
        );
 
 
 
 
扩展汇编语句共包括四个参数,分别是汇编语句模板、输出操作数、输入操作数以及 被破坏寄存器的列表,其中除第一个外,后三个均可以省略。虽然参数可以不填,位置却要留在那(就像for循环那样),一个最简单的扩展内联汇编语句形式如下:

    asm ( assembler template   
        : 
        : 
        :   
        );
上記の形式の分析により、拡張されたインラインアセンブル文は関数呼び出しに似ています。入力操作数は関数パラメータに似ています。出力操作数は関数戻り値に似ています。
ここで注意したいのは、入出力操作数が、破壊レジスタのリストに追加される必要がないことです。