Tatara

Chapter 19
The symbol table dump and the diagnostic switches

/S makes TATARA print the symbol table when the assembly ends: every name the source defined, with its value, grouped by segment. It is the quickest way to check where a label ended up, what value an EQU was given, or which names a module makes public and which it expects from others.

The chapter also describes /F, /M and /H, the three options that show how TATARA read a source. They are not needed to write programs, but their output is what to send with a report of a problem in TATARA.

19.1 The symbol table

/S prints the table after the last line has been assembled and before the summary line, so that the summary line is still the last thing on the screen. The table always goes to the screen, even when a listing file is written.

This source defines a name of each kind:

                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)
 

With /Q as well, the banner and the summary line are left out and only the table is printed.

19.2 Reading the table

19.2.1 Sections

The table has one section for each segment of the module (chapter 10), then one for the external names, then one for the names declared PUBLIC and never defined. Each section starts with a heading line; table 19.1 lists the forms it takes.

Heading

Section

ASEG - absolute

the absolute segment, and every absolute value

CSEG - default code segment, 0011h bytes

the default code segment

DSEG - default data segment, 0004h bytes

the default data segment

music - named code segment, 0001h bytes

a named code segment

scratch - named data segment, transient, group reading, 0042h bytes

a named data segment; transient and with a group (section 10.6)

EXTERNAL - resolved by the linker

names declared EXTRN

UNDEFINED - named by PUBLIC, never defined

names declared PUBLIC and not defined

Table 19.1: Section headings in the symbol table.

The size in a heading is the number of bytes the segment takes in this module. The absolute segment has no size, because its bytes can be anywhere in memory.

The three default segments always have a section, even when they have no symbols. A source that defines nothing still prints these:

ASEG - absolute 
 
(no symbols) 
 
CSEG - default code segment, 0001h bytes 
 
(no symbols) 
 
DSEG - default data segment, 0000h bytes 
 
(no symbols)
 

The sections for named segments, external names and undefined names appear only when there is something to put in them.

19.2.2 Symbol lines

Each line in a segment’s section has the symbol’s value, its type and its name. The lines are in order of value.

Type The name is
(blank) a label or an EQU name
public a label or an EQU name made public
var a DEFL name
public var a DEFL name made public
Table 19.2: The types in the symbol table.

The names ??0000 and ??0001 are the ones LOCAL made up for the two uses of wait (chapter 16). They are ordinary labels, one for each use.

19.2.3 Names with no value

External names have no value in the module that uses them: TANREN finds it in another module (chapter 25). They are listed with no value and no type, in no particular order.

A name declared PUBLIC and never defined stops TATARA when it writes an object file (chapter 12). Without an object file, the source is accepted, and /S lists the name in a section of its own. This source declares two public names and defines only one:

                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 The table and the listing

A listing file ends with a page of symbols of its own (section 18.2.1). For the source in section 19.1, it is this:

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
 

It holds the same symbols, in M80’s layout: three to a line, in no particular order, with ’ after a relocatable value and * after an external name. It does not say which segment a value belongs to, or whether a name is public: tune and start are both at 0000’, one in music and one in the default code segment. The table that /S prints says both, and is the one to read when that matters.

The two can be asked for together, with /L and /S: the page goes into the listing file, and the table to the screen.

19.4 Diagnostic switches

/F, /M and /H show how TATARA read a source, rather than what it made of it. If TATARA does something unexpected with a line, run the source again with the option that concerns it, and send the output with the report. MSX-DOS can save the output in a file with >:

tatara /f prog.as prog.tro > fields.txt
 

19.4.1 /F: the fields of each line

/F prints each line as TATARA divided it into fields (chapter 6), instead of listing it. This source has a comment, a line skipped by a conditional, a macro, an include file and a string that holds a semicolon:

; 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 holds a comment line and 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)
 

Each line of the output has six parts in square brackets:

  1. the label, without its colon;
  2. the operation;
  3. the operands;
  4. the comment;
  5. a number that TATARA gives each directive, in hexadecimal, or 00 for a line that is not a directive;
  6. where the line came from: the number of the file, 00 for the source named on the command line and 01 and so on for include files in the order they were opened, then the line number in that file, in hexadecimal.

The output shows each line as it is read on the first pass. Lines skipped by a conditional are shown, as nop is here. A line from a macro expansion shows the line of the macro’s body it came from: db 5,5 is line 3, where db x,x was written. The lines of a macro’s body are shown only when it is used, not when it is defined. The semicolon inside ’a;b’ is part of the operand, not the start of a comment.

/F prints to the screen, with or without /P.

19.4.2 /M: macro definitions

/M prints each macro definition as TATARA stored it, when the definition is read:

; 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)
 

The first line gives the macro’s name, the number of parameters, of LOCAL names and of lines in its body, and where the definition starts. Each line of the body follows, with its line number in the source:

The REPT block at the end of the source is not printed: /M shows macros only, not repeat blocks (chapter 17).

19.4.3 /H: memory in use

TATARA keeps its symbols and macros in blocks of memory in the memory mapper, which it takes as it needs them. /H prints, after the summary line, how many blocks are still in use when the assembly ends:

A:\>tatara /h heap1.as heap1.tro 
... 
ended at HEAP1.AS(8) 
HEAP: 7 blocks.
 

The figure is never zero: each symbol takes a block, each macro definition takes blocks for its name and its body, and TATARA’s own records take a few more. It is useful only when compared with the figure for another source. A macro with a LOCAL adds a block each time it is used, because each use defines a new ?? name: the same wait used three times instead of once gives HEAP: 9 blocks.