awk言語で作った簡易クロス・アセンブラ


▲▲ トップページに戻る    ▲ 前のページに戻る

このプログラムは1994年末から1995年初めにかけて作成・使用 したもので、現在は使用したPC-9801シリーズもありませんので、サポートできないことをお断り しておきます。また、本ドキュメントは1995年にPC-9801のワープロで書いたものをWindows用にコンバート したもので、図表等おかしなところもありますがご容赦ください。

概要

 極言すれば、クロス・アセンブラとはテキストで記述した命令をバイナリ・コードに変換(置換)しオブジェクト・ファイルを作るだけのものです。やる気になれば、手作業でもできます(ハンド・アセンブル)。もちろん、分岐命令などではアドレスの計算も必要ですし、引数の処理もありますから手作業では大変です。しかし、現在ではパソコンが使える環境にありますから、変換作業を自動的に行うことは容易です。今回は、awkによるテキスト処理の応用としてPIC16C84の簡易クロス・アセンブラを製作してみました。
awkの概要

 awkはテキスト・ファイルを処理するのに適したUNIXツールです(今回使用するのはGNUプロジェクト版gawkの日本語MS−DOS版jgawk)。awkで便利なのが、1行にセパレータ(スペースやタブ、他の文字に変更可能)で区切られて書かれた複数の文字列をデータ・ベースのフィールドとして、そして異なる行をレコードとして扱う機能です。例えば、リスト1のようなテキスト・ファイル(in.txt)があり、「抵抗」のみを抽出し、金額(単価×数量)を追加し、最後に合計金額を追加する場合のプログラム(awkスクリプト)はリスト2(sample.awk)のようになります。
リスト1 サンプル・データ(in.txt)

10kΩ>抵抗102
10μFコンデンサ154
20kΩ抵抗103
2SC1815トランジスタ205
1S1588ダイオード101
100kΩ抵抗151
リスト2 サンプル・プログラム(sample.awk)

BEGIN{ goukei = 0; }
{
 if($2 == "抵抗") {
  printf("%s %s %d %d %d\n",$1,$2,$3,$4,$3*$4);
  goukei += $3*$4;
 }
}
END { printf("合計 = %d 円\n",goukei); }
BEGINの後の{}でくくられた範囲は、ファイルを読み込む前に実行されます。また、ENDの後の{}でくくられた範囲は、ファイルを全て読み込んだ後に実行されます。BEGINとENDの間にある{}でくくられた範囲が、ファイルの1行毎に実行される部分です。データ・ファイルの各フィールドを参照したい場合にはフィールド演算子$を用います。$の後に数値nを書くと、$nはn番目のフィールドのデータを参照することになります。なお、行全体を参照する場合は$0とします。変数には数値や文字列の区別はありません。また配列を使用することもできます。プログラム構文はC言語とほぼ同様で、条件文やループ文が使用できます。また、関数を定義することも可能です。上記のプログラムはjgawkの場合、DOSプロンプトから、
jgawk -f sample.awk in.txt > out.txt
のように実行します(out.txtは結果を格納するファイル、リダイレクトを指定しない場合は画面への表示となります)。結果は、リスト3のようになります。
リスト3 結果出力(out.txt)

10kΩ 抵抗 10 2 20
20kΩ 抵抗 10 3 30
100kΩ 抵抗 15 1 15
合計 = 65
 通常アセンブラのソース・ファイルは各行に、
[命令] [引数] [コメント]
のように記述しますから、[命令]や[引数]をスペースやタブで区切られたフィールドとみなすと、awkで処理するのに打って付けです。
アセンブラの文法

 アセンブラでは命令以外にも、ラベルやコメントなども必要となりますから文法を定めなければなりません。今回製作したアセンブラの文法はリスト4を参照して下さい。
リスト4 簡易クロス・アセンブラの文法

