前回は触れなかったのですが、OpenWatcom Cでは インラインアセンブラ も使うことが可能です。「コマケー話」であれば、わざわざアセンブリ言語を書くための別ファイルなどを用意せずともC言語ソース内に「ちょこっと」書き込んで済ませることが可能。それもゴージャスなことに2種類のインライン記法があるのだけれども。
※実機動作確認には以下を使用しております。
OpenWatcom Cのインライン・アセンブラ記法
以下の2種類のインライン・アセンブラ記法がサポートされています。
-
- #pragma 使う記法
- _asm 使う記法
コンパイラによりどちらも「ある」記法じゃないかと思います。使いでは一長一短、それぞれにクセがあるのでお好みかと。
お惚け老人が勝手に調べたところでは、#pragma使う記法では、引数、戻り値、破壊されるレジスタなどを宣言し、アセンブラで独立した関数を記述可能。またC言語レベルの変数の参照も可能です。キッチリした記述が可能である反面、論理的に1行という制限があるためか、行末に¥マーク必須とか、アセンブリ言語ソース部分を””でくくらないとならないとか体裁はメンドイです。
一方 _asm 使う記法では、上記のようなレジスタ指定などはできないようなので、自立した関数とはいかず、Cの関数内に居候するようなコードになります。それでもC言語レベルの変数は参照できるので、変数を経由したやりとりは可能。_asm { につづいて、複数行にわたるアセンブリ言語命令をそのまま記述していけるので記述はお楽。
上記の両方を合体させた感じで「ちょっと抽象的かつ荘厳な」gccの_asmより、OpenWatcomのインライン・アセンブラ記法の方が「軽み」が感じられるのはお惚け老人だけか?
#pragma aux記法の例
以下は符号無数の足し算をするだけのサンプルプログラムです。アセンブリ言語で記述した testFuncなる関数は引数を1個とり、その値とC言語レベルで定義されている変数 _v1との和を求め、結果を関数戻り値として返してきます。同じ1本のソース内で定義しているのだけれども testFunc は extern という扱いデス。
#include <stdio.h> static unsigned short _v1; extern unsigned short testFunc( unsigned short ); #pragma aux testFunc = \ "mov dx, _v1" \ "add ax, dx" \ parm [ax] \ value [ax] \ modify [dx]; void main() { unsigned short temp; _v1 = 123; temp = testFunc(2); printf("Result = %d\n", temp); }
コンパイルそのものは、以前と変わらず以下で可能です。
wcl /l=dos inline.c
生成された inline.exe を走らせれば Result = 125と結果が表示されます。
_asm記法の例
こちらの場合、引数や戻り値を定義する方法が見当たりませんでした。C言語の変数には普通にアクセスできるようなので、以下のようにしています。
#include <stdio.h> static unsigned short _v1; static unsigned short _result; void main() { _result = 2; _v1 = 123; _asm { mov ax, _result mov dx, _v1 add ax, dx mov _result, ax }; printf("Result = %d\n", _result); }
こちらもコンパイルは、以下で可能です。
wcl /l=dos inline2.c
やはり生成された inline2.exe を走らせれば Result = 125と結果が表示されます。
まあ、インライン・アセンブラ使ってもアセンブラできなくもないっす。