【リロケータブルとは?】
リロケータブルというのは何のことでしょうか? これは大きなプログラム
を作る時に必要とされるもので、下記のような特徴を持ったプログラムの
作り方を言い、MPASMはこの機能を内蔵しています。
(1) プログラムを分割して作成し、アセンブルはそれぞれ独立に行う
ことができる。そしてアセンブルした後に、それらの必要な部分を
関連付けして「リンク」することができる。
(2) 分割して作成したプログラムを、各々メモリ内の場所を指定して
配置することができる。
(3) 別モジュールにある変数を共有したり、別モジュールにジャンプしたり
サブルーチンを使ったりすることが出来ます。
このため、繰り返し使うサブルーチン群をまとめて「ライブラリ」として
おき、何時でもリンクして使うことができる。
(4) アセンブラだけでなく、C言語や他の言語でできたプログラムも
リンクして使うことができる。
このリンクには「MPLINK]を使用する。
【リロケータブル用指示命令】
まずは、アセンブラ言語でリロケータブルなプログラムを作成するには
どうすれば良いのでしょうか?
リロケータブルにするためには下表の指示命令が重要な役割をします。
これらの指示命令により、アセンブラがリロケータブルであることを判断
してそれぞれに適する処理をします。
命令
機 能
書 式
CODE
実行プログラムの指定 [<name>] code [<address>] UDATA
初期化無しのデータエリア確保。
RES命令でエリアを確保する。[<name>] udata [<address>] UDATA_OVR
初期化無しの変数エリアで複数モジュールから使用できる。
RES命令でエリアを確保する。[<name>] udata_ovr [<address>] UDATA_SHR
初期化無しの変数エリアで全バンクに共通とされる。RES命令でエリアを確保する。 [<name>] udata_shr [<address>] IDATA
初期化付きのデータエリア確保をする。
RES,DB,DW命令でデータを定義する。[<name>] idata [<address>] CBLOCK
名前付きリストで変数エリアを確保する。
ENDCまでの複数行の記述ができる。cblock [<expr>] ENDC
〃 endc GLOBAL
他のモジュールでも使える変数であることを定義する。 global <label>[ ,<label>] EXTERN
他のモジュールでGLOBAL定義されていることを宣言する。 extern <label>[ ,<label>] BANKSEL
labelで指定されたデータが存在するバンクに切り替える banksel <label> PAGESEL
labelで指定されたプログラムが存在するpageに切り替える pagesel <label>
【指示命令の詳細】
【リロケータブルなソースの構造】
では実際に上記の指示命令を使って、リロケータブルなソースファイル
を作成する方法です。
(1)単一なバンクとページで良いときのソースファイル
一つのバンクやページの中でプログラムが完了するときのリロケー
タブルなプログラムは下記のような構造のソースファイルとします。
<モジュール1> 定義モジュール
UDATA ;変数エリア定義
INGAIN RES 1 ;エリア確保
OUTGAIN RES 1
GLOBAL INGAIN,OUTGAIN ;グローバル変数定義
CODE ;プログラム部指定
FILTER
GLOBAL FILTER ;グローバル定義
・・・・・・
・・・・・・
END
<モジュール2> 実行モジュール
EXTERN INGAIN,OUTGAIN,FILTER ;外部変数定義
UDATA ;変数エリア定義
READ RES 1 ;変数エリア確保
CODE ;プログラム部指定
・・・・
・・・・
MOVLW GAIN1
MOVWF INGAIN ;外部変数も通常と
MOVLW GAIN2 ;同じ扱い
MOVWF OUTGAIN
MOVF READ,W
CALL FILTER ;外部プログラムも同じ
・・・・
・・・・
END
(2)複数バンクやページを使うとき
データやプログラムが複数のバンク、ページを使うときには、どのバンク
かページかを指定する必要がありますが、リンクするまでは、どのバンク
、ページに存在するかは不明なままとなってしまいます。
このような時には、下記のように、BANKSELやPAGSEL指示命令を使って
ソースファイルを作成します。
<モジュール3> 複数バンク、ページのモジュール
LIST P=16C73A ;通常と同じ定義方法で可
#INCLUDE "PIC16C73A.INC"
VAR1 EQU 010H ;Bank0とする
VAR2 EQU 030H ;Bank1とする
・・・・
CODE ;プログラムエリア開始
MOVLW IVAL ;初期値定数ロード
BANKSEL VAR1 ;Bankを指定
MOVWF VAR1 ;変数にセット
BANKSEL VAR2 ;Bankを指定
MOVWF VAR2
PAGESEL SUBPRO ;Pageを指定
CALL SUBPRO
・・・・
・・・・
(別のバンクから開始しているとする)
SUBPRO CLRW
・・・・ ;
・・・・ ;一つのサブルーチンが
RETURN ;ページをまたがってはならない
【リロケータブルなソースの実例1】
下記はMPASMに実例として紹介されているリロケータブルなプログラム
の実際で、1バイトの掛け算のサブルーチンをライブラリとして使える
ようにした例です。
このライブラリは、常にソースとしてモジュールを使う側のモジュールと
一緒にアセンブルする必要は無く、オブジェクトファイルとしておいて、
使う側のモジュールのオブジェクトを作った後に、リンカで一緒にリンク
して使うことができます。
このようなリロケータブルなライブラリとしておくことで、ライブラリを
色々なプログラムで共用して使うことができます。
例えば、液晶表示や他の周辺機器のサブルーチンをリロケータブル
なサブルーチンとしておけば、どのプログラムにも共通にメモリ配置も
気にすること無く使うことが出来ます。
<リロケータブルプログラム例>
《メインモジュール》
LIST P=16C54
#INCLUDE "PIC16C5x.INC"
EXTERN MULCND,MULPLR,H_BYTE,L_BYTE
EXTERN MPY
CODE
START CLRW
OPTION
MAIN MOVF PORTB,W
MOVWF MULPLR
MOVF PORTB,W
MOVWF MULCND
CALL_M CALL MPY
GOTO MAIN
RESET CODE 01FFH
GOTO START
END
《ライブラリモジュール》
LIST P=16C54
#INCLUDE "PIC16C5x.INC"
UDATA
MULCND RES 1
MULPLR RES 1
H_BYTE RES 1
L_BYTE RES 1
COUNT RES 1
GLOBAL MULCND,MULPLR,H_BYTE,L_BYTE
CODE
MPY
GLOBAL MPY
CLRF H_BYTE
CLRF L_BYTE
MOVLW 8
MOVWF COUNT
・・・・・
・・・・
RETLW 0
END
【リロケータブルなソースの実例2】
下記は、PIC活用例にある「周波数カウンタ」を例にして、リロケー
タブルな形式で作成したものです。
全体は下記の3つのモジュールで構成されています。
(1) ベクター定義モジュール(cntvct.asm)
リセットと割り込みのエントリーを指定する絶対番地にGOTO文
だけで出来ているモジュールです。
(2) メインモジュール(cntmain.asm)
カウンタとしての機能を実現しているモジュールです。
(3) ライブラリモジュール(cntlib.asm)
液晶表示器の制御サブルーチンと、タイマサブルーチンの
ライブラリモジュールです。
(4) これに標準リンクファイルが付きます。(16F84.lkr)
以上の4つのファイルをProject "newcnt.prj"として登録しています。
これでリンクした結果は、"newcnt.hex"として出力されます。
下記で上記3個のソースファイルをダウンロード出来ます。
★ リロケータブル構成のカウンタソースファイル