Tatara

第12章
シンボルの定義と共有

シンボルとは、数の代わりに使う名前です(2章)。この章では、名前に値を与える3つの方法、1つの名前は1つの値しか持たないという規則、モジュールどうしで名前を共有するための疑似命令、そしてソースを終わらせ、プログラムがどこから始まるかを示すENDを説明します。

12.1 名前に値を与える3つの方法

表12.1に、その3つを示します。

書き方 値 変更
name: その行でのロケーション・カウンター できない
name equ value 与えた値 できない
name defl value 与えた値 できる
表 12.1: 名前に値を与える3つの方法

数に名前を付けると、プログラムが読みやすく、変更しやすくなります。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つあります。

どのモジュールも定義していない名前のように、複数のモジュールにまたがる誤りは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     start
 
WARNING: 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に示します。

行

メッセージ

five: equ 5

EQU, DEFL and MACRO take a name, not a label.

five equ 5のあとの
five equ 6、同じラベルを2回、
n equ 1のあとの
n defl 2、
EXTRNでもあり定義もされた名前

this name already has a value.

x equ far
(farは外部)

an external symbol may not be used here.

名前のないpublic

bad PUBLIC or EXTRN list.

public nowhere
(定義されていない)

a PUBLIC name was never defined.

x set 5

not a form this instruction has.

表 12.2: シンボルについてのメッセージ

もう1つ、正しいソースでは表示されることのないメッセージがあります。

phase error - this label had a different value on pass 1.
 

TATARAはソースを2回読み、ラベルはどちらのときも同じ値にならなければなりません。これがどんなときに起こるかは、20章で説明します。