第12章
シンボルの定義と共有
シンボルとは、数の代わりに使う名前です(2章)。この章では、名前に値を与える3つの方法、1つの名前は1つの値しか持たないという規則、モジュールどうしで名前を共有するための疑似命令、そしてソースを終わらせ、プログラムがどこから始まるかを示すENDを説明します。
12.1 名前に値を与える3つの方法
表12.1に、その3つを示します。
| 書き方 | 値 | 変更 |
| name: | その行でのロケーション・カウンター | できない |
| name equ value | 与えた値 | できない |
| name defl value | 与えた値 | できる |
数に名前を付けると、プログラムが読みやすく、変更しやすくなります。ld c,9では何をするのかわかりませんが、ld c,_STROUTならわかります。また、その数が変わっても、直すのは名前を定義している行だけです。MSXDOS.INCの名前がEQUで定義されているのは、まさにこのためです(14章)。
12.2 ラベル
ラベルは、それを書いた行でのロケーション・カウンターの値、つまりその行が作る最初のバイトのアドレスを持ちます(10章)。ラベルは 1回だけ定義します。同じ名前のラベルがもう1つあると、TATARAは止まります。
LABTWICE.AS(3): ERROR: this name already has a value.
12.3 EQU
EQUは、名前に固定の値、つまりそのあとに書いた式の値を与えます。
five equ 5 screen equ 4000h here equ $ ; an address in the code
名前はコロンを付けずに書きます。コロンを付けると、TATARAはそれをラベルとみなし、EQUには名前がないことになってしまいます。five: equ 5と書くと、TATARAはEQU, DEFL and MACRO take a name, not a label.と表示して止まります。
値にはどんな式でも書けます(8章)。hereのように、アドレスでもかまいません。その場合、値は同じ場所にあるラベルと同じようにリロケータブルになります。ただし、外部の名前は書けません。外部の名前は、プログラムをリンクするまで値を持たないからです。
EQUで定義した名前は、それを定義する行より前でも使えます。次のソースでは、laterをEQUの前の行で使っていますが、TATARAは正しく0Ahとしてアセンブルします。
ld de,later later equ five*2
EQUが与える値は変わりません。同じ名前を同じ値で定義し直すのはかまいませんが、別の値で定義すると、TATARAはthis name already has a value.と表示して止まります。
12.4 DEFL
DEFLも名前に値を与えますが、その名前にはあとで、ソースに必要なだけ何度でも、新しい値を与えることができます。名前を使うそれぞれの行は、ソースのその位置での値を使います。
count defl 0 db count ; 00 count defl count+1 db count ; 01 count defl count+1 db count ; 02
DEFLで定義した名前は変数シンボル (variable symbol)と呼ばれることがあり、シンボル表にはvarと表示されます。変数シンボルは、ラベルやEQUと同じ名前を持てません。n equ 1のあとにn defl 2と書くと、TATARAはthis name already has a value.と表示して止まります。EQUと同じように、名前はコロンを付けずに書きます。
DEFLがいちばん役に立つのは、条件付きアセンブルやマクロの中で、ソースを読み進めるにつれて変わるカウンターやスイッチとして使うときです(15章から17章)。
注. ほかのコンピューターでM80を知っている人は、DEFLの別名としてSETという疑似命令を期待するかもしれません。しかし、Z80モードの M80にもTATARAにも、この疑似命令はありません。setはビットをセットするZ80の命令だからです。x set 5はその命令として読まれ、TATARAはnot a form this instruction has.と表示して止まります。定義し直せるシンボルはDEFLだけです(マクロも定義し直せますが、それは別の話で、16章で説明します)。
同じように、TATARAには.Z80という疑似命令もありません。M80では Z80のニーモニックを受け付けるためにこれが必要でしたが、TATARAはZ80のニーモニックしか受け付けず、切り替えるモードもありません。M80向けに書かれたソースが.Z80で始まっていると、その行でnot a directive, a macro or an instruction.と表示して止まるので、その行は削除してかまいません。
12.5 モジュールどうしで名前を共有する
2章で説明したように、プログラムはいくつかのモジュールで作ることができます。モジュールは、PUBLICでほかのモジュールに名前を提供し、EXTRNでほかのモジュールの名前を使います。どちらもコンマで区切った名前の並びをとり、それぞれに別名があります。PUBLICの別名はENTRY、EXTRNの別名はEXTです。また、both::のようにコロンを2つ付けて書いたラベルもパブリックになります(6章)。
次のモジュールは、それぞれ別の書き方で4つの名前を提供しています。
public greet,value entry other cseg greet: ret other: ret both:: ret value equ 5
PUBLICは、この例のように定義より前に書いても、あとに書いてもかまいません。パブリックにできるのは、ラベル、EQUの値、そしてDEFLの名前です。シンボル表には、パブリックな名前に印が付きます。
ASEG - absolute 0005h public value CSEG - default code segment, 0003h bytes 0000h public greet 0001h public other 0002h public both
次のモジュールは、それらの名前を使います。
extrn greet,value ext other,both cseg start: call greet call other call both ld hl,value ret end start
TATARAが外部の名前について知っているのは、ほかのモジュールが定義しているということだけなので、シンボル表には4つの名前がEXTERNAL - resolved by the linkerの下に表示されます。外部の値は TANRENが仕上げるので、ld hl,valueのように2バイトに入れる場所にしか使えません。ld a,valueのように1バイトに入れようとすると受け付けられません(8.6節)。2つのモジュールをリンクすると、完全なプログラムができます。
A:\>tanren /o:use.com use.tro pub.tro Tatara MSX Linker v1.2.0 Copyright (C) 2026 Javier Lavandeira https://tatara.tools 2 modules, 20 records, ends at EOF. Wrote USE.COM, 0100-010F (16 bytes), entry 0100.
TATARA自身が見つける誤りが2つあります。
- EXTRNで宣言した名前を同じモジュールで定義すると、TATARAはthis name already has a value.と表示して止まります。外部でもあり定義されてもいる、ということはありえないからです。
- PUBLICで宣言した名前がどこでも定義されていないと、TATARAはa PUBLIC name was never defined.と表示して止まります。この確認はTATARAがオブジェクト・ファイルを書き出すときに行うので、コマンド・ラインにオブジェクト・ファイルの名前がなければ、そのソースは受け付けられます。
どのモジュールも定義していない名前のように、複数のモジュールにまたがる誤りはTANRENが見つけます(27章)。
12.6 ENDと開始アドレス
ENDはソースを終わらせます。TATARAはそのあとを何も読みません。ENDを含むファイルを取り込んだファイルの残りも読みません(13章)。ENDのないソースも受け付けられ、その場合はファイルの終わりがソースの終わりになります。
ENDにオペランドがあれば、それはプログラムの開始アドレス(start address)、つまりプログラムが実行を始める場所を表します。TATARAはそれをオブジェクト・ファイルに書き込み、TANRENは要約行にentryとして表示します(4章)。
警告. MSX-DOS2は、ENDに何が書かれていても、.COMのプログラムを必ずファイルの最初のバイトである0100hから実行します。そのため、.COMのプログラムでは、ENDで示すラベルがコードの一番最初になければなりません。次のソースのようにデータが先にあると、プログラムはデータを命令として実行し、暴走してしまいます。TANRENはそれでもファイルを書き出しますが、開始アドレスがプログラムの実行が始まる場所ではないことを警告します。
cseg msg: db 'Started at start.',13,10,'$' start: ld de,msg ... end startWARNING: ENTRY.COM is entered at 0100, not at 0114. 1 modules, 7 records, ends at EOF. Wrote ENTRY.COM, 0100-0120 (33 bytes), entry 0114..COMのプログラムでTANRENがこの警告を出したら、ENDで示すコードを先頭に移すか、データをデータ・セグメントに移してください(10章)。
12.7 メッセージ
シンボルの定義と共有についてのメッセージを、それぞれの原因となる行とともに表12.2に示します。
もう1つ、正しいソースでは表示されることのないメッセージがあります。
phase error - this label had a different value on pass 1.
TATARAはソースを2回読み、ラベルはどちらのときも同じ値にならなければなりません。これがどんなときに起こるかは、20章で説明します。