リンカ WLK

石上達也
 
 大規模なプログラム開発には,リロケータブルアセンブラを用いると有利です。そのとき,リロケータブルアセンブラから出力された個々のリロケータブルファイルをつなげ(リンクし)1本のオブジェクトファイルを出力するのがこのリンカです。
 ざっと使い方を説明しましょう。モニタから起動してプロンプト‘*'が出ている状態が,入力可能状態です。ここでは,ディスクに収録されているYGCSのサンプルプログラム(YGCS_SMP.OBJ)のリンク作業を例にとって説明します。
 まずYGCS_SMP.OBJのメモリ配置は,
  8000H番地
からコードセグメント,
  9000H番地からが
データセグメントですので,それぞれのスタートアドレスをリンカに知らせてやります。
 それには,
  */P:8000,/D:9000
と入力します。そして,YGCS_SMP.OBJ本体は,1本のプログラムですから,リンクするプログラムも1本ですみます。
  *YGCS_SMP
以上のように打ち込むとリンクが完了します。
さて,リンクするプログラムが複数の場合も説明しておきましょう。ここでは,AAA.REL,BBB.REL,CCC.RELのリロケータブルファイルをリンクすることを考えます。まず,
   *AAA
と打ち込むと,画面上に未定義ラベルとそのラベルが初めて使用された場所が示されますさらに残りのファイルをリンクしていきましょう。
   *BBB,CCC
 以上のように打ち込むと画面上にプロンプトだけが表示されてリンクが終了したことを告げてくれます。
 リンクが終わった状態で,もしラベルリストがほしければ,
  *LABEL/M
と入力してください。ファイル“WZD.MAP"にラベルリストが収録されています。
 次に,オブジェクトをセーブします。YGCS_SMP.ASMはデータセグメントに初期条件などを置いていないので(つまり,実際に必要なのはコードセグメントのみなので),
  *YGCS_SMP/N:P
と入力すれば,“YGCS_SMP.OBJ"というファイル名で,オブジェクトファイルを作ります。そして,オブジェクトを生成する段階で,
  *YGCS_SMP/N
とやってしまうとデータセグメントに割り振ったワークエリア領域までも含んだファイルができてしまいます。これでも動くオブジェクトができあがりますが,データの初期化をきちんとやっているプログラムでは,かなりの無駄な部分まで含んでしまいます(もちろんデータセグメント領域に初期データを置いてある場合は,ちゃんとワークエリア領域も含めたオブジェクトを生成しなくてはなりません)。
 と,こんな具合にリンク作業は行うのですが,要は,/P:スイッチと/D:スイッチで,スタートアドレスを決めてやり,リンクしたいファイルの名前を打ち込んでやればいいのです。
 そうしたら,/Nスイッチで,それらをオブジェクトファイルとして,取り出せます。
 

◆プログラム

 このプログラムもWZDと同様に腕力にものをいわせて作ったものです。それぞれのアイテムに応じて,適当な処理を行います。サブルーチンも何カ所か同じようなものが出てきたら,適宜作っていくという感じです(WZDと違いリンカは,これでも作れた)。
 サブルーチンごとに,ほとんどが独立しているので解析はそんなに困難ではないと思います。WZDと同様にWLK1.ASMは,最初Small-Cを用いて作成しました。
 このとき,
  1. ローカル変数は,だいたい1関数につき3つ以内(BC,DE,HLレジスタに対応させることができる)
  2. グローパルなポインタは2つ以内(IX,IYレジスタに対応させることができる)
という条件が満たされていたのでハンドコンパイルは,たいへんスムーズに行えました。
 気になるサイズですが(プログラムのサイズです。念のため),だいたいSmall-Cでコンパイルしたときの1/3程度になりました(ライブラリは除いた本体のみ)。メモリマップの変更は,リンカに与えるパラメータとWLKのヘッダファイルであるWLK.Hの内容を変更することによって行えます。
 現在,ローカルなラベルは1024個使用できるようになっていますが,この数を変更するときもこのWLK.Hを書き換えます。配布ディスクにはソースリストが収録されていないため,実際に試すことができませんが,一応,WLKをソースからアセンブルする方法を説明しておきます。
