第19章
シンボル表の出力と
診断用スイッチ
/Sを付けると、TATARAはアセンブルが終わったときにシンボル表(symbol table)を表示します。ソースが定義したすべての名前が、その値とともに、セグメントごとにまとめて表示されます。ラベルがどこに置かれたか、EQUにどんな値が与えられたか、モジュールがどの名前をパブリックにし、どの名前をほかのモジュールに求めているかを確かめるには、これがいちばん手早い方法です。
この章では、TATARAがソースをどう読んだかを示す3つのオプション、/F、/M、/Hについても説明します。これらはプログラムを書くためには必要ありませんが、TATARAの問題を報告するときには、その出力を一緒に送ってください。
19.1 シンボル表
/Sは、最後の行をアセンブルしたあと、要約行の前にシンボル表を表示します。そのため、要約行は画面の最後に残ります。リスティング・ファイルを書き出すときでも、シンボル表は必ず画面に表示されます。
次のソースは、それぞれの種類の名前を1つずつ定義しています。
public start,count,limit,level extrn print,exit limit equ 100 level defl 1 level defl 2 tmp defl 3 cseg start: ld hl,msg call print call MIXED jp exit wait macro local loop loop: djnz loop endm wait wait Mixed: ret after equ start+1 dseg count: ds 1 msg: db 'Hi$' cseg music tune: db 0 end
A:\>tatara /s syms.as syms.tro Tatara MSX Macro-Assembler v1.2.0 Copyright (C) 2026 Javier Lavandeira https://tatara.tools ASEG - absolute 0002h public var level 0003h var tmp 0064h public limit CSEG - default code segment, 0011h bytes 0000h public start 0001h after 000Ch ??0000 000Eh ??0001 0010h Mixed DSEG - default data segment, 0004h bytes 0000h public count 0001h msg music - named code segment, 0001h bytes 0000h tune EXTERNAL - resolved by the linker exit print ended at SYMS.AS(26)
/Qも付けると、バナーと要約行が省かれ、シンボル表だけが表示されます。
19.2 シンボル表の読み方
19.2.1 セクション
シンボル表には、モジュールのセグメント(10章)ごとに 1つずつセクションがあり、そのあとに外部の名前のセクション、PUBLICで宣言して定義していない名前のセクションが続きます。各セクションは見出しの行で始まります。見出しの形を表19.1に示します。
見出し |
セクション |
ASEG - absolute |
アブソリュート・セグメントと、すべてのアブソリュートな値 |
CSEG - default code segment, 0011h bytes |
標準のコード・セグメント |
DSEG - default data segment, 0004h bytes |
標準のデータ・セグメント |
music - named code segment, 0001h bytes |
名前付きコード・セグメント |
scratch - named data segment, transient, group reading, 0042h bytes |
名前付きデータ・セグメント。この例はトランジェントで、グループがある(10.6節) |
EXTERNAL - resolved by the linker |
|
UNDEFINED - named by PUBLIC, never defined |
見出しの大きさは、そのセグメントがこのモジュールで占めるバイト数です。アブソリュート・セグメントのバイトはメモリのどこにでも置けるので、アブソリュート・セグメントには大きさがありません。
3つの標準のセグメントには、シンボルがなくても必ずセクションがあります。何も定義しないソースでも、次のように表示されます。
ASEG - absolute (no symbols) CSEG - default code segment, 0001h bytes (no symbols) DSEG - default data segment, 0000h bytes (no symbols)
名前付きセグメント、外部の名前、定義されていない名前のセクションは、入れるものがあるときにだけ表示されます。
19.2.2 シンボルの行
セグメントのセクションの各行には、シンボルの値、種類、名前が表示されます。行は値の順に並びます。
- 値は、セグメントの中のオフセットです。Mixedは、TANRENがコード・セグメントをどこに置いても、その始まりから10h バイトのところにあります。アブソリュート・セグメントでは、値そのものです。after equ start+1のように値がリロケータブルなEQUは、その値のセグメントに属します。DEFLの名前には、最後に与えられた値が表示されます。levelは2です。
- 種類は、表19.2の言葉のどれかです。
- 名前は、定義したところで書いたとおりに表示されます。このソースはMixed:を定義する前にMIXEDを使っていますが、シンボル表にはMixedと表示されます。/Cを付けると、これらは別の名前になります(7章)。
??0000と??0001は、waitを2回使ったときにLOCALが作った名前です(16章)。これらはふつうのラベルで、使うたびに1つずつ作られます。
19.2.3 値を持たない名前
外部の名前は、それを使うモジュールの中では値を持ちません。値は TANRENがほかのモジュールから見つけます(25章)。外部の名前は、値も種類もなしに、特に決まっていない順で表示されます。
PUBLICで宣言して定義していない名前があると、TATARAはオブジェクト・ファイルを書き出すときに止まります(12章)。オブジェクト・ファイルがなければ、ソースは受け付けられ、/Sはその名前を専用のセクションに表示します。次のソースは、2つの名前をパブリックと宣言し、そのうち1つだけを定義しています。
public here,nowhere here: ret end
A:\>tatara /s undef.as ... CSEG - default code segment, 0001h bytes 0000h public here DSEG - default data segment, 0000h bytes (no symbols) UNDEFINED - named by PUBLIC, never defined nowhere
19.3 シンボル表とリスティング
リスティング・ファイルは、独自のシンボルのページで終わります(18.2.1節)。19.1節のソースでは、次のようになります。
Macros: wait Symbols: 000E' ??0001 000C' ??0000 0000* exit 0003 tmp 0000' tune 0001' after 0010' Mixed 0000' count 0001' msg 0000' start 0002 level 0000* print 0064 limit
このページには同じシンボルが、M80と同じ形で表示されます。1行に3つずつ、特に決まっていない順で並び、リロケータブルな値には’、外部の名前には*が付きます。値がどのセグメントに属するかや、名前がパブリックかどうかは表示されません。tuneとstartはどちらも0000’ですが、一方はmusicに、もう一方は標準のコード・セグメントにあります。/Sのシンボル表にはその両方が表示されるので、それが問題になるときは、こちらを見てください。
/Lと/Sを一緒に付けると、両方が出力されます。ページはリスティング・ファイルに、シンボル表は画面に出力されます。
19.4 診断用スイッチ
/F、/M、/Hは、TATARAがソースから何を作ったかではなく、ソースをどう読んだかを示します。TATARAがある行を思いがけないように扱ったときは、その行に関係するオプションを付けてもう一度アセンブルし、その出力を報告と一緒に送ってください。MSX-DOSでは、>で出力をファイルに保存できます。
tatara /f prog.as prog.tro > fields.txt
19.4.1 /F:各行のフィールド
/Fを付けると、各行をリスティングに表示する代わりに、TATARAがその行をどのようにフィールドに分けたか(6章)が表示されます。次のソースには、コメント、条件付きアセンブルで飛ばされる行、マクロ、インクルード・ファイル、セミコロンを含む文字列があります。
; FIELDS.AS - what /F shows. two macro x db x,x endm cseg start: ld hl,msg ; a comment if 0 nop endif two 5 include finc.inc msg: db 'a;b' end
FINC.INCには、コメントの行とretがあります。
A:\>tatara /f fields.as fields.tro ... [][][][; FIELDS.AS - what /F shows.][00][00:0001] [two][macro][x][][01][00:0002] [][cseg][][][1A][00:0005] [start][ld][hl,msg][; a comment][00][00:0006] [][if][0][][08][00:0007] [][nop][][][00][00:0008] [][endif][][][13][00:0009] [][two][5][][00][00:000A] [][db][5,5][][20][00:0003] [][include][finc.inc][][14][00:000B] [][][][; FINC.INC - included by FIELDS.AS.][00][01:0001] [][ret][][][00][01:0002] [msg][db]['a;b'][][20][00:000C] [][end][][][15][00:000D] ended at FIELDS.AS(13)
出力の各行は、角かっこで囲んだ6つの部分からなります。
- ラベル(コロンは除く)
- オペレーション
- オペランド
- コメント
- TATARAが疑似命令ごとに付けている番号(16進数)。疑似命令でない行では00
- その行がどこから来たか。ファイルの番号(コマンド・ラインで指定したソースが00、インクルード・ファイルは開いた順に01から)と、そのファイルの中での行番号(16進数)
出力には、各行が第1パスで読まれたとおりに表示されます。このnopのように、条件付きアセンブルで飛ばされた行も表示されます。マクロの展開から作られた行には、それが来たマクロ本体の行が表示されます。db 5,5は、db x,xを書いた3行目です。マクロ本体の行は、マクロを使ったときにだけ表示され、定義したときには表示されません。’a;b’の中のセミコロンはオペランドの一部で、コメントの始まりではありません。
/Fの出力は、/Pを付けても付けなくても画面に表示されます。
19.4.2 /M:マクロの定義
/Mを付けると、マクロの定義を読んだときに、TATARAが記憶したとおりの定義が表示されます。
; MDUMP.AS - what /M shows. put macro x,y local skip ld a,x ; kept jr skip ;; dropped lab&y: db '&x' skip: endm cseg put 1,2 rept 2 nop endm end
A:\>tatara /m mdump.as mdump.tro ... MACRO put: 2 parameters, 1 locals, 4 lines, MDUMP.AS(2) 4 | ld a,<0> ; kept 5 | jr <L0> 6 | lab<1>: db '<0>' 7 | <L0>: ended at MDUMP.AS(14)
最初の行には、マクロの名前、パラメーターの数、LOCALの名前の数、本体の行数、定義が始まる場所が表示されます。そのあとに、本体の各行が、ソースでの行番号とともに表示されます。
- パラメーターは、MACROの行での順に<0>、<1>のように、LOCALの名前は<L0>、<L1>のように表示されます。lab&yはlab<1>になっています。&の働きはここで済んでいます(16.3節)。
- LOCALの行とENDMの行は記憶されません。
- ;;で始まるコメントは捨てられています(16.4節)。
ソースの最後のREPTのブロックは表示されません。/Mが表示するのはマクロだけで、繰り返しブロック(17章)は表示しません。
19.4.3 /H:使用中のメモリ
TATARAは、シンボルやマクロを、メモリ・マッパーの中のメモリのブロックに置き、必要になったときにブロックを取ります。/Hを付けると、アセンブルが終わったときにまだ使われているブロックの数が、要約行のあとに表示されます。
A:\>tatara /h heap1.as heap1.tro ... ended at HEAP1.AS(8) HEAP: 7 blocks.
この数が0になることはありません。シンボル1つにブロック1つ、マクロの定義には名前と本体のブロックが使われ、TATARA自身の記録もいくつかのブロックを使うからです。この数は、ほかのソースの数と比べるときにだけ役に立ちます。LOCALを持つマクロは、使うたびに新しい??の名前を定義するので、使うたびにブロックが1つ増えます。同じwaitを1回ではなく3回使うと、HEAP: 9 blocks.となります。