home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC Underground
/
UNDERGROUND.ISO
/
share
/
a86
/
a13.doc
< prev
next >
Wrap
Text File
|
1994-01-24
|
19KB
|
403 lines
CHAPTER 13 ASSOCIATED TOOLS AND OUTPUT FILES
Listings with A86
A86 has a powerful listing facility, that allows you to tailor
the format of your listings to your specific needs. Because the
listing pass adds a significant percentage to the time it takes
A86 to execute, the listing is not produced by default. You must
include either a +L switch, or the name of a file with a .LST
extension on the A86 invocation line.
By default (+L but nothing else specified), an A86 listing file
consists of a sequence of pages, each 59 lines long and 79
characters wide. Each page has a header line identifying A86 and
its version number, giving the name of the program output file,
the date and time of assembly, the name of the source file
currently being listed, and a page number. Note that I am not so
obnoxious as to splash my company name over the top of every page
of your listing! If both a TITLE and a SUBTTL have been
specified, the header consists of three content lines and one
skipped line; otherwise, there are just two content lines. Each
listing line has a sequential line number, a hex offset and hex
object bytes, an indicator field with "i" for include files and
"m" for macro expansions, and the source code itself. Nested
includes have no special indication; nested macros are indicated
by increasing indentation of the macro expansion line. A86 tries
to be intelligent about the formatting of its listings: it will
break up the wraparound of a long line at a word if reasonable.
It will avoid breaking up a multi-line listing of less than 10
lines. It will break pages at sensible locations (described in
detail shortly, under the PAGE directive). It will suppress
blank lines at the top and bottom of pages (but it counts them in
the sequential line numbering so you can tell they were there).
Five A86 switches, H, I, L, T, and W, allow you to control the
existence and characteristics of titling, pagination, page-number
format, page break control, source line numbering, hex object
display, and source line display. The operation of these
switches is described in detail in Chapter 3. Here are some
examples of switch settings that will produce listings meeting
some specialized needs:
+L21+T0+W12+I137 produces a listing consisting only of the source
code, with the hex offset of each line placed to the left, and
with the line truncated at 79 columns. Such a listing file would
be ideal for viewing the source file while debugging on a
primitive remote system that cannot run D86.
+L9+T0+W4+I128 produces a list file of just source code, with all
conditional-assembly lines and skipped code removed. All
titling, pagination, line numbers, and hex codes are eliminated,
so the list file could be renamed as a source file, and
reassembled. This might be useful for archival purposes, or for
giving individualized versions of a source file to parties who
don't need any of the conditional-assembly options you've
programmed.
13-2
+L+I186+H15+W12 produces a list file that concentrates on the hex
output, increasing the width to 16 bytes per line, showing up to
15 hex runover lines, and limiting the amount of source code
shown.
Listing Control Directives
In addition to the five switches just mentioned, A86 has a number
of source-code directives that control aspects of listings.
The .NOLIST directive causes all subsequent listing to be
suppressed, until a .LIST directive is seen. Line numbering and
page numbering continues during list suppression, so the result
is as if you had text-edited the listing file to remove all the
suppressed lines.
I also offer a macro-definition control code, #H, which causes
the suppression of the listing of macro expansion lines. If #H
appears anywhere within a macro definition, all calls to that
macro will be listed as the macro call line only, showing the
generated hex object bytes on that call line. This allows you to
define macros that will be listed as if they were simple machine
instructions. This effect can be achieved for all macros with an
L switch setting that doesn't include the value 4 (see Chapter
3).
The TITLE directive specifies a title that will appear at the top
of every page of the entire assembly. The title consists of the
first 60 characters starting with the first nonblank after the
word TITLE on the line. If you give more than one TITLE
directive in a program, only the first will be recognized.
The SUBTTL directive specifies a subtitle to appear at the top of
every page until another SUBTTL directive is given (or until the
next file change if you have the +T16 switch-bit value set). If
the directive is at the very top of the listing page, or it is
shortly after an automatic page break, the subtitle will take
effect on the page in which it appears. Otherwise, it will take
effect at the next page.
The PAGE directive serves several purposes. The word PAGE by
itself will force a new page in the listing, at that point. A
plus sign following the word PAGE causes a new page plus an
incremented section number -- e.g. PAGE + on page 1-17 will cause
a new page 2-1 to begin. The word PAGE followed by one or more
constant parameters will set various A86 listing variables to the
specified parameter values. The variables are as follows:
1. The length, in lines, of a listing page. Minimum is 10;
maximum is 65535.
2. The width, in characters, of the maximum listing line.
3,4,5,6. The number of lines at the end of a page, less than
which A86 guarantees will not be "widowed" after a page break
of level 1,2,3,4, respectively.
13-3
Omitted parameters (either left off the end or via leading commas
or 2 consecutive commas) will remain unchanged.
The concept of "page break levels" is unique to A86 listings: it
is my attempt to get A86 to make intelligent decisions about
where to issue new listing pages. There are 4 page break levels,
normally triggered by gaps (consecutive blank lines) in the
source code, and by source-file changes. One- and two-line gaps
cause breaks of level 1 and 2, respectively. Three-or-more-line
gaps cause a break of level 3. A source-file change causes a
break of level 4. If a page break occurs close to the end of a
page, and a break of greater level hasn't already been marked,
A86 will mark the point for a potential new page. If a page
break of equal or greater level doesn't occur before the page is
full, A86 will issue a new page at the marked point. The
definition of "close to the end of the page" is 10,20,30, and 40
lines, respectively, for break levels 1,2,3,4. Those line counts
can be changed by parmeters 3,4,5,6 of the PAGE directive, as
already described.
If you are intimidated by all this, or if you want to control
page break levels manually, you may specify a T switch value that
does not include the "auto-paging" option value 4. With that
option disabled, page break levels will occur only at places
where you issue a PAGE directive containing a special parameter
value /1, /2, /3, or /4. The leading slash indicates that a page
break of the indicated level is desired here. Such a parameter
will typically be given by itself following PAGE; but, if you
wish, it can be interspersed anywhere among other parameter
values -- it will not be "counted" for the purposes of
determining the other parameters' positions.
Cross-reference Facility
When you specify the +X switch, A86 will create a
cross-referenced symbol table listing of your program.
The output file, having a standard extension of .XRF is an
alphabetical listing of all the non-local symbols in your
program. For each symbol, A86 gives its type, the file in which
it was defined, its value, and a list of all procedures in which
the file was used. If you print this file, you typically use the
TCOLS tool to obtain a multi-column listing from A86's
single-column output.
Note the use of procedure names to identify references -- this
makes the cross-reference listing truly readable. Other
cross-reference listings often give either line numbers, which
are meaningless unless you go find the associated line; or a file
name, which doesn't give you as much useful information.
Here is a more detailed description of the various pieces of
information provided for each symbol:
13-4
1. TYPE. Labels are indicated by a colon immediately following
the symbol name. Special symbols such as macro names are
denoted by an appropriate word such as "macro" in place of the
value on the following line. Other symbol types are described
by one or two characters, following the symbol name.
Possibilities for the first character are:
m for a simple memory variable
+ for an index memory quantity
c for a constant
i for an interrupt equate
s for a structure
If there is a second letter, it is a size attribute: b for
byte, w for word, f for far (or doubleword).
2. FILE in which the symbol was defined. The name is stripped of
its extension, which is presumably the same for all your
source files. The name is preceded by = or period, which
denotes a definition of, not a reference to the symbol.
3. VALUE, given as 4 hex digits, on the line following the
symbol. For memory variables, this is the location of the
variable. For indexed quantities, this is the
constant-displacement part of the quantity. For structures,
it is the size of the structure. For interrupt equates, it is
the number of the interrupt.
4. REFERENCES, given on indented lines following the symbol name.
All occurrences of the symbol in your program produce a
reference. If the symbol is the first thing on a line, it is
considered a "definition" of that symbol, the reference listed
is the source file name. The name is preceded by a period if
the definition was via a colon (i.e., a label); it is preceded
by an equals sign otherwise. If the symbol is not the first
thing on the line, then it is not a definition. The reference
listing consists of the name of the last definition that A86
scanned (which, if your program is organized in a standard
way, will be the name of the procedure in which the reference
occurred.
Observe that you must use the local-label facility of A86 to
make this work. If you don't use local labels as your
"place-marker" symbols, the symbol the cross-reference gives
you will often be the name of the last "place-marker" symbol,
not the name of the last procedure.
To save space, duplicate reference entries are denoted by a
single entry, followed by "*n", where n is the decimal number
of occurrences of that entry.
13-5
A86LIB Source File Library Tool
There is a tool, A86LIB.COM, available only if you are
registered, that lets you build libraries of source files. To
use A86LIB, you must first code and debug the A86 source files
that you wish to include in your library. Then you issue the
command A86LIB followed by the names of the source files.
Wildcards are accepted; so you will typically want to gather the
source files into a single directory, and use the wildcard
specification. For example, if you use the filename extension .8
for your source files, you can issue the command A86LIB *.8 to
create the library.
The library created consists of a catalog file, always named
A86.LIB, together with the source files that you fed to A86LIB to
create the catalog.
The following observations about A86LIB are in order:
1. Unlike object-code libraries, A86.LIB contains only symbol
names and file names; it does not contain the code itself. You
MUST retain the source files used to create A86.LIB, because
A86 will read those files that it needs after consulting
A86.LIB to read their names.
2. A86LIB records all non-local symbols that start a line, and
are followed by a colon or an EQU. (Recall that local symbols
are those names consisting of a single letter followed by one
or more decimal digits.) A86LIB also records all symbols
appearing on lines starting with the word PUBLIC.
3. If a symbol appears in more than one library source file, it
will be logged for the first file A86LIB sees, and not the
subsequent ones. No error will be reported, unless and until
A86 tries to assemble both files in one assembly, and sees a
conflict.
4. A86LIB is simple-minded. A86LIB does NOT recognize or expand
macros; nor does it recognize conditional-assembly directives.
This is because the library files do not stand by themselves;
the macros and conditional-assembly variables being used might
well be defined in the main program of the programs accessing
the library files.
You may update A86.LIB by running A86LIB again; either with new
files or previously-recorded ones. If A86LIB is given a file it
had already read in a previous run, then A86LIB marks all the
symbols it had logged for the file as deleted, before rereading
the file. Those symbols that are still in the file are then
"unmarked". Thus, symbols that have been deleted from the file
disappear functionally from A86.LIB, but still occupy space
within A86.LIB. What I'm getting at is this: A86LIB will
tolerate alterations in library files quite nicely; but for
optimum storage efficiency you should delete A86.LIB and rebuild
it from scratch any time you delete anything from the library.
A86LIB is so fast that this is never very painful.
13-6
Using A86.LIB in A86 Assemblies
Once you have created a library with A86LIB, you access it simply
by calling the procedures in it from your A86 program. When A86
finishes an assembly and sees that there are undefined symbols in
your program, it will automatically look for copies of A86.LIB in
the current directory (then in other directories, as described in
the next section). If any of the undefined symbols are found in
the A86.LIB catalog, the files containing them are assembled.
You see this in the list of files output to the console by A86.
The subroutines in your library or libraries are effectively a
permanent part of the A86 language. They can be called up
effortlessly in your A86 programs. In time you can build up an
impressive arsenal of library modules, making A86 as easy to
program in as most high-level languages.
You may now have macros in your A86LIB library. Here's how it
works: when A86 sees a new symbol at the beginning of a line, in
a context where it would formerly have issued an error, A86 will
first look in the A86LIB libraries for the symbol. If it's
found, A86 will INCLUDE that library file on the spot, and then
assemble the line. NOTE that if the macro is being called within
a sequence of executable instructions, the library file must
generate no output object code.
Environment Variable A86LIB
You can set an environment variable A86LIB to specify which
drives or subdirectories contain A86.LIB files. The variable
consists of a sequence of path names separated by semicolons,
just like the PATH variable used by the operating system. For
example, if you include in your AUTOEXEC.BAT file the line
SET A86LIB=C:\bin\lib;\tools\a86lib
then A86 will look for A86.LIB in the current directory, then it
will look for C:\bin\lib\A86.LIB, then \tools\a86lib\A86.LIB. A86
will keep looking in all three catalog files, assembling the
appropriate source files from any or all of them, until there are
no more undefined symbols, or there are no more source files to
assemble.
For every symbol in an A86.LIB catalog, there is recorded the
name of the library file containing the symbol. The library file
is assumed to be in the same directory as its A86.LIB file,
unless a complete path name (starting with \ or a drive
specifier) was fed to A86.LIB when A86.LIB was created.
13-7
Forcing a Library Search
You may force A86 to assemble library files before moving on to
more of your program's source files. You do this by placing a
hash sign # (hex code 23) between file names in your invocation
line. For example, suppose your program has two modules FIRST.8
and LAST.8. FIRST.8 calls subroutines from your library; but you
need the library files assembled before LAST.8 is assembled. (You
might want this because LAST.8 allocates memory space beyond the
end of your program, which would be the end of LAST.8 if it were
truly the last module.) You accomplish this by the invocation
line:
A86 FIRST.8 # LAST.8
Note that there is never any need to force a library search at
the end of your program modules: A86 always makes a library
search there, if you have any undefined symbols.
You may now also force a library search from within a source
file, by placing a line with INCLUDE by itself with no file
names, into the source code. A86 will include any library files
necessary to resolve any forward-references at the point of the
INCLUDE.
Mimicking Tool: FAKE.EXE
As of this writing, Turbo C is aware only of the existence of
Microsoft's MASM for assembling source files it generates. I
hope to persuade Borland to provide a switch to Turbo C that
causes it to invoke A86 directly. Until that happens, I offer
the tool FAKE.EXE, that convinces Turbo C that A86 is really
MASM.
To use FAKE.EXE, it must be renamed MASM.EXE in your disk system.
I would have named it MASM myself, except that
1. Bill Gates would probably get mad at me if I did, and
2. You need to decide what to do with your real MASM if you have
it, before installing FAKE. You could either place FAKE
(named MASM.EXE) into the individual directories containing
Turbo C programs, or you can rename MASM to something like
MSM.EXE or REALMASM.EXE.
Having renamed FAKE.EXE to MASM.EXE, you may now use the Turbo
C's switch, -B, that allows you to place A86 statements into your
C program. You don't need to worry about the gory details of
what FAKE does.
If you like gory details, here they are: FAKE filters the command
line handed to it, replacing switches:
13-8
/D becomes =
/ml becomes +c
/mx becomes +C
/E becomes +f
FAKE also eliminates the semicolon, appends .ASM to the source
file name, and turns on the O and S switches. It then feeds the
resulting filtered command line to A86 for assembly.