アセンブラとの共存


【C言語とアセンブリ言語の共存方法】

 MPLAB C30コンパイラはアセンブリ言語との共存をサポートしています。
C言語プログラムの中でアセンブリプログラムを記述する方法には
下記の2種類の方法があります。

 (1) 個別モジュールに分ける記述
 (2) 簡易インラインアセンブル記述
 (3) 拡張インラインアセンブル記述

【個別モジュールに分けた記述】

 アセンブリ言語で記述したモジュールと、C言語で記述したモジュールを
同じプロジェクトに登録すれば、アセンブリモジュールとC言語モジュール
それぞれをアセンブル、コンパイルした後でC言語のモジュールにリンク
されます。

 アセンブリ言語モジュールとC モジュールとの変数または関数を関連づける
 には下記のようにします。

(1) W0からW7のレジスタを使って変数を受け渡しできる。レジスタW0-W7は
  パラメータの受け渡しに使用される。
  アセンブリ言語関数は、これらのレジスタで、パラメータを受け取り、コール
  された関数への引数の引渡しを行う。

(2) 割り込み処理で使われない関数が、レジスタW8-W15 を使う場合は、現在値
  を退避、復旧しなければならない。
  レジスタW0-W7 は退避、復旧することなく使える。

(3) 割り込み関数はすべてのレジスタを退避、復旧しなけれならない。

(4) Cソースファイルでも使われる変数または関数をアセンブラソースファイルで
  宣言する場合には、アセンブラ指定子.global でグローバル宣言する。
  この外部シンボルは少なくとも1 つのアンダースコアが前になければならない。

  C 関数のmain は、アセンブリの中では、_main と名づけられ、逆にアセンブリ
  シンボル_do_something は、C 内ではdo_something として参照される。
  アセンブリファイルの中で使用される未宣言シンボルは、外部定義されたもの
  として扱われる。

 実際のC言語とアセンブリ言語で記述したファイルの例を下記に示します。
ASM_C1.c ファイルではアセンブリ言語ファイル内で記述された関数asmFunc1と
asmFunc2を外部定義し、このアセンブリ関数をコールする方法と戻り値の扱い方を
示す。
 パラメータで受け渡す例では、結果はUARTで123+456=579となり579という値が
送信されます。
また外部変数として受け渡す例では、1234+1111=2345 となり2345という結果が
送信されます。



 アセンブリ言語側は下記のようになり、パラメータで受け渡しする場合には
W0からW7レジスタが使われます。例では整数型の引数をW0とW1レジスタで
取り出し、戻り値はW0レジスタで返します。
 このようにパラメータの受け渡しはW0からW7のレジスタが基本となっていて、
受け渡しのときのレジスタの組み合わせはW0側から順にデータの型により
下記のように決まっています。
  8または16ビット長データ → 1個のWレジスタ  (char、int、short、pointer)
  32ビット長データ       → 2個のレジスタペア(long、float、double)
  64ビット長データ       → 4個のレジスタ組 (long double)
パラメータが多く、W0からW7で不足するときはスタックが使われます。

 変数で受け渡しする場合には、外部シンボル宣言をしておき、アセンブラ内
の指定にはアンダーバーを最初に付加して扱います。






【簡易インラインアセンブル記述】

 MPALB C30ではC言語記述のプログラムの任意の場所に簡単な記述で
インラインのアセンブラ命令を挿入することができます。
そのときの記述には、下記のフォーマットを使用します。



 このasmという特別な構文によりアセンブラ命令の記述が可能となります。
ただし記述できるのは1個の文字列で記述した内容に限られます。
この""で囲んだ中に通常のアセンブラ記述を挿入します。レジスタ名などは
C言語の場合と同じです。

 volatile修飾を追加すると、コンパイルの際に、アセンブラ命令が消去されたり、
大きく配置を移動されたり、他と結合されたりすることを防ぐことができます。
 実際にンラインアセンブルを使う場面は、非常に処理時間が厳しい場合や、
シーケンスとタイミングがシビアで特定の順序が必要な場合などに使われます。

 例えば、実際の例としてOSCCONレジスタによるクロック源の切替には、
シビアなタイミングが必要でアセンブラ命令で記述する必要があります。
このような場合にインラインアセンブルを使用します。
 クロック源の切替をするプログラム例が下記リストとなります。ここでは、
タイマ1の一定周期で3個のLEDをフリッカ点滅させています。
この間にSW3が押されたかをチェックして、押された都度、クロックをFRCと
PLL付きFRCとに交互に切り替えます。これでクロック源の周波数が4倍異なり
ますから、LEDのフリッカ周期を見ることでクロック源が切り替わったことが判ります。

 クロック選択をインラインアセンブルで記述し、さらにOSCCONレジスタへの
書き込みに必要なアンロックシーケンスをインラインアセンブラで記述した関数
として用意しています。




【拡張インライン記述】

 アセンブラ命令のオペランド記述をC言語の形式で記述できるようにした
拡張記述方法です。
 複雑なオペランド記述が可能ですが、判り難くなるので、ここでは使わないことに
します。




   目次ページへ