/* この行のように行頭が"/*"で始まる行はコメント行です
/* "/*"の後には1文字以上の半角スペース又はタブが必要です
/* 下記のような空白行があっても構いません

/* セパレータは半角スペース、タブ、","の3種類です使用します

/* ID情報及びコンフィグレーション・ヒューズを設定します
/* アドレスは16進4桁で、データは2進14ビットで指定します
/* 指定可能なアドレスはID情報が2000〜2003
/* コンフィグレーション・ヒューズが2007です
#CNF 2000 11111111111111
#CNF 2007 00000000010001
/* アドレスが小さいものから順に記述します

/* データ・メモリを設定します
/* アドレス及びデータは16進2桁で指定します
/* 指定可能なアドレスは00〜3F、データは00〜FFです
#DAT 00 50 ;'P' 命令行のコメントは";"から始まります
#DAT 3F 0D ;
/* アドレスが小さいものから順に記述します

/* 定義命令
/* 名称 数値 名称に用いる文字は制限はありません
#DEF IND0 00 ;ファイル・レジスタのアドレスを定義する場合は、
#DEF TMR0 01 ;16進2桁(00〜FF)で指定します
#DEF RB0 0 ;ファイル・レジスタのビット・アドレスを定義する
#DEF RB7 7 ;場合は、0〜7を指定します
#DEF CONST1 FF ;定数を定義する場合は、16進2桁(00〜FF)を指
#DEF CONST2 00 ;定します
#DEF WREG 0 ;宛先指定子dを定義する場合は、0又は1を指定します
#DEF ADDR1 128 ;プログラム・メモリのアドレスを指定するときは1
#DEF ADDR2 256 ;0進数で指定します

/* アドレスを指定します
#ORG 0 ;アドレスは10進数で指定します

GOTO MAIN ;ラベルMAINに分岐します

#ORG 128
#LBL MAIN ;ラベルMAINを定義します、ラベルに用いる名称には
;制限はありません
MOVF TMR0, WREG ;TMR0とWREGの間に","を入れても
SUBWF IND0 WREG ;のように、いれなくてもかまいません
SUBLW #30 ;引数を直接指定する場合は、#を付けた16進数を使
;用します

/* プログラムの終わりを示す、疑似命令はありません
使い方

 アセンブラには下記の1)〜4)のawkプログラムを使用します。ただし、プリンター・ポートに接続するライタの場合には4)は不要です。なお、下記のプログラムで使用したawkのコマンドを表2に示します。
1)picasm1.awk(リスト5)
 ラベルや定義文字列などを数値に置き換えるものです。
2)picasm2.awk(リスト6)
 命令や数値をPIC16C84のオペコードに変換し、リスト・ファイルを作成するもので、アセンブラの中核となるものです。
3)picasm3.awk(リスト7)
 リスト・ファイルからプリンター・ポートに接続するライタで使用する、独自フォーマットのオブジェクト・ファイルを抽出するものです。
4)picasm4.awk(リスト8)
 3)で作成した独自フォーマットのオブジェクト・ファイルをインテルのHEXフォーマット・ファイルに変換するものです。

 ソース・ファイルをアセンブルする場合には、リスト9に示したバッチ・ファイルを使用します(このバッチ・ファイルでは、AWKプログラムの検索パスを環境変数AWKASMで、作業用ディレクトリを環境変数TMPで指定していますので、AUTOEXEC.BATなどでSETコマンドにより定義して下さい)。例えば、SAMPLE.ASMをアセンブルする場合には、
picasm sample.asm
とします。アセンブルが終了すると、作業用ディレクトリには、
out.ps1(作業用中間ファイル)
out.lst(リスト・ファイル)
out.txt(独自フォーマットのオブジェクト・ファイル)
out.obj(インテルHEXフォーマットのオブジェクト・ファイル)
の4つのファイルが作成されます。
 リスト9のバッチ・ファイルでは上記1)〜2)のプログラムでエラーが発生した場合にエラー・メッセージを表示し処理を中断します。エラーの内容は作成される各ファイルに埋め込まれます。
参考・引用文献

  1. Dale Dougherty(福崎俊博訳)、sed & awkプログラミング、アスキー出版局、1991

▲▲ トップページに戻る    ▲ 前のページに戻る