#L WZD
#J3000
*=WLK1
*=WLK2
*=WLK3
*
[ここで、SHIFT+BREAKキーを押す]
#L WLK
#J3000
*/P:3000,/D:4500
*WLK1,WLK2,WLK3,WLK/N:P
とすれば,配布ディスクに収録したものと同様なオブジェクトが得られます。
 いうまでもないと思いますが,ソースリストのみを一生懸命に入力しでも,WZDとWLKのオブジェクト形式のプログラムがなければ,アセンブラを通してオブジェクトを得るということはできません。
 まず最初に,WZDとWLKのオブジェクト・プログラムが絶対に必要です。
 最後にばらしてしまいますが,べき乗を行うサブルーチンは,第1パラメータ(HLレジスタ)を,第2パラメータ(DEレジスタ)回掛け合わせるということをしています。本当は,
A^B=EXP(B×Log(A))
を展開して,ゴリゴリ計算したかったのですが,メモリを大量に使ううえ,浮動小数のレベルで計算しなければ精度が出ないので,しかたなしに,中学l年生しています。
 

WLKリファレンスマニュアル

■パラメータ

 以下,[ファイル名]とあるのは,大文字小文字を区別し,スイッチ(/Sとか/Nとか)は,どちらでもかまいません。
*[ファイル名]
 [ファイル名]で表されたりロケータブルファイルを,取り込みます。省略時の鉱張子は‘.REL'です。
*[ファイル名]/S
 [ファイル名]で表されたライブラリファイルを,未定義なモジュールに限り取り込みます。省略時の拡張子は,‘.LlB'となります。
 ライブラリファイル,そしてモジュールなどについては,ライブラリアンWLBの記事を参照してください。
*/P:xxxx
 コードセグメントの領域を,アドレスxxxx(16進数で4桁以内)から取ります。
*/D:xxxx
 データセグメントの領域を,アドレスxxxx(16進数で4桁以内)から取ります。
*[ファイル名]/N
 リンクの結果を[ファイル名]で表されるファイルにコードセグメント,データセグメントともに出力します。デフォルトの拡張子は,‘.OBJ'です。以下同様。
*[ファイル名]/N:P
 リンクの結果を[ファイル名]で表されるファイルにコードセグメントのみ出力します。
*[ファイル名]/N:D
 リンクの結果を[ファイル名]で表されるファイルにデータセグメントのみ出力します。
*[ファイル名]/M
 ラベル情報を[ファイル名]で表されるファイルに出力する(外部ラベルの情報のみ)。
SHIFT+BREAK
 リンカの作業を中断し“SWORD"のコマンドラインに戻ります。
 

■エラーメッセージ

・Undefined Item-xx
 未定義アイテムxxを使用した。つまり指定されたリロケータブルファイルの内容がおかしい。WZDを使用している場合には起こらない。
・Multi Defined
 同じラベル名が,2力所以上で定義されている。このメッセージの後ろに16進2桁の数字が表示されたらそのラベル番号を持つ内部ラベルがエラーであり,文字列が表示されたらその名前の外部ラベルがエラーである。
・Undefined Label
 未定義ラベルが使用された。内部エラーと外部エラーの区別については,Multi Definedエラーのときと同様である。
・Too Many Labels
 使用されたラベルの数が多すぎる。
・Too Far
 相対ジャンプ関係のオブジェクトを作成しようとしたが,目的のアドレスが相対ジャンプで届く範囲にない。
・Stack Over
 演算用のスタックがオーバーした(16レベル以上のスタックが使用された)。
・Stack Empty
 演算用のスタックが空なのにその内容を参照するアイテムが使用された。
・Illegal ORG to xxxx
 PC(Position Counter)を後ろ向きにアドレスxxxxに変更しようとした。以下のオブジェクトファイルの内容は保証されない。
・DSEG buffer is Over Flowed!!
 DSEGエリア用のバッファが足りなくなった(DSEG用のバッファは8Kバイト,これ以上のメモリを用いる場合は,WLK.H内のメモリテーブルを変更するか,ほかのセグメントに割り振ってください)。
 
(C)1990 Tatsuya Ishigami(original)
(C)1997 Junji Okazaki(edited)
(C)2024 Oh!Ishi,Nibbles Lab.(formatted)