11 UTILITIES

This chapter contains the following sections:

Overview

arxa

ccxa

mkxa

mppxa
Introduction
mppxa Invocation
Detailed Description of Macro Preprocessor Options
INCLUDE Files
Creating and Calling Macros
Creating Parameterless Macros
Creating Macros with Parameters
Local Symbols in Macros
The Macro Preprocessor's Built-In Functions
Comment, Escape and Bracket Functions
Comment Function
Escape Function
Bracket Function
METACHAR Function
Numbers and Expressions in mppxa
SET Function
EVAL Function
Logical Expressions and String Comparisons in mppxa
Control Flow Functions and Conditional Assembly
IF Function
WHILE Function
REPEAT Function
EXIT Function
String Manipulation Functions
LEN Function
SUBSTR Function
MATCH Function
Console I/O Functions
Advanced mppxa Concepts
Macro Delimiters
Implied Blank Delimiters
Identifier Delimiters
Literal Delimiters
Literal vs. Normal Mode
Algorithm for Evaluating Macro Calls

prxa
Preparing the Demo Files
Displaying Parts of an Object File
Option -h, display general file info
Option -s, display section info
Option -c, display call graph
Option -e, display external part
Option -g, display global type information
Option -d, display debug information
Option -i, display the section images
Option -il4, produce disassembly
View an Object at Lower Level
Object Layers
The Level Option -ln
The Verbose Option -vn

11.1 Overview

The following utilities are supplied with the Cross-Assembler for the XA processor family which can be useful at various stages during program development.

arxa An IEEE archiver. This is a librarian facility, which can be used to create and maintain object libraries.

ccxa A control program for the XA tool chain.

mkxa A utility program to maintain, update, and reconstruct groups of programs.

mppxa A macro preprocessor with a syntax compatible with Intel's macro processing language (MPL).

prxa An IEEE object reader that views the contents of files which have been created by a tool from the TASKING XA tool chain.

When you use a UNIX shell (Bourne shell, C-shell), arguments containing special characters (such as '( )' and '?') must be enclosed with "" or escaped. The -? option (in the C-shell) becomes: "-?" or -\?.

The utilities are explained on the following pages.

11.2 arxa

Name

arxa IEEE archiver and library maintainer

Syntax

arxa key_option [option]... library [object_file]...
arxa -V
arxa
-? ( UNIX C-shell : " -?" or -\? )

Description

With arxa you can combine separate object modules in a library file. The linker optionally includes modules from a library when a specific module resolves an external symbol definition in one of the modules that has been read before. The library maintainer arxa is a program to build library files and it offers the possibility to replace, extract or remove modules from an existing library.

key_option one of the main options indicating the action arxa has to take. Key options may appear in any order, at any place.

option optional sub-options as explained on the next pages.

library is the library file.

object_file is an object module to be added, extracted, replaced or removed from the library.

Options

You may specify options with or without a leading '-'. Options may occur in random order. You may also combine options. So -xv is allowed. -V and -? however, must be the only option on the command line.

Key options:

-d Delete the named object modules from the library.

-m Move the named object modules to the end of the library, or to another position as specified by one of the positioning options.

-p Print the named object modules in the library on standard output.

-r Replace the named object modules in the library if they exist. If they are not in the library, add them. If no names are given, only those object modules are replaced for which a file with the same name is found in the current directory. New modules are placed at the end.

-t Print a table of contents of the library. If no names are given, all object modules in the library are printed. If names are given, only those object modules are tabled.

-x Extract the named object modules from the library. If no names are given, all modules are extracted from the library. In neither case does x alter the library.

Other options:

-? Display an explanation of options at stdout.

-V Display version information at stderr.

-a posname
Append or move new object modules after existing module posname. This option can only be used in combination with the m or r option.

-b posname
Insert or move new object modules before existing module posname. This option can only be used in combination with the m or r option.

-c Create the library file without notification if the library does not exist.

-f file Read options from file file. '-' means stdin.

-o Reset the last-modified date to the date recorded in the library. It can only be used in combination with the x option.

-s Print a list of symbols. This option must be combined with -t.

-s1 Print a list of symbols. Each symbol is preceded by the library name and the name of the object file. This option must be combined with -t.

-u Replace only those object modules with the last-modified date later than the library file. It can only be used in combination with the r option.

-v Verbose. Under the verbose option, arxa gives a module-by-module description of the making of a new library file from the old library and the constituent modules. It can only be used in combination with the d, m, r, or x option.

-wn Set warning level n.

Examples

1. Create library clib.a consisting of the modules startup.obj, and calc.obj :

arxa cr clib.a startup.obj calc.obj

2. Extract all modules form library clib.a :

arxa x clib.a

3. Print a list of symbols from library clib.a :

arxa ts clib.a
startup.obj
   symbols:
        _start
        _copytable
calc.obj
   symbols:
        _entry

4. Print a list of symbols from library clib.a in a different form:

arxa ts1 clib.a
clib.a:startup.obj:_start
clib.a:startup.obj:_copytable
clib.a:calc.obj:_entry

5. Delete module calc.obj from library clib.lib :

arxa d clib.a calc.obj

11.3 ccxa

Name

ccxa control program for the XA tool chain

Syntax

ccxa [ [option]... [control] ... [file]... ]...
ccxa -V
ccxa
-? ( UNIX C-shell : " -?" or -\? )

Description

The control program ccxa facilitates the invocation of the various components of the XA family tool chain from a single command line. The control program accepts source files and options on the command line in random order.

Options are preceded by a '-' (minus sign). The input file can have one of the extensions explained below.

The control program recognizes the following argument types:

Normally, a control program tries to compile and assemble all source files to object files, followed by a link and locate phase which produces an absolute output file. There are however, options to suppress the assembler, linker or locator stage. The control program produces unique filenames for intermediate steps in the compilation process, which are removed afterwards. If the compiler and assembler are called subsequently, the control program prevents preprocessing of the compiler generated assembly file. Normally, assembly input files are preprocessed first.

Options

-? Display a short explanation of options at stdout.

-Ccpu Use special function register definitions for cpu.

-M{t|s|c|m|l}
Specify the memory model to be used:

-V The copyright header containing the version number is displayed, after which the control program terminates.

-Wa arg
-Wcarg
-Wcparg
-Wlkarg
-Wlcarg
-Wmarg

-Wplarg With these options you can pass a command line argument directly to the macro preprocessor (-Wm), assembler (-Wa), C compiler (-Wc), C++ compiler (-Wcp), C++ pre-linker (-Wpl), linker (-Wlk) or locator (-Wlc). These options may be used to pass some options that are not recognized by the control program, to the appropriate program. The argument may be either directly appended to the option, or follow the option as a separate argument of the control program.

-al Generate an absolute list file for each module in the application.

-c++ Specify that files with the extension .c are considered to be C++ files instead of C files. So, the C++ compiler is called prior to the C compiler. This option also forces the linker to link C++ libraries.

-c
-cc
-cl

-cs Normally, the control program invokes all stages to build an absolute file from the given input files. With these options it is possible to skip the C compiler, assembler, linker or locator stage. With the -cc option the control program stops after compilation of the C++ files and retains the resulting .c files. With the -cs option the control program stops after the compilation of the C source files (.c) and after preprocessing the assembly source files (.asm), and retains the resulting .src files. With the -c option the control program stops after the assembler, with as output one or more object files (.obj). With the -cl option the control program stops after the link stage, with as output a linker object file (.out).

-f file Read command line arguments from file. The filename "-" may be used to denote standard input. To get around the limits on the size of the command line, it is possible to use command files. These command files contain the options that could not be part of the real command line. Command files can also be generated on the fly, for example by the make utility.

1. It is possible to have multiple arguments on the same line in the command file.

2. To include whitespace in the argument, surround the argument with either single or double quotes.

3. If single or double quotes are to be used inside a quoted argument, we have to go by the following rules:

a. If the embedded quotes are only single or double quotes, use the opposite quote around the argument. Thus, if a argument should contain a double quote, surround the argument with single quotes.

b. If both types of quotes are used, we have to split the argument in such a way that each embedded quote is surrounded by the opposite type of quote.

Example:

or

or

4. Some operating systems impose limits on the length of lines within a text file. To circumvent this limitation it is possible to use continuation lines. These lines end with a backslash and newline. In a quoted argument, continuation lines will be appended without stripping any whitespace on the next line. For non-quoted arguments, all whitespace on the next line will be stripped.

Example:

5. It is possible to nest command line files up to 25 levels.

-fptrap Use floating point library with trap handling (libfptt.a, libfpst.a, libfpmt.a or libfplt.a). Without this option a floating point library is selected which uses no trapping.

-g[f|l|n]... Enable symbolic debug information (unless -gn used). With -gn you disable all debug, including type checking. With -gl you disable lifetime information for all types. If you use -gf, high level language type information is also emitted for types which are not referenced by variables. Therefore, this sub-option is not recommended.

-ieee
-ihex
-srec

-tiof With these options you can specify the locator output format of the absolute file. The output file can be an IEEE-695 file (.abs), Intel Hex file (.hex), Motorola S-record file (.sre) or TIOF-695 file (.abs). The default output is IEEE-695 (.abs).

-nolib With this option the control program does not supply the standard libraries to the linker. Normally the control program supplies the default C and run time libraries to the linker. Which libraries are needed is derived from the compiler options.

-o file Normally, this option is passed to the locator to specify the output file name. When you use the -cl option to suppress the locating phase, the -o option is passed to the linker. When you use the -c option to suppress the linking phase, the -o option is passed to the assembler, provided that only one source file is specified. When you use the -cs option to suppress the assembly phase, the -o option is passed to the compiler. The argument may be either directly appended to the option, or follow the option as a separate argument of the control program.

-tmp With this option the control program creates intermediate files in the current directory. They are not removed automatically. Normally, the control program generates temporary files for intermediate translation results, such as compiler generated assembly files, object files and the linker output file. If the next phase in the translation process completes successfully, these intermediate files will be removed.

-v When you use the -v option, the invocations of the individual programs are displayed on standard output, preceded by a '+' character.

-v0 This option has the same effect as the -v option, with the exception that only the invocations are displayed, but the programs are not started.

-wc++ Enable C and assembler warnings for C++ files. The assembler and C compiler may generate warnings on C output of the C++ compiler. By default these warnings are suppressed.

Environment Variables used by ccxa

The control program uses the following environment variables:

TMPDIR This variable may be used to specify a directory, which the control program should use to create temporary files. When this environment variable is not set, temporary files are created in the directory "/tmp" on UNIX systems, and in the current directory on other operating systems.

CCXAOPT This environment variable may be used to pass extra options and/or arguments to each invocation of the control program ccxa. The control program processes the arguments from this variable before the command line arguments.

CCXABIN When this variable is set, the control program prepends the directory specified by this variable to the names of the tools invoked.

11.4 mkxa

Name

mkxa maintain, update, and reconstruct groups of programs

Syntax

mkxa [option]... [target]... [macro=value]...
mkxa -V
mkxa
-? ( UNIX C-shell: "-?" or -\? )

Description

mkxa takes a file of dependencies (a 'makefile') and decides what commands have to be executed to bring the files up-to-date. These commands are either executed directly from mkxa or written to the standard output without executing them.

If no target is specified on the command line, mkxa uses the first target defined in the first makefile.

Long filenames are supported when they are surrounded by double quotes ("). It is also allowed to use spaces in directory names and file names.

Options

-? Show invocation syntax.

-D Display the text of the makefiles as read in.

-DD Display the text of the makefiles and 'mkxa.mk'.

-G dirname
Change to the directory specified with dirname before reading a makefile. This makes it possible to build an application in another directory than the current working directory.

-K Do not remove temporary files.

-S Undo the effect of the -k option. Stop processing when a non-zero exit status is returned by a command.

-V Display version information at stderr.

-W target Execute as if this target has a modification time of "right now". This is the "What If" option.

-d Display the reasons why mkxa chooses to rebuild a target. All dependencies which are newer are displayed.

-dd Display the dependency checks in more detail. Dependencies which are older are displayed as well as newer.

-e Let environment variables override macro definitions from makefiles. Normally, makefile macros override environment variables. Command line macro definitions always override both environment variables and makefile macros definitions.

-f file Use the specified file instead of 'makefile'. A - as the makefile argument denotes the standard input.

-i Ignore error codes returned by commands. This is equivalent to the special target .IGNORE:.

-k When a nonzero error status is returned by a command, abandon work on the current target, but continue with other branches that do not depend on this target.

-m file Read command line information from file. If file is a '-', the information is read from standard input.

-n Perform a dry run. Print commands, but do not execute them. Even lines beginning with an @ are printed. However, if a command line is an invocation of mkxa, that line is always executed.

-q Question mode. mkxa returns a zero or non-zero status code, depending on whether or not the target file is up to date.

-r Do not read in the default file 'mkxa.mk'.

-s Silent mode. Do not print command lines before executing them. This is equivalent to the special target .SILENT:.

-t Touch the target files, bringing them up to date, rather than performing the rules to reconstruct them.

-w Redirect warnings and errors to standard output. Without, mkxa and the commands it executes use standard error for this purpose.

macro=value
Macro definition. This definition remains fixed for the mkxa invocation. It overrides any regular definitions for the specified macro within the makefiles and from the environment. It is inherited by subordinate mkxa's but act as an environment variable for these. That is, depending on the -e setting, it may be overridden by a makefile definition.

Usage

Makefiles

The first makefile read is 'mkxa.mk', which is looked for at the following places (in this order):

- in the current working directory

- in the directory pointed to by the HOME environment variable

- in the etc directory relative to the directory where mkxa is located

Example (PC):

Example (UNIX):

It typically contains predefined macros and implicit rules.

The default name of the makefile is 'makefile' in the current directory. If this file is not found on a UNIX system, the file 'Makefile' is then used as the default. Alternate makefiles can be specified using one or more -f options on the command line. Multiple -f options act as if all the makefiles were concatenated in a left-to-right order.

The makefile(s) may contain a mixture of comment lines, macro definitions, include lines, and target lines. Lines may be continued across input lines by escaping the NEWLINE with a backslash (\). If a line must end with a backslash then an empty macro should be appended. Anything after a "#" is considered to be a comment, and is stripped from the line, including spaces immediately before the "#". If the "#" is inside a quoted string, it is not treated as a comment. Completely blank lines are ignored.

An include line is used to include the text of another makefile. It consists of the word "include" left justified, followed by spaces, and followed by the name of the file that is to be included at this line. Macros in the name of the included file are expanded before the file is included. Include files may be nested.

An export line is used for exporting a macro definition to the environment of any command executed by mkxa. Such a line starts with the word "export", followed by one or more spaces and the name of the macro to be exported. Macros are exported at the moment an export line is read. This implies that references to forward macro definitions are equivalent to undefined macros.

Conditional Processing

Lines containing ifdef, ifndef, else or endif are used for conditional processing of the makefile. They are used in the following way:

The if-lines and else-lines may contain any number of lines or text of any kind, even other ifdef, ifndef, else and endif lines, or no lines at all. The else line may be omitted, along with the else-lines following it.

First the macroname after the if command is checked for definition. If the macro is defined then the if-lines are interpreted and the else-lines are discarded (if present). Otherwise the if-lines are discarded; and if there is an else line, the else-lines are interpreted; but if there is no else line, then no lines are interpreted.

When using the ifndef line instead of ifdef, the macro is tested for not being defined. These conditional lines can be nested up to 6 levels deep.

Macros

Macros have the form `WORD = text and more text'. The WORD need not be uppercase, but this is an accepted standard. Spaces around the equal sign are not significant. Later lines which contain $(WORD) or ${WORD} will have this replaced by `text and more text'. If the macro name is a single character, the parentheses are optional. Note that the expansion is done recursively, so the body of a macro may contain other macro invocations. The right side of a macro definition is expanded when the macro is actually used, not at the point of definition.

Example:

`$(FOOD)' becomes `meat and/or vegetables and water' and the environment variable FOOD is set accordingly by the export line. However, when a macro definition contains a direct reference to the macro being defined then those instances are expanded at the point of definition. This is the only case when the right side of a macro definition is (partially) expanded. For example, the line

after the export line affects `$(FOOD)' just as the line

would do. However, the environment variable FOOD will only be updated when it is exported again.

You are advised not to use the double quotes (") for long filename support in macros, otherwise this might result in a concatination of two macros with double quotes (") in between.

Special Macros

MAKE This normally has the value mkxa. Any line which invokes MAKE temporarily overrides the -n option, just for the duration of the one line. This allows nested invocations of MAKE to be tested with the -n option.

MAKEFLAGS
This macro has the set of options provided to mkxa as its value. If this is set as an environment variable, the set of options is processed before any command line options. This macro may be explicitly passed to nested mkxa's, but it is also available to these invocations as an environment variable. The -f and -d flags are not recorded in this macro.

PRODDIR This macro expands the name of the directory where mkxa is installed without the last path component. The resulting directory name will be the root directory of the installed XA package, unless mkxa is installed somewhere else. This macro can be used to refer to files belonging to the product, for example a library source file.

Example:

When mkxa is installed in the directory /cxa/bin this line expands to:

SHELLCMD
This contains the default list of commands which are local to the SHELL. If a rule is an invocation of one of these commands, a SHELL is automatically spawned to handle it.

TMP_CCPROG
This macro contains the name of the control program. If this macro and the TMP_CCOPT macro are set and the command line argument list for the control program exceeds 127 characters then mkxa will create a temporary file filled with the command line arguments. mkxa will call the control program with the temporary file as command input file. This macro is only known by the PC version of mkxa.

TMP_CCOPT
This macro contains the option for the control program which tells the control program to read a file as command arguments. This macro is only known by the PC version of mkxa.

Example:

$ This macro translates to a dollar sign. Thus you can use "$$" in the makefile to represent a single "$".

There are several dynamically maintained macros that are useful as abbreviations within rules. It is best not to define them explicitly.

$* The basename of the current target.

$< The name of the current dependency file.

$@ The name of the current target.

$? The names of dependents which are younger than the target.

$! The names of all dependents.

The $< and $* macros are normally used for implicit rules. They may be unreliable when used within explicit target command lines. All macros may be suffixed with F to specify the Filename components (e.g. ${*F}, ${@F}). Likewise, the macros $*, $< and $@ may be suffixed by D to specify the directory component.

The result of the $* macro is always without double quotes ("), regardless of the original target having double quotes (") around it or not.
The result of using the suffix F (Filename component) or D (Directory component) is also always without double quotes ("), regardless of the original contents having double quotes (") around it or not.

Functions

A function not only expands but also performs a certain operation. Functions syntactically look like macros but have embedded spaces in the macro name, e.g. '$(match arg1 arg2 arg3 )'. All functions are built-in and currently there are five of them: match, separate, protect, exist and nexist.

The match function yields all arguments which match a certain suffix:

will yield

The separate function concatenates its arguments using the first argument as the separator. If the first argument is enclosed in double quotes then '\n' is interpreted as a newline character, '\t' is interpreted as a tab, '\ooo' is interpreted as an octal value (where, ooo is one to three octal digits), and spaces are taken literally. For example:

will result in

Function arguments may be macros or functions themselves. So,

will yield all object files the current target depends on, separated by a newline string.

The protect function adds one level of quoting. This function has one argument which can contain white space. If the argument contains any white space, single quotes, double quotes, or backslashes, it is enclosed in double quotes. In addition, any double quote or backslash is escaped with a backslash.

Example:

will yield

The exist function expands to its second argument if the first argument is an existing file or directory.

Example:

When the file test.c exists it will yield:

When the file test.c does not exist nothing is expanded.

The nexist function is the opposite of the exist function. It expands to its second argument if the first argument is not an existing file or directory.

Example:

Targets

A target entry in the makefile has the following format:

Any line which does not have leading white space (other than macro definitions) is a 'target' line. Target lines consist of one or more filenames (or macros which expand into same) called targets, followed by a colon (:). The ':' is followed by a list of dependent files. The dependency list may be terminated with a semicolon (;) which may be followed by a rule or shell command.

Special allowance is made on MS-DOS for the colons which are needed to specify files on other drives, so for example, the following will work as intended:

If a target is named in more than one target line, the dependencies are added to form the target's complete dependency list.

The dependents are the ones from which a target is constructed. They in turn may be targets of other dependents. In general, for a particular target file, each of its dependent files is 'made', to make sure that each is up to date with respect to it's dependents.

The modification time of the target is compared to the modification times of each dependent file. If the target is older, one or more of the dependents have changed, so the target must be constructed. Of course, this checking is done recursively, so that all dependents of dependents of dependents of ... are up-to-date.

To reconstruct a target, mkxa expands macros and functions, strips off initial white space, and either executes the rules directly, or passes each to a shell or COMMAND.COM for execution.

For target lines, macros and functions are expanded on input. All other lines have expansion delayed until absolutely required (i.e. macros and functions in rules are dynamic).

Special Targets

.DEFAULT:
The rule for this target is used to process a target when there is no other entry for it, and no implicit rule for building it. mkxa ignores all dependencies for this target.

.DONE: This target and its dependencies are processed after all other targets are built.

.IGNORE: Non-zero error codes returned from commands are ignored. Encountering this in a makefile is the same as specifying -i on the command line.

.INIT: This target and its dependencies are processed before any other targets are processed.

.SILENT: Commands are not echoed before executing them. Encountering this in a makefile is the same as specifying -s on the command line.

.SUFFIXES:
The suffixes list for selecting implicit rules. Specifying this target with dependents adds these to the end of the suffixes list. Specifying it with no dependents clears the list.

.PRECIOUS:
Dependency files mentioned for this target are not removed. Normally, mkxa removes a target file if a command in its construction rule returned an error or when target construction is interrupted.

Rules

A line in a makefile that starts with a TAB or SPACE is a shell line or rule. This line is associated with the most recently preceding dependency line. A sequence of these may be associated with a single dependency line. When a target is out of date with respect to a dependent, the sequence of commands is executed. Shell lines may have any combination of the following characters to the left of the command:

@ will not echo the command line, except if -n is used.

- mkxa will ignore the exit code of the command, i.e. the ERRORLEVEL of MS-DOS. Without this, mkxa terminates when a non-zero exit code is returned.

+ mkxa will use a shell or COMMAND.COM to execute the command.

If the '+' is not attached to a shell line, but the command is a DOS command or if redirection is used (<, |, >), the shell line is passed to COMMAND.COM anyway. For UNIX, redirection, backquote (`) parentheses and variables force the use of a shell.

You can force mkxa to execute multiple command lines in one shell environment. This is accomplished with the token combination ';\'.

Example:

The ';' must always directly be followed by the '\' token. Whitespace is not removed when it is at the end of the previous command line or when it is in front of the next command line. The use of the ';' as an operator for a command (like a semicolon ';' separated list with each item on one line) and the '\' as a layout tool is not supported, unless they are separated with whitespace.

mkxa can generate inline temporary files. If a line contains '<<WORD' then all subsequent lines up to a line starting with WORD, are placed in a temporary file. Next, '<<WORD' is replaced with the name of the temporary file.

No whitespace is allowed between '<<' and 'WORD'.

Example:

The three lines between the tags (EOF) are written to a temporary file (e.g. "\tmp\mk2"), and the command line is rewritten as "lkxa -o $@ -f \tmp\mk2".

Implicit Rules

Implicit rules are intimately tied to the .SUFFIXES: special target. Each entry in the .SUFFIXES: list defines an extension to a filename which may be used to build another file. The implicit rules then define how to actually build one file from another. These files are related, in that they must share a common basename, but have different extensions.

If a file that is being made does not have an explicit target line, an implicit rule is looked for. Each entry in the .SUFFIXES: list is combined with the extension of the target, to get the name of an implicit target. If this target exists, it gives the rules used to transform a file with the dependent extension to the target file. Any dependents of the implicit target are ignored.

If a file that is being made has an explicit target, but no rules, a similar search is made for implicit rules. Each entry in the .SUFFIXES: list is combined with the extension of the target, to get the name of an implicit target. If such a target exists, then the list of dependents is searched for a file with the correct extension, and the implicit rules are invoked to create the target.

Examples

This makefile says that prog.out depends on two files prog.obj and sub.obj, and that they in turn depend on their corresponding source files (prog.c and sub.c) along with the common file inc.h.

LIB  =  -ls

prog.out: prog.obj sub.obj
     lkxa prog.obj sub.obj $(LIB) -o prog.out

prog.obj: prog.c inc.h
     cxa  prog.c
     asxa prog.src

sub.obj:  sub.c inc.h
     cxa  sub.c
     asxa sub.src

The following makefile uses implicit rules (from mkxa.mk) to perform the same job.

LDFLAGS  =  -ls
prog.out  prog.obj sub.obj
prog.obj: prog.c inc.h
sub.obj:  sub.c inc.h

Files

makefile Description of dependencies and rules.
Makefile Alternative to makefile, for UNIX.
mkxa.mk Default dependencies and rules.

Diagnostics

mkxa returns an exit status of 1 when it halts as a result of an error. Otherwise it returns an exit status of 0.

11.5 mppxa

11.5.1 Introduction

It is recommended that you use the internal preprocessor of the assembler asxa. Preprocessor mppxa is supplied for those who need a Intel MPL compatible preprocessor syntax.

The macro preprocessor, mppxa, is a string manipulation tool which allows you to write repeatedly used sections of code once and then insert that code at several places in your program. mppxa also handles conditional assembly, assembly-time loops, console I/O and recursion.

The macro preprocessor is implemented as a separate program which saves both time and space in an assembler, particularly for those programs that do not use macros and thus need not run the macro preprocessor. mppxa is compatible with Intel's syntax and semantics for the 8051 macro processing language (MPL). A user of macros must submit his source input to the macro preprocessor. The macro preprocessor produces one output file which can then be used as an input file to the XA Cross-assembler.

The macro preprocessor regards its input file as a stream of characters, not as a sequence of statements like the assembler does. The macro preprocessor scans the input (source) file looking for macro calls. A macro-call is a request to the macro preprocessor to replace the call pattern of a built-in or user-defined macro with its return value.

As soon as a macro call is encountered, the macro preprocessor expands the call to its return value. The return value of a macro is the text that replaces the macro call. This value is then placed in a temporary file, and the macro preprocessor continues. The return value of some macros is the null string, i.e., a character string containing no characters. So, when these macros are called, the call is replaced by the null string on the output file, and the assembler will never see any evidence of its presence. This is of course particularly useful for conditional assembly.

This chapter documents mppxa in several parts. First the invocation of mppxa is described. The following sections describe how to define and use your own macros, describe the syntax of the macro processing language and describe the macro preprocessor's built-in functions. This chapter also contains a section that is devoted to the advanced concepts of mppxa.

The first five sections give enough information to begin using the macro preprocessor. However, sometimes a more exact understanding of mppxa's operation is needed. The advanced concepts section should fill those needs.

At macro time, symbols, labels, predefined assembler symbols, EQU, and SET symbols, and the location counter are not known. The macro preprocessor does not recognize the assembly language. Similarly, at assembly time, no information about macro symbols is known.

11.5.2 mppxa Invocation

The command line invocation line of mppxa is:

The input-file is an assembly source-file containing user-defined macros. You must give a complete filename (no default file extension is taken).

The output file is an assembly source file in which all user-defined macros are replaced. This file is the input file for asxa. It has the default file extension of .src.

Invocation with -V only displays a version header.

Option Description
-? Display invocation syntax
-Dmacro=def Define preprocessor macro
-Idirectory Look in directory for include files
-V Display version header only
-o filename Specify name of output file

Table 11-1: mppxa options

11.5.3 Detailed Description of Macro Preprocessor Options

-?

Option:

-?

Description:

Display an explanation of options at stdout.

Example:

mppxa  -?

-D

Option:

-Dmacro=def

Arguments:

The macro you want to define and optionally its definition.

Description:

Define macro as in 'define' Any number of symbols can be defined.

Example:

mppxa -DPI=3.1416 test.asm

-I

Option:

-Idirectory

Arguments:

The name of the directory to search for include file(s).

Description:

Change the algorithm for searching $INCLUDE files whose names do not have an absolute pathname to look in directory. Thus, $INCLUDE files are searched for first in the directory of the file containing the $INCLUDE line, then in directories named in -I options in left-to-right order.

Example:

mppxa -I/proj/include test.asm

-o

Option:

-o filename

Arguments:

An output filename.

Default:

Basename of assembly source file with .src suffix.

Description:

Use filename as output filename of the macro preprocessor instead of the basename of the assembly source file with the .src extension.

Example:

To create the assembly file myfile.src instead of test.src, enter:

-V

Option:

-V

Description:

With this option you can display the version header of the macro preprocessor. This option must be the only argument of mppxa. Other options are ignored. mppxa exits after displaying the version header.

Example:

mppxa -V
XA macro preprocessor va.b rc SN00000000-015 (c) year TASKING, Inc.

11.5.4 INCLUDE Files

If the macro preprocessor encounters a $INCLUDE statement in the input file, preprocessing will continue by scanning the specified file until an end-of-file or another INCLUDE is encountered.

Syntax:

$INCLUDE(file)

Abbreviation:

$IC(file)

Expansion:

$<spaces><eol># 1 "file"

Description:

The '$' must be in column 1 for the macro preprocessor to recognize it for processing at macro time. In the output file the INCLUDE(file) part of the INCLUDE call is replaced by spaces (because the assembler also recognizes the '$' character but does not recognize INCLUDE as a control). Also a line containing # 1 "file" is put in the output file.

As soon as the macro preprocessor encounters an end-of-file in the include file, input is resumed where it left off, namely at the next line after the latest INCLUDE call (which due to nesting does not necessarily mean returning to the original input file). Nesting of include files is allowed up to 32 files.

If the macro preprocessor after recognizing the '$' character does not find an INCLUDE before it encounters an end-of-line, due to misspelling or simple because the '$' is followed by a control only recognized by the assembler, no macro-time error is reported and scanned characters are simply passed to the output file.

Restriction:

Each control line (i.e. a line starting with '$') may not contain more than one INCLUDE call.

Example:

; source lines
.
$include( mysrc.inc )     ; include the contents of
                          ; file mysrc.inc
.
; other source lines
.

11.5.5 Creating and Calling Macros

Macro calls differ between user-defined macros and so-called built-in functions. All characters in bold typeface in the syntax descriptions of the following sections are constituents of the macro syntax. Italic tokens represent place holders for user-specific declarations.

The macro preprocessor scans through the input source, one character at a time, looking for a special character called the METACHARACTER, the percent sign '%' initially. This metacharacter must precede a macro-call. Until the macro preprocessor finds a metacharacter, it does not process text. It simply passes the text from the input file to the output file.

Since mppxa only processes macro calls, it is necessary to call a macro in order to create other macros, the so-called "user-defined macros". The built-in function DEFINE creates macros. Built-in functions are a predefined part of the macro language, so they may be called without prior definition. The general syntax for DEFINE is shown below.

Syntax:

DEFINE is the most important mppxa built-in function. This section is devoted to describing this built-in function. Each of the symbols in the syntax above (macro-name, parameter-list, local-list and macro-body) are described in detail on the pages that follow. In some cases, we have abbreviated this general syntax to emphasize certain concepts.

11.5.5.1 Creating Parameterless Macros

When you create a parameterless macro, there are two parts to a DEFINE call: the macro-name and the macro-body. The macro-name defines the name used when the macro is called; the macro-body defines the return value of the call.

Syntax:

The '%' character signals a macro call. The '*' is the optional literal character. When you define a macro using the literal character '*', as shown above, macro calls contained in the body of the macro are not expanded until the macro is called. The exact use of the literal character is discussed in the advanced concept section. When you define a parameterless macro, the macro-name is a macro identifier that follows the '%' character in the source line. The rules for macro identifier are:

- The identifier must begin with an upper or lowercase alphabetic character (A,B,...,Z or a,b,...,z), or a special character ( a question mark '?' or an underscore character '_').

- The remaining characters may be alphabetic, special or decimal digits (0,1,2,...,9).

- Only the first 31 characters of a macro identifier are recognized as the unique identifier name. Upper and lower case characters are not distinguished in a macro identifier.

The macro-body is usually the return value of the macro call. However, the macro-body may contain calls to other macros. If so, the return value is actually the fully expanded macro-body, including the return values of the call to other macros. The macro call is re-expanded each time it is called.

Example 1:

%*DEFINE (String_1)   (An)

%*DEFINE (String_2)   (ele)

%*DEFINE (String_3)
     (phant)

%*DEFINE (String_4)   (shopping)

%DEFINE (String_5)    (goes
%String_4)

%DEFINE (Part_1)
     (%String_1 %String_2%String_3)

The macro-body must consist of a balanced-text string, i.e. you must have balanced parentheses within the macro-body. In other words, each left parenthesis must have a succeeding right parenthesis, and each right parenthesis must have a preceding left parenthesis.

The possible placement of the macro-body and the parenthesis are both represented in the above examples. The beginning of the macro-body is determined by the syntactical end of the left parenthesis, where tabs (08H), blanks and the first new line (0AH) are also part of the macro-body.

The macro-body of String_1 starts with the 'A' of "An"
The macro-body of String_3 starts with the 'p' of "phant"
The macro-body of String_4 starts with the '(08H)' of "(08H)shopping".

The end of macro-body is determined by the right parenthesis.

The macro-body of String_4 is "(08H)shopping"
The macro-body of String_5 is "goes (0AH)
(08H)shopping"

The expanded value of DEFINE is the null string, but the macro body is stored internally for later use. User-defined macros may invoke themselves within their bodies. This property is called 'recursion'. Any macro which calls itself must terminate eventually or the macro preprocessor may enter an infinite loop.

Once a macro has been created, it may be redefined by a second call to DEFINE.

To call a macro, you use the '%' character followed by the name of the macro (the literal character '*' is only admissible for defined macros whose call is passed to a macro as a an actual parameter; example: %M1(%*M2)). The macro preprocessor removes the call and inserts the return value of the call. If the macro-body contains any call to other macros, they are replaced with their return values.

Example 2:

%Part_1 %String_5     --> An elephant goes
                          shopping

Once a macro has been created, it may be redefined by a second call to DEFINE. Note, however that a macro should not redefine itself within its body (see Advanced mppxa Concepts).

The examples below show several macro definitions. Their return values are also shown.

Example 3:

Macro definition at the top of the program:

%*DEFINE (MOVE)
( MOV R3H,  [R1]
  MOV [R2], R3H
)

The macro call as it appears in the program:

     MOV R1, #1
----%MOVE

The program as it appears after the macro preprocessor made the following expansion, where the first expanded line is preceded by the four blanks preceding the call (the sign - indicates the preceding blanks):

     MOV R1, #1
----     MOV R3H, [R1]
     MOV [R2], R3H

Example 4:

Macro definition at the top of the program:

%*DEFINE (ADD5)
(    MOV R0, #5
     MOV R5, [R2]
     ADD R5, R0
)

The macro call as it appears in the original program body:

     MOV R5, #2
%ADD5

The program after the macro expansion:

     MOV R5, #2
     MOV R0, #5
     MOV R5, [R2]
     ADD R5, R0

Example 5:

Macro definition at the top of the program:

%*DEFINE (MOVE_AND_ADD) (
     %MOVE
     %ADD5
)

The macro call as it appears in the body of the program:

     MOV R1, #1
%MOVE_AND_ADD

The program after the macro expansion:

     MOV R1, #1

     MOV R3H, [R1]
     MOV [R2], R3H

     MOV R0, #5
     MOV R5, [R2]
     ADD R5, R0

11.5.5.2 Creating Macros with Parameters

If the only function of the macro preprocessor was to perform simple string replacement, then it would not be very useful for most of the programming tasks. Each time we wanted to change even the simplest part of the macro's return value we would have to redefine the macro.

Parameters in macro calls allow more general-purpose macros. Parameters leave holes in a macro-body that are filled in when you call the macro. This permits you to design a single macro that produces code for typical programming operations. The term 'parameters' refers to both the formal parameters that are specified when the macro is defined (the holes, and the actual parameters or arguments that are specified when the macro is called (the fill-ins).

The syntax for defining macros with parameters is very similar to the syntax for macros without parameters.

Syntax:

The macro-name must be a valid identifier.

The parameter-list is a list of macro identifiers separated by macro delimiters. These identifiers comprise the formal parameters used in the macro. The macro identifier for each parameter in the list must be unique, but they may be the same as other formal argument names to other macros since they have no existence outside the macro definition. They may also be the same as the names of other user macros or of macro functions. Note, however that in this case the macro or function cannot be used within the macro-body, since its name would be recognized as a parameter instead. To reference a formal argument within the macro-body, use its name preceded by the metacharacter.

Typically, the macro delimiters are parentheses and commas. When using these delimiters, you would enclose the parameter-list in parentheses and separate each formal parameter with a comma. When you define a macro using parentheses and commas as delimiters, you must use those same delimiters, when you call that macro.

The example below shows the definition of a macro with three parameters: SOURCE, DEST and COUNT. The macro produces code to copy any number of words from one part of memory to another.

Example:

%*DEFINE (MOVE_ADD_GEN(SOURCE,DEST,COUNT))
(    MOV  R1, #%SOURCE
     MOV  R0, #%DEST
     MOV  R6, #%COUNT
     MOV  R3H, [R1]
     MOV [R0], R3H
     ADDS R1, #1
     ADDS R0, #1
     DJNZ R6, ($-4)
)

To call a macro with parameters, you must use the metacharacter followed by the macro's name as with parameterless macros. However, a list of the actual parameters must follow. These actual parameters have to be enclosed within parentheses and separated from each other by commas. The actual parameters may optionally contain calls to other macros.

A simple call to a macro defined above might be:

%MOVE_ADD_GEN( 10, 24, 8 )

The above macro call produces the following code:

     MOV  R1, #10
     MOV  R0, #24
     MOV  R6, #8
     MOV  R3H, [R1]
     MOV  [R0], R3H
     ADDS R1, #1
     ADDS R0, #1
     DJNZ R6, ($-4)

11.5.5.3 Local Symbols in Macros

If we used a fixed label instead of the offset ($-4) in the previous example, the macro using the fixed label can only be called once, since a second call to the macro causes a conflict in the label definitions at assembly time. The label can be made a parameter and a different symbol name can be specified each time the macro is called.

A preferable way to ensure a unique label for each macro call is to put the label in a local-list. The local-list construct allows you to use macro identifiers to specify assembly-time symbols. Each use of a LOCAL symbol in a macro guarantees that the symbol will be replaced by a unique assembly-time symbol each time the symbol is called.

The macro preprocessor increments a counter once for each symbol used in the list every time your program calls a macro that uses the LOCAL construct. Symbols in the local-list, when used in the macro-body, receive a two to five digit suffix that is the hexadecimal value of the counter. The first time you call a macro that uses the LOCAL construct, the suffix is '00'.

The syntax for the LOCAL construct in the DEFINE function is shown below. (This is the complete syntax for the built-in function DEFINE):

Syntax:

The local-list is a list of valid macro identifiers separated by spaces. Since these macro identifiers are not parameters, the LOCAL construct in a macro has no effect on a macro call.

To reference local symbols in the macro-body, they must be preceded by the metacharacter. The symbol LOCAL is not reserved; a user symbol or macro may have this name.

The next example shows a macro definition that uses a LOCAL list.

Example:

%*DEFINE (MOVE_ADD_GEN(SOURCE,DEST,COUNT)) LOCAL LAB
(    MOV  R1, #%SOURCE
     MOV  R0, #%DEST
     MOV  R6, #%COUNT
%LAB:
     MOV  R3H, [R1]
     MOV  [R0], R3H
     ADDS R1, #1
     ADDS R0, #1
     DJNZ R6, %LAB
)

A simple call to a macro defined above might be:

%MOVE_ADD_GEN( 50, 100, 24 )

The above macro call might produce the following code (if this is he eleventh call to a macro using a LOCAL list):

     MOV  R1, #50
     MOV  R0, #100
     MOV  R6, #24
LAB0A:
     MOV  R3H, [R1]
     MOV  [R0], R3H
     ADDS R1, #1
     ADDS R0, #1
     DJNZ R6, LAB0A

Since macro identifiers follow the same rules as asxa, any macro identifier can be used in a local-list. However, if long identifier names are used, they should be restricted to 29 characters. Otherwise, the label suffix may cause the identifier to exceed 31 characters and these would be truncated.

The assembler supports numeric labels. The numbers 1 through 255 can be used as labels. They must be followed by a colon, when defined. To reference such a numeric label, you must put an n (next) or p (previous) immediately after the label. This is required because the same label number may be used repeatedly. Thus it is possible to use numeric labels in macros. The following example shows the use of a previous referenced numeric label (label followed by the character 'p') as a substitute for the LOCAL list example.

Example:

%*DEFINE (MOVE_ADD_GEN(SOURCE,DEST,COUNT))
(    MOV  R1, #%SOURCE
     MOV  R0, #%DEST
     MOV  R6, #%COUNT
1:
     MOV  R3H, [R1]
     MOV  [R0], R3H
     ADDS R1, #1
     ADDS R0, #1
     DJNZ R6, 1p
)

After the following calls,

%MOVE_ADD_GEN( 50, 100, 24 )
%MOVE_ADD_GEN( 60, 200, 48 )

the preprocessor produces the following code:

     MOV  R1, #50
     MOV  R0, #100
     MOV  R6, #24
1:
     MOV  R3H, [R1]
     MOV  [R0], R3H
     ADDS R1, #1
     ADDS R0, #1
     DJNZ R6, 1p
     MOV  R1, #60
     MOV  R0, #200
     MOV  R6, #48
1:
     MOV  R3H, [R1]
     MOV  [R0], R3H
     ADDS R1, #1
     ADDS R0, #1
     DJNZ R6, 1p

The assembler accepts the duplicate numerical labels and translates them to the corresponding address offsets in a segment.

11.5.6 The Macro Preprocessor's Built-In Functions

The macro preprocessor has several built-in or predefined macro functions. These built-in functions perform many useful operations that are difficult or impossible to produce in a user-defined macro.

We have already discussed one of these built-in functions, DEFINE. DEFINE creates user-defined macros. DEFINE does this by adding an entry in the macro preprocessor's tables of macro definitions. Each entry in the tables includes the macro-name of the macro, its parameter-list, its local-list and its macro-body. Entries for the built-in functions are present when the macro preprocessor begins operation.

Other built-in functions perform numerical and logical expression evaluation, affect control flow of the macro preprocessor, manipulate character strings, and perform console I/O.

The following sections deal with the following:

Comment, escape , bracket ('...', '..., n..., (...) )METACHAR

Metachar function ( METACHAR)

Expressions processed by mppxa

Calculating functions ( SET , EVAL )

Controlling functions ( IF , WHILE , REPEAT , EXIT )

String-processing functions ( LEN , SUBSTR , MATCH )

String-comparing functions (EQS, NES, LTS, LES, GTS, GES)

Input/Output functions ( IN, OUT)

11.5.6.1 Comment, Escape and Bracket Functions

11.5.6.1.1 Comment Function

The macro processing language can be very subtle, and the operation of macros written in a straightforward manner may not be immediately obvious. Therefore, it is often necessary to comment macro definitions.

Syntax:

or

The comment function always evaluates to the null string. Two terminating characters are recognized: the apostrophe ' and the end-of-line (line-feed character, ASCII 0AH). The second form of the call allows macro definitions to be spread over several lines, while avoiding any unwanted end-of-lines in the return value. In either form of the comment function, the text or comment is not evaluated for macro calls.

Example:

%*DEFINE (MOVE_ADD_GEN(SOURCE,DEST,COUNT)) LOCAL LAB
(    MOV  R1, #%SOURCE %'This is the source address'
     MOV  R0, #%DEST %'This is the destination'
     MOV  R6, #%COUNT %'%COUNT must be a constant'
%LAB:     %'This is a local label.
%'End of line is inside the comment!
     MOV  R3H, [R1]
     MOV  [R0], R3H
     ADDS R1, #1
     ADDS R0, #1
     DJNZ R6, %LAB
)

Call the above macro:

%MOVE_ADD_GEN( 50, 100, 24 )

Return value from above call:

     MOV  R1, #50
     MOV  R0, #100
     MOV  R6, #24
LAB0A:
     MOV  R3H, [R1]
     MOV  [R0], R3H
     ADDS R1, #1
     ADDS R0, #1
     DJNZ R6, LAB0A

Note that the comments that were terminated with the end-of-line removed the end-of-line character along with the rest of the comment.

The metacharacter is not recognized as flagging a call to the macro preprocessor when it appears in the comment function.

11.5.6.1.2 Escape Function

Sometimes it is necessary to prevent the macro preprocessor from processing text. The escape function and the bracket function perform such tasks.

Syntax:

The escape function prevents the macro preprocessor from processing a text string of n characters long, where n is a decimal digit from 0 to 9. The escape function is useful for inserting a metacharacter as text, adding a comma as part of an argument, or placing a single parenthesis in a character string that requires balanced parentheses.

Example:

Before Macro Expansion    After Macro Expansion

;Average of 20%1%           ->;Average of 20%

%DTCALL(JAN 21%1, 1992,     -> JAN 21, 1992 
       JUN 12%1, 1992)      -> JUN 12, 1992

%MYCALL(1%1) Option 1,      -> 1) Option 1
       2%1) Option 2,       -> 2) Option 2
       3%1) Option 2)       -> 3) Option 3

The first example add a literal '%' in the text. The second example keeps the date as one actual parameter adding a literal ','. The third example adds a literal right parenthesis ')' to each parameter.

11.5.6.1.3 Bracket Function

The bracket function is the other built-in function that inhibits the macro preprocessor from expanding text.

Syntax:

The bracket function inhibits all macro preprocessor expansion of the text contained within the parentheses. However, the escape function, the comment function, and the parameter substitution are still recognized. Since there is no restriction for the length of the text within the bracket function, it is usually easier to use than the escape function.

The literal character '*' is not accepted in connection with the three functions described in this subsection.

Example:

%*DEFINE (DW(LIST,NAME))
( %NAME  DW  %LIST)

The macro DW expands DW statements, where the variable NAME represents the first parameter and the expression LIST represents the second parameter.

The following expansion should be obtained by the call:

If the call in the following form:

occurs, the macro preprocessor would interpret the first argument (198H) as NAME and everything after the first comma as the second parameter, since the first comma would be interpreted as the delimiter separating the macro parameters.

In order to change this method of interpretation, all tokens that are to be combined for an individual parameter must be identified as a parameter string and set in a bracket function:

This way the bracket function prevents the string '198H, 3DH, 0F0H' from being evaluated as separate parameters.

11.5.6.2 METACHAR Function

The METACHAR function can be used to redefine the metacharacter (initially: '%')

Syntax:

Although the balanced-text string may be any number of characters long, only the first character in the string is taken to be the new metacharacter. Macro calls in the balanced-text string are still recognized and corresponding actions that will not lead to any direct expansion on the output file will be performed. So, for example a SET macro call inside the balanced-text string will be performed.

Characters that may not be used as a metacharacter are: a blank, letter, digit, left or right parenthesis, or asterisk.

The following example is catastrophic !!!

This examples defines the space character as the new metacharacter, since it is the first character in the balanced-text strings!

11.5.6.3 Numbers and Expressions in mppxa

Many built-in functions recognize and evaluate numerical expressions in their arguments. mppxa uses the same rules for representing numbers as asxa (see chapter Operands and Expressions for detailed information):

- Numbers may be represented in the formats binary (B suffix), octal (O or Q suffix), decimal (D or no suffix), and hexadecimal (H suffix).

- Internal representation of numbers is 16-bits (00H to 0FFFFH); the processor does not recognize or output real or long integer numbers.

- The following operators are recognized by the macro preprocessor (in descending precedence):

The symbolic forms of the relational operators (i.e., <, >, =, <>, >=, <=) are not recognized by the macro preprocessor.

The macro preprocessor cannot access the assembler's symbol table. The values of labels, location counter, EQU and SET symbols are not known during macro time expression evaluation. Any attempt to use assembly time symbols in a macro time expression generates an error. Macro time symbols can be defined, however, with the predefined macro, SET.

11.5.6.4 SET Function

SET assigns the value of the numeric expression to the identifier, macro-variable, and stores the macro-variable in the macro time symbol table, macro-variable must follow the same syntax convention used for other macro identifiers. Expansion of a macro-variable always results in hexadecimal format.

Syntax:

The SET macro call affects the macro time symbol table only; when SET is encountered, the macro preprocessor replaces it with the null string. Symbols defined by SET can be redefined by a second SET call, or defined as a macro by a DEFINE call The SET function is thanks to the necessary compatibility with Intel the only predefined macro function which may be redefined. Such a redefinition of the SET function must however be strongly dissuaded, because as a consequence, the original functionality will be lost for the rest of the program, i.e., macro-time symbols can no longer be defined.

Example:

%SET(COUNT,0)                    -> null string
%SET(OFFSET,16)                  -> null string
MOV R1, #%COUNT + %OFFSET        -> MOV R1,#0H + 10H
MOV R2, #%COUNT                  -> MOV R2,#0H

SET can also be used to redefine symbols in the macro time table:

%SET(COUNT,%COUNT + %OFFSET)     -> null string
%SET(OFFSET,%OFFSET * 2)         -> null string
MOV R1, #%COUNT + %OFFSET        -> MOV R1,#10H + 20H
MOV R2, #%COUNT                  -> MOV R2,#10H

11.5.6.5 EVAL Function

The built-in function EVAL accepts an expression as its argument and returns the expression's value in hexadecimal.

Syntax:

The expression argument must be a legal macro-time expression. The return value from EVAL is built according to asxa's rules for representing hexadecimal numbers. The trailing character is always the hexadecimal suffix (H). The expanded value is at most 16 bits and negative numbers are shown in two's complement form. If the leading digit of the return-value is 'A', 'B', 'C', 'D', 'E' or 'F', it is preceded by a 0.

Example:

COUNT SET %EVAL(33H + 15H + 0f00H)     -> COUNT SET 0f48H

MOV  R1, #%EVAL(10H - ((13+6) *2 ) +7) -> MOV  R1, #0fff1H

%SET( NUM1, 44)                        -> null string
%SET( NUM2, 25)                        -> null string

MOV   R1, #%EVAL( %NUM1 LE %NUM2 )     -> MOV  R1, #00H

11.5.6.6 Logical Expressions and String Comparisons in mppxa

Several built-in functions return a logical value when they are called. Like relational operators that compare numbers and return TRUE or FALSE ('0fffH' or '00H') respectively, these built-in functions compare character strings. If the function evaluates to 'TRUE', then it returns the character string '0ffffH'. If the function evaluates to 'FALSE', then it returns '00H'.

The built-in functions that return a logical value compare two balanced-text arguments and return a logical value based on that comparison. The list of string comparison functions below shows the syntax and describes the type of comparison made for each. Both arguments may contain macro calls.

%EQS(arg1,arg2 ) TRUE if both arguments are identical; equal

%NES(arg1,arg2 ) TRUE if arguments are different in any way; not equal

%LTS(arg1 ,arg2) TRUE if first argument has a lower value than second argument; less than

%LES(arg1,arg2 ) TRUE if first argument has a lower value than second argument or if both arguments are identical; less than or equal

%GTS(arg1,arg2 ) TRUE if first argument has a higher value than second argument; greater than

%GES(arg1,arg2 ) TRUE if first argument has a higher value than second argument, or if both arguments are identical; greater than or equal

Before these functions perform a comparison, both strings are completely expanded. Then the ASCII value of the first character in the first string is compared to the ASCII value of the first character in the second string. If they differ, then the string with the higher ASCII value is to be considered to be greater. If the first characters are the same, the process continues with the second character in each string, and so on. Only two string s of equal length that contain the same characters in the same order are equal.

Example:

Before Macro Expansion After Macro Expansion

%EQS(ABC,ABC) 0ffffH (TRUE).
The character strings are identical.

%EQS(ABC, ABC) 00H (FALSE).
The space after the comma is part of
the second argument

%LTS(CBA,cba) 0ffffH (TRUE).
The lower case characters have a
higher ASCII value than upper case.

%GES(ABC,ABC) 00H (FALSE).
The space at the end of the second
string makes the second string greater
than the first one.

%GTS(16,111H) 0ffffH (TRUE).
ASCII '6' is greater than ASCII '1'.

The strings to the string comparison macros have to follow the rules of the balanced-text described earlier.

11.5.6.7 Control Flow Functions and Conditional Assembly

Some built-in functions expect logical expressions in their arguments. Logical expressions follow the same rules as numeric expressions. The difference is in how the macro interprets the 16-bit value that the expression represents. Once the expression has been evaluated to a 16-bit value, mppxa uses only the low-order bit to determine whether the expression is TRUE or FALSE. If the low-order bit is one, the expression is TRUE. If the low-order bit is zero the expression is FALSE.

Typically, the relational operators (EQ, NE, LE, LT, GE, or GT) or the string comparison functions (EQS, NES, LES LTS, GES, or GTS) are used to specify a logical value. Since these operators and functions always evaluate to 0FFFFH or 00H, internal determination is not necessary.

11.5.6.7.1 IF Function

The IF built-in function evaluates a logical expression, and based on that expression, expands or withholds its text arguments.

The IF function allows a user to decide at macro time whether to assemble certain code or not (conditional assembly). So, the assembler never has to see any code which is not to be assembled.

Syntax:

The IF function first evaluates the expression. If it is TRUE, then the succeeding balanced-text1 is expanded; if it is FALSE and the optional ELSE clause is included in the call, then the balanced-text2 is expanded. If the expression results to FALSE and the ELSE clause is not included, the IF call returns the null string. The macro call must be terminated by FI.

IF calls can be nested. The ELSE clause refers to the most recent IF call that is still open (not terminated by FI). FI terminates the most recent IF call that is still open. The level of macro nesting is limited to 300.

Example:

This is a simple example of the IF call with no ELSE clause:

%SET( VALUE, 0F0H )
%IF( %VALUE GE 0FFH )
THEN
     (MOV  R1, #%VALUE)
FI

Example:

This is a simple form of the IF call with an ELSE clause:

%IF( %EQS(ADD,%OPERATION))
THEN
     (ADD  R6, #03H)
ELSE
     (SUB  R6, #03H)
FI

Example:

This is an example of three nested IF calls:

%IF( %EQS(%OPER,ADD)) THEN (
     ADD  R1, #03H
)ELSE (%IF( %EQS(%OPER,SUB)) THEN (
          SUB  R1, #03H
     )ELSE (%IF( %EQS(%OPER,MUL)) THEN (
               MOV  R1, #03
               JMP  MUL_LAB
          )ELSE (
               MOV  R1, #DATUM
               JMP  DIV_LAB
          )FI
     )FI
)FI

Example:

Demonstrating conditional assembly:

%SET(DEBUG,1)
%IF(%DEBUG)
THEN (
     MOV  R1, #%DEBUG
     JMP  DEBUG
)FI

     MOV  R1, R2
      .
      .
      .

This expands to:

     MOV  R1, #%DEBUG
     JMP  DEBUG
     MOV  R1, R2

%SET can be changed to:

     %SET(DEBUG,0)

to turn off the debug code.

11.5.6.7.2 WHILE Function

The IF macro is useful for implementing one kind of conditional assembly including or excluding lines of code in the source file. However, in many cases this is not enough. Often you may wish to perform macro operations until a certain condition is met. The built-in function WHILE provides this facility.

Syntax:

The WHILE function evaluates the expression. If it results to TRUE, the balanced-text is expanded WHILE expands to the null string. Once the balanced-text has been expanded, the logical argument is retested and if it is still TRUE, the balanced-text is expanded again. This continues until the logical argument proves FALSE.

Since the macro continues processing until the expression is FALSE, the balanced-text should modify the expression, or else WHILE may never terminate.

A call to built-in function EXIT always terminates a WHILE macro. EXIT is described below.

The following example shows the common use of the WHILE macro:

Example:

%SET(COUNTER,7)

%WHILE( %COUNTER GT 0 )
(    MOV  R2, #%COUNTER
     MOV  [R1], R2
     ADD  R1, #2
     %SET(COUNTER, %COUNTER - 1)
)

This example uses the SET macro and a macro-time symbol to count the iterations of the WHILE macro.

11.5.6.7.3 REPEAT Function

mppxa offers another built-in function that performs the counting loop automatically. The built-in function REPEAT expands its balanced-text a specified number of times.

Syntax:

Unlike the IF and WHILE macros, REPEAT uses the expression for a numerical value that specifies the number of times the balanced-text should be expanded. The expression is evaluated once when the macro is first called, then the specified number of iterations is performed.

A call to built-in function EXIT always terminates a REPEAT macro. EXIT is described in the next section.

Example:

Lab:
     MOV R3H, #8
     MOV R2, #0FFFFH

     %REPEAT( 8 )
     (  MOV [R2], R3H
        ADD [R1], R3H
     )

11.5.6.7.4 EXIT Function

The built-in function EXIT terminates expansion of the most recently called user defined macro. It is most commonly used to avoid infinite loops (e.g. a recursive user defined macro that never terminates). It allows several exit points in the same macro.

Syntax:

Example:

This use of EXIT terminates a recursive macro when an odd number of bytes have been added.

%*DEFINE (MEM_ADD_MEM(SOURCE,DEST,BYTES))
(     %IF( %BYTES LE 0 )THEN ( %EXIT ) FI
      ADD         R3H, %SOURCE
      ADDC R3H, %DEST
      MOV         %DEST, R3H
      %IF( %BYTES EQ 1 ) THEN ( %EXIT ) FI
      MOV         R3H, %SOURCE+1
      ADDC R3H, %DEST+1
      MOV         %DEST+1, R3H
      IF (%BYTES GT 2) THEN (
            %MEM_ADD_MEM(%SOURCE+2,%DEST+2,%BYTES-2)) FI
)

The above example adds two pairs of bytes and stores results in DEST. As long as there is a pair of bytes to be added, the macro MEM_ADD_MEM is expanded. When BYTES reaches a value of 1 or 0, the macro is exited.

Example:

This EXIT is a simple jump out of a recursive loop:

%*DEFINE (BODY)
(     MOV R3H,%MVAR
      %SET(MVAR, %MVAR + 1 )
)

%*DEFINE (UNTIL(CONDITION,EXE_BODY))
(     %EXE_BODY
      %IF( %CONDITION )
      THEN (
         %EXIT )
      ELSE (
         %UNTIL( %CONDITION, %EXE_BODY )
      )FI
)

%SET(MVAR,0)
%UNTIL( %MVAR GT 3, %*BODY )

11.5.6.8 String Manipulation Functions

The macro language contains three functions that perform common string manipulation functions, namely, the LEN, SUBSTR and MATCH function.

11.5.6.8.1 LEN Function

The built-in function LEN takes a character string argument and returns the length of the character string in hexadecimal format (the same format as EVAL).

Syntax:

Before Macro Expansion        After Macro Expansion

%LEN(ABNCDEFGHIJKLMOPQRSTUVWXYZ)     -> 1bH
%LEN(A,B,C)                          -> 05H
%LEN()                               -> 00H

%MATCH(STR1,STR2) (Cheese,Mouse)
%LEN(%STR1)                          -> 06H
%LEN(%SUBSTR(%STR2, 1, 3 ))          -> 03H

11.5.6.8.2 SUBSTR Function

The built-in function SUBSTR returns a substring of its text argument. The macro takes three arguments: a string from which the substring is to be extracted and two numeric arguments.

Syntax:

balanced-text as described earlier. It may contain a macro call.

expression1 specifies the starting character of the substring.

expression2 specifies the number of characters to be included in the substring.

If expression1 is zero or greater than the length of the argument string, SUBSTR returns the null string.

If expression2 is zero, then SUBSTR returns the null string. If it is greater than the remaining length of the string, then all characters from the start character of the substring to the end of the string are included.

Example:

The examples below several calls to SUBSTR and the value returned:

Before Macro Expansion      After Macro Expansion

%SUBSTR(ABCDEFG, 5, 1 )            -> E
%SUBSTR(ABCDEFG, 5, 100 )          -> EFG
%SUBSTR(123(56)890, 4, 4 )         -> (56)
%SUBSTR(ABCDEFG, 8, 1 )            -> null
%SUBSTR(ABCDEFG, 3, 0 )            -> null

11.5.6.8.3 MATCH Function

The MATCH function primarily serves to define macro identifiers. The MATCH function searches a character string for a delimiter character and assigns the substrings on either side of the delimiter to the macro identifiers.

Syntax:

balanced-text as described earlier. It may contain a macro call.

macro-id1 and macro-id2 may be any valid mppxa identifier.

delimiter is the first character to follow macro-id1. You can use a space or a comma or any other delimiter. See the Advanced mppxa Concepts section for more information on delimiters.

MATCH searches the balanced-text for the first delimiter. When it is found, all characters to the left of it are assigned to macro-id1 and all characters to the right are assigned to macro-id2. If the delimiter is not found, the entire balanced-text is assigned to macro-id1 and the null string is assigned to macro-id2.

Example:

%MATCH(MS1,MS2) (ABC,DEF)        -> MS1=ABC  MS2=DEF
%MATCH(MS3,MS4) (GH,%MS1)        -> MS3=GH   MS4=ABC
%MATCH(MS5,MS6) (%LEN(%MS1))     -> MS5=03H  MS6=null

You can use the MATCH function for processing string lists as shown in the next example.

Example:

%MATCH(NEXT,LIST)(10H,20H,30H)
%WHILE(%LEN(%NEXT))
(    MOV  R3H, %NEXT
     ADD  R3H, #2
     MOV  %NEXT, R3H
     %MATCH(NEXT,LIST)(%LIST)
)

Produces the following code:

First iteration of WHILE:

     MOV  R3H, 10H
     ADD  R3H, #2
     MOV  10H, R3H

Second iteration of WHILE:

     MOV  R3H, 20H
     ADD  R3H, #2
     MOV  20H, R3H

Third iteration of WHILE:

     MOV  R3H, 30H
     ADD  R3H, #2
     MOV  30H, R3H

11.5.6.9 Console I/nctions

Two built-in functions, IN and OUT, perform console l/O. They are line-oriented. IN outputs the character '>' as a prompt to the console, and returns the next line typed at the console including the line terminator. OUT outputs a string to the console; the return value of OUT is the null string.

The results of an IN call (of the input) is interpreted as a macro-string. IN can also be used everywhere, where a macro-string is allowed.

Syntax:

Example:

%OUT(ENTER NUMBER OF PROCESSORS IN SYSTEM)
%SET(PROC_COUNT,%IN)
%OUT(ENTER THIS PROCESSOR'S ADDRESS)
ADDRESS SET %IN
%OUT(ENTER BAUD RATE)
%SET(BAUD,%IN)

The following lines would be displayed on the console:

ENTER NUMBER OF PROCESSORS IN SYSTEM
> user response
ENTER THIS PROCESSOR'S ADDRESS
> user response
ENTER BAUD RATE
> user response

11.5.7 Advanced mppxa Concepts

For most programming problems, mppxa as described above, is sufficient. However, in some cases, a more complete description of the macro preprocessor's function is necessary. It is impossible to describe all of the obscurities of the macro preprocessor in a single chapter. Specific questions to mppxa can easily be answered by simple tests following the given rules.

11.5.7.1 Macro Delimiters

Delimiters are used in the function DEFINE to separate the macro-name from the optional parameter-list and to separate different parameters in this parameter-list. In the MATCH function a delimiter is used to define a separator, which is used as kind of terminator in the corresponding balanced-text argument. The most commonly used delimiters are characters like parentheses and commas, but the macro language permits almost any character or group of characters to be used as a delimiter.

Regardless of the type of delimiter used to define a macro, once it has been defined, only the delimiters used in the definition can be used in the macro call. Macros defined with parentheses and commas require parentheses and commas in the macro call. Macros defined with spaces (or any other delimiter), require that delimiter when called.

Macro delimiters can be divided into three classes: implied blank delimiters, identifier delimiters, and literal delimiters.

11.5.7.1.1 Implied Blank Delimiters

Implied blank delimiters are the easist to use and contribute the most readability and flexibility to macro definitions. An implied blank delimiter is one or more spaces, tabs or new lines (a carriage-return/linefeed pair) in any order. To define a macro that uses the implied blank delimiter, simply place one or more spaces, tabs, or new lines surrounding the parameter list and separating the formal parameters.

When you call the macro defined with the implied blank delimiter, each delimiter will match a series of spaces, tabs, or new lines. Each parameter in the call begins with the first non-blank character, and ends when a blank character is found.

Example:

%*DEFINE(WORDS FIRST SECOND)(TEXT: %FIRST %SECOND)

All of the following calls are valid:

Before Macro Expansion      After Macro Expansion

%WORDS hello world          -> TEXT: hello world
%WORDS one
       two                  -> TEXT: one two
%WORDS
     well
done                        -> TEXT: well done

11.5.7.1.2 Identifier Delimiters

Identifier delimiters are legal macro identifiers designated as delimiters. To define a macro that uses an identifier delimiter in its call pattern, you must prefix the delimiter with the commercial at symbol '@'. You must separate the identifier delimiter from the macro identifiers by a blank character.

When calling a macro defined with identifier delimiters, an implied blank delimiter is required to precede the identifier delimiter, but none is required to follow the identifier delimiter.

Example:

%*DEFINE(ADD M1 @TO M2 @AND M3)(
     MOV R3H,%M1
     ADD R3H,%M2
     MOV %M2,R3H
     MOV R3H,%M1
     ADD R3H,%M3
     MOV %M3,R3H
)

The following call (there is no blank after TO and AND):

%ADD ATOM TOBILL ANDLIST

returns the following code after expansion:

     MOV R3H,ATOM
     ADD R3H,BILL
     MOV BILL,R3H
     MOV R3H,ATOM
     ADD R3H,LIST
     MOV LIST,R3H

11.5.7.1.3 Literal Delimiters

The delimiters we used with the user-defined macros (parentheses and commas) were literal delimiters. A literal delimiter can be any character except the metacharacter.

When you define a macro using a literal delimiter, you must use exactly that delimiter when you call the macro.

When defining a macro, you must literalize the delimiter string, if the delimiter you wish to use meets any of the following conditions:

You can use the escape function (%n) or the bracket function (%()) to literalize the delimiter string.

Example:

Before Macro Expansion        After Macro Expansion

%*DEFINE(MAC(A,B))(%A  %B)          -> null string
%MAC(2,3)                           -> 2  3

In the following example brackets are used instead of parentheses. The commercial at symbol separates the parameters:

%*DEFINE(OR[A%(@)B])(OR %A,%B)      -> null string
%OR[A1@A2]                          -> OR A1,A2

In the next example, delimiters that could be identifier delimiters have been defined as litteral delimiters:

%*DEFINE(ADD(A%(AND)B))(AND %A,%B)     -> null string
%ADD (R3H AND #34H)                    -> AND R3H , #27H

The spaces around AND are considered as part of the argument string.

Next folllows an example to demonstrate the difference between identifier delimiters and literal delimiters.

Example:

%*DEFINE(ADD M1%(TO)M2%(AND)M3)(
     MOV R3H,%M1
     ADD R3H,%M2
     MOV %M2,R3H
     MOV R3H,%M1
     ADD R3H,%M3
     MOV %M3,R3H
)

The following call:

%ADD ATOM TOBILL ANDLIST

returns the following code after expansion (the TO in ATOM is recognized as the delimiter):

     MOV R3H,R3H
     ADD R3H,M TOBILL
     MOV M TOBILL,R3H
     MOV R3H,R3H
     ADD R3H,LIST
     MOV LIST,R3H

11.5.7.2 Literal vs. Normal Mode

In normal mode, the macro preprocessor scans text looking for the metacharacter. When it finds one, it begins expanding the macro call. Parameters and macro calls are expanded. This is the usual operation of the macro preprocessor, but sometimes it is necessary to modify this mode of operation. The most common use of the literal mode is to prevent macro expansion. The literal character in DEFINE prevents the expansion of macros in the macro-body until you call the macro.

When you place the literal character in a DEFINE call, the macro preprocessor shifts to literal mode while expanding the call. The effect is similar to surrounding the entire call with the bracket function. Parameters to the literalized call are expanded, the escape, comment, and bracket functions are also expanded, but no further processing is performed. If there are any calls to other, they are not expanded.

If there are no parameters in the macro being defined, the DEFINE built-in function can be called without the literal character. If the macro uses parameters, the macro will attempt to evaluate the formal parameters in the macro-body as parameterless macro calls.

Example:

The following example illustrates the difference between defining a macro in literal mode and normal mode:

%SET(TOM,1)

%*DEFINE (M1)(
     %EVAL(%TOM)
)

%DEFINE (M2)(
     %EVAL(%TOM)
)

When M1 and M2 are defined, TOM is equal to 1. The macro-body of M1 has not been evaluated due to the literal character, but the macro-body of M2 has been completely evaluated, since the literal character is not used in the definition. Changing the value of TOM has no affect on M2, it changes the return value of M1 as illustrated below:

Before Macro Expansion    After Macro Expansion

%SET(TOM,2)
%M1                          -> 02H
%M2                          -> 01H

The macros themselvescan be called with the literal character. The return value then is the unexpanded body:

%*M2                         -> 01H
%*M1                         -> %EVAL(%TOM)

Sometimes it is necessary to obtain access to parameters by several macro levels. The literal mode is also used for this purpose. The following example assumes that the macro M1 called in the macro-body is predefined.

Example:

@*DEFINE (M2(P1))(
     MOV  R3H,%P1
     %M1(%P1)
)

In the above example, the formal parameter %P1 is used once as a simple place holder and once as an actual parameter for the macro M1.

Actual parameters in the contents must not be known in literal mode, since they are not expanded. If the definition of M2, however, occurred in normal mode, the macro preprocessor would try to expand the call from M1 and, therefore, the formal parameter %P1 (used as an actual parameter). However, this first receives its value when called from M2. If its contents happen to be undefined, an error message is issued.

Another application possibility for the literal mode exists for macro calls that are used as actual parameters (macro-strings, macro-variables, macro-calls).

Example:

The formal parameter of M1 was assigned the call from M2 ('%M2') by its expansion. M2 is expanded from M1 when the formal parameters are processed.

In normal mode, M2 is expanded in its actual parameter list immediately when called from M1. The formal parameters of M1 in its body are replaced by the prior expanded macro-body from M2.

The following example shows the different use of macros as actual parameters in the literal and normal mode.

Example:

%SET(M2,1)

%*DEFINE (M1(P1))(
     %SET(M2,%M2 + 1)
     %M2, %P1
)

%M1(%*M2)                    -> 02H, 02H
%M1(%M2)                     -> 03H, 02H
%M1(%*M2)                    -> 04H, 04H

11.5.7.3 Algorithm for Evaluating Macro Calls

The algorithm of the macro preprocessor used for evaluating the source file can be broken down into 6 steps:

1) Scan the input stream until the metacharacter is found.

2) Isolate the macro-name.

3) If macro has parameters, expand each parameter from left to right (initiate step one on actual parameter), before expanding the next parameter.

4) Substitute actual parameters for formal parameters in macro-body.

5) If the literal character is not used, initiate step one on macro-body.

6) Insert the result into output stream.

The terms 'input stream' and 'output stream' are used because the return value of one macro may be a parameter to another. On the first iteration, the input stream is the source line. On the final iteration, the output stream is passed to the assembler.

Example:

The examples below illustrate the macro preprocessor's evaluation algorithm:

%SET(TOM,3)

%*DEFINE (STEVE)(%SET(TOM,%TOM - 1) %TOM)

%DEFINE (ADAM(A,B))(
     DB  %A, %B, %A, %B, %A, %B
)

The call ADAM is presented here in the normal mode with TOM as the first actual parameter and STEVE as the second actual parameter. The first parameter is completely expanded before the second parameter is expanded. After the call to ADAM has been completely expanded, TOM will have the value 02H.

Before Macro Expansion      After Macro Expansion

%ADAM(%TOM,%STEVE)   -> DB 03H, 02H, 03H, 02H, 03H, 02H

Now reverse the order of the two actual parameters. In this call to ADAM, STEVE is expanded first (and TOM is decremented) before the second parameter is evaluated. Both parameters have the same value.

%SET(TOM,3)
%ADAM(%STEVE,%TOM)   -> DB 02H, 02H, 02H, 02H, 02H, 02H

Now we will literalize the call to STEVE when it appears as the first actual parameter. This prevents STEVE from being expanded until it is inserted in the macro-body, then it is expanded for each replacement of the formal parameters. TOM is evaluated before the substitution in the macro-body.

%SET(TOM,3)
%ADAM(%*STEVE,%TOM)  -> DB 02H, 03H, 01H, 03H, 00H, 03H

11.6 prxa

Name

prxa IEEE object reader
Displays the contents of a relocatable object file or an absolute file

Synopsis

prxa [option]... file
prxa -V
prxa
-? ( UNIX  C-shell: " -?" or -\? )

Description

prxa gives you a high level view of an object file which has been created by a tool from the TASKING XA tool chain. Note that prxa can be used as a disassembler with the -il4 option.

Options

Options start with a '-' sign and can be combined after a single '-'. There are options to print a specific part of an object file. For example, with option -h you can display the header part, the environment part and the AD/extension part as a whole. These parts are small, and you cannot display these parts separately. If you do not specify a part, the default is -hscegd0i0 (all parts, the debug part and the image part displayed as a table of contents).

Furthermore, there are some additional options by which you can control the output.

Input Control Option

-ffile Read command line information from file. If file is a '-', the information is read from standard input.

1. It is possible to have multiple arguments on the same line in the command file.

2. To include whitespace in the argument, surround the argument with either single or double quotes.

3. If single or double quotes are to be used inside a quoted argument, we have to go by the following rules:

a. If the embedded quotes are only single or double quotes, use the opposite quote around the argument. Thus, if a argument should contain a double quote, surround the argument with single quotes.

b. If both types of quotes are used, we have to split the argument in such a way that each embedded quote is surrounded by the opposite type of quote.

Example:

or

or

4. Some operating systems impose limits on the length of lines within a text file. To circumvent this limitation it is possible to use continuation lines. These lines end with a backslash and newline. In a quoted argument, continuation lines will be appended without stripping any whitespace on the next line. For non-quoted arguments, all whitespace on the next line will be stripped.

Example:

5. It is possible to nest command line files up to 25 levels.

Output Control Options

-H or -? Display an explanation of options at stdout.

-V Display version information at stderr.

-Wn Set output width to n columns. Default 128, minimum 78.

-ln Level control, see paragraph 11.6.3.

-ofile Name of the output file, default stdout.

-v Print the selected parts in a verbose form.

-vn Print level n verbose, see paragraph 11.6.3.

-wn Suppress messages above warning level n.

Display Options

-c Print call graphs.

-d Print all debug info except for the global types.

-d0 Print table of contents for the debug part.

-dn Print debug info from file number n.

-e Print variables with external scope.

-e1 Print variables with external scope and precede symbol name with name of the object file.

-g Print global types.

-h Print general file info.

-i Print all section images.

-i0 Print table of contents for the image part.

-in Print image of section n.

-s Print section info.

11.6.1 Preparing the Demo Files

There are three files which are used in this chapter to show how you can use prxa. These files are:

If you want to try the examples yourself, prepare these files by copying the calc example files to a working directory. Be sure that the XA tools can be found via a search path. Make the files with the following command:

11.6.2 Displaying Parts of an Object File

11.6.2.1 Option -h, display general file info

The -h option gives you general information of the file. The invocation:

Gives the following information:

This output speaks for itself. You may combine the -h switch with the verbose option:

The output is extended with more general information of less importance:

The table gives you the file offsets and the length of the main object parts.

11.6.2.2 Option -s, display section info

With the -s option, you can obtain the section information from an object module. The section contents can be obtained with the -i option, see 11.6.2.7.

Note that the section information is not available any more in a located file. Once located, the separate sections are combined to new clusters. For an absolute file 'prxa -s' will give the cluster information:

The locate map shows you which section is located in which cluster. Of course, you can also use the verbose option to see all section information available:

Section Size Address Algn PageSize Mau Attributes
-----------------------------------------------------------------------------
CALC_PR 0x00003e - 0x002 - - Execute Space 10 Cumulate
CALC_INI_NE 0x000001 - 0x001 - - Write Space 8 Initialized Cumulate
CALC_CLR_NE 0x000002 - 0x002 - - Write Space 8 Cleared Cumulate
START_PR 0x000020 - 0x002 - - Execute Space 10 Cumulate
RESET_VECTOR 0x000004 - 0x001 - - Execute Space 10 Cumulate
INIT_PR 0x0000c4 - 0x002 - - Execute Space 10 Cumulate

The first two columns give you the section name and the section size. The column 'Address' gives you the section address, or a '-' if the section is still relocatable. The section alignment is 1 (byte) or 2 (word) for the XA. The page size is valid only for the short sections. Mau is the minimum addressable unit of an address space (in bits). There are two main groups of section attributes, the allocation attributes, used by the locator and the overlap attributes, used by the linker:

Allocation attributes
Write Must be located in ram
ReadOnly May be located in rom
Execute May be located in rom
Space num Must be located in addressing mode num
Abs Already located by the assembler
Cleared Section must be initialized to '0'
Initialized Section must be copied from ram to rom
Scratch Section is not filled or cleared

Table 11-2: Allocation attributes

Overlap attributes
MaxSize Use largest length encountered
Unique Only one section with this name allowed
Cumulate Concatenate sections with the same name to one bigger section
Overlay Sections with the name name@func must be combined to one section name, according to the rules for func obtained from the call graph.
Separate Sections are not linked.

Table 11-3: Overlap attributes

11.6.2.3 Option -c, display call graphs

The call graph is used by the linker overlaying algorithm. Once a file is linked and overlaying is done, the call graph information is removed from the object file. If you try to see the call graph in calc.out you will get the message 'No call graph found'.

The file calc.obj is not yet linked. You can use this file to see what a call graph looks like:

Each call graph consists of a function (factorial in graph 0), followed by a list of functions and/or other graphs, which are called by the first function. The functions and call graphs called by this function are indented by two spaces. If a function calls other functions, those functions are listed again with another indentation of two spaces.

As you can see, there are references from one call graph to another. Call graph 0 even calls itself!! This means that function factorial() is a recursive function.

If a function is a static function the source name is added to the function name to avoid name conflicts.

If you want a call graph with resolved call graph references, you can use the linker to generate one:

Option -M tells the linker to generate a .lnl file. This file contains the call graph in the verbose layout. Option -c causes the linker to generate a .cal file. This file contains also the (same) call graph, but in the compact (non verbose) layout. Option -r tells the linker that this is an incremental link.

11.6.2.4 Option -e, display external part

In the external part of an object file, you can find all symbols used at link time. These symbols have an external scope. With the -e option (or -e0) prxa displays the external symbols:

With option -e1 also the name of the output object file is displayed.

The first column contains the name of the symbol. In general, this symbol is a high level symbol with an underscore added at the front. The next column gives you the symbol status. This can be I for a defined symbol, and X for a symbol which is referred to, but which is not yet defined. In the last column you can find the symbols address. If this address is still relocatable, the section offsets are printed in the form 'section + offset'. If a symbol has already received an absolute address, this address is printed. Symbols that are not yet defined (marked with a X) have a dash printed as address, indicating unknown.

You can add the verbose option as usual. With verbose on more information is printed:

Variable S Type Attrib MAU Amod Address/Size
--------------------------------------------------------------
entry    I  -    -     8   10   CALC_PR + 0x00
num      I  -    -     8   8    CALC_INI_NE + 0x00
result   I  -    -     8   8    CALC_CLR_NE + 0x00
__START  I  -    -     8   10   START_PR + 0x00
initseg  I  -    -     8   10   INIT_PR + 0x00
__lc_es  X  -    -     8   7    -
__lc_cp  X  -    -     8   10   -

Four additional columns appear. The Type column gives you the symbol type, if available. You can find the meaning of the types in the global type part, section 11.6.2.5. The global types are used to type check the symbols during linking. The Attribute column specifies the attribute of the symbol, if available. For example, the attribute value 0x0020 indicates that the symbol is generated by the assembler. The MAU colomn indicates the minimum addressable unit in bits. So, MAU 8 means the symbol is 8-bit addressable. The Amod column lists the addressing mode of the symbol.

11.6.2.5 Option -g, display global type information

The linker uses the global type information to check on type mismatches of the symbols in the external part. This information is always available, unless you explicitly suppress the generation of these types with option -gn at compile time. Of course, type checking can only be done if the types are available. The global types in calc.out:

In this example you will get the message 'No global types available'. The following is just an example of what the global type information could look like:

In the first column you find the type index. This is the number by which the type is referred to. This number is always a hexadecimal number. Numbering starts at 0x101, because the indices less than 0x100 are reserved for, so-called, 'basic types'. The second column contains the type mnemonic. This mnemonic defines the new 'high level' type. In the Name column you will find the name for the type, if any.

The last column contains type parameters. They tell you which (basic) types a high level type is based on and give other parameters such as modes and sizes. Types are preceded by a T. So, in the example above, type 105 is based upon type 2 (T2 in the parameter list) and type 103 is based upon type 1 and type 104.

In the next table you can find an overview of the basic types:

Type index Type Meaning
1 void -
2 char 8 bits signed
3 unsigned char 8 bits unsigned
4 short 16 bits signed
5 unsigned short 16 bits unsigned
6 long 32 bits signed
7 unsigned long 32 bits unsigned
10 float 32 bit floating point
11 double 64 bit floating point
16 int 16 bits signed
17 unsigned int 16 bits unsigned

Table 11-4: Basic types

The type mnemonics define the class of the newly created type. The next table shows the type mnemonics with a short description:

Mnemonic Description Parameters
G generalized structure size, [member, Tindex, offset, size ]...
N enumerated type [name, value ]...
n pointer qualifier Tindex, memspace
O small pointer Tindex
P large pointer Tindex
Q type qualifier q-bits, Tindex
S structure size, [member, Tindex, offset ]...
T typedef Tindex
t compiler generated type Tindex
U union size, [member, Tindex, offset ]...
X function x-bits, Tindex, 0, nbr-arg, [ Tindex ]...
Z array Tindex, upper-bound
g bit type sign, nbr-of-bits

Table 11-5: Type mnemonics

The Tindex for mnemonic n, O, P, Q, T, t and Z are the types upon which the new type is built. The Tindex for the union and the structures are the type indices for the members. For the function type, the first Tindex is the return type of the function. The second Tindex is repeated for each parameter, and gives the type of each parameter. The value -1 (0xffffffff) always means 'unknown'. This can occur with a function type if the number of parameters is unknown, or with an array if the upper bound in unknown. The sizes and offset for the generalized structure are in bits. The first size is the size of the structure, the second size is the size for the member.

The type information obtained with the -g switch has no verbose equivalent.

11.6.2.6 Option -d, display debug information

The -d switch has two variants. With -d0 you get a table of contents:

Now, you can use -dn to examine a single (linked) file. For instance, -d1 shows you only the debug info of calc.obj. It is also possible to see all debug info, by using option -d without a value.

The -d switch without the verbose option -v shows you only local variables and procedure information. If you combine the -d switch with the verbose switch -v, also local type info, line numbers, stack update information and more procedure information is displayed.

In the example you are using the verbose switch. Where required, the remark 'Only with verbose on' will be given.

The object reader starts with a header, followed by the local type information:

This type info is only printed if you use the verbose option -v. The information found in this table is exactly the same as the information explained for the global type information, see 11.6.2.5.

After the local types, you will find the local symbols.

The value for the symbol status in the external part was an I or an X. Here, you can see a new letter. The N stands for a local symbol. Other possible entires can have the letter G or S. They are no symbols, but procedures. These procedures are printed at this place in order to define their relative position. The actual procedure information is given in the next block of information. Here you can find the additional procedure information. The procedure block is printed only if you use the verbose switch:

The following is an example of some procedures:

Name           S  Additional information
-----------------------------------------
main           G  0x00, 0x00, T101, QUEENS_PR + 0x00, 
                  ( QUEENS_PR + 0x49 ) - 0x01
find_legal_row S  0x00, 0x00, T120, QUEENS_PR + 0x49, 
                  ( QUEENS_PR + 0x156 ) - 0x01
display_board  S  0x00, 0x00, T10a, QUEENS_PR + 0x156, 
                  ( QUEENS_PR + 0x2a4 ) - 0x01
display_field  S  0x00, 0x00, T121, QUEENS_PR + 0x2a4, 
                  ( QUEENS_PR + 0x302 ) - 0x01
display_status S  0x00, 0x00, T103, QUEENS_PR + 0x302, 
                  ( QUEENS_PR + 0x31d ) - 0x01

The first two columns are the same as those in the local variable table. The G stands for an external (global) function, the S for a static (local) function.

Each function has 5 parameters with the following meaning:

param #1 Frame type, not used

param #2 Frame size, the distance from the stack pointer before the function call to the stack position just after the local variables.

param #3 The type of the function

param #4 The start address of the function. In a relocatable object the syntax 'section + offset' is used.

param #5 The last function address. See also param #4.

Next in the debug info is the line number information and the stack information. Both items are only printed if you had turned the verbose switch on:

Lines include/stdarg.h:
=======================
No line info available

Lines include/stdio.h:
======================
No line info available

Lines queens.c:
===============

Address | Line Address | Line Address ...
--------------------------- --------------------------- ---------------
QUEENS_PR + 0x000000 | 52 QUEENS_PR + 0x0000c2 | 90 QUEENS_PR + ...
QUEENS_PR + 0x000000 | 53 QUEENS_PR + 0x0000d9 | 101 QUEENS_PR + ...
QUEENS_PR + 0x000006 | 55 QUEENS_PR + 0x0000d9 | 103 QUEENS_PR + ...
. . .
. . .
. . .
QUEENS_PR + 0x0000bd | 98 QUEENS_PR + 0x00018e | 133 QUEENS_PR + ...
QUEENS_PR + 0x0000c0 | 99 QUEENS_PR + 0x000190 | 136 QUEENS_PR + ...
QUEENS_PR + 0x0000c2 | 100 QUEENS_PR + 0x00019f | 137

Stack info include/stdarg.h:
============================
No stack info available

Stack info include/stdio.h:
===========================
No stack info available

Stack info queens.c:
====================
No stack info available

The stack info gives the actual stack position for each executable address. This value is measured from the start position, just after the functions local variables to the actual stack position. If you push one byte on stack, the delta will be increased by one.

The debug info per module ends with a block for each function. Within this block the local variables per function are displayed:

11.6.2.7 Option -i, display the section images

As with the -d option, you can ask a table with available section images by specifying option -i0:

You can select the image to display by specifying the image number:

It is also possible to get the section offsets or absolute addresses by specifying the verbose flag:

Section CALC_PR:
================

000000 86 rr rr c5 03 00 8e rr rr 80 d6 00 72 99 04 00 ............r...
000010 84 02 0f 74 94 02 02 04 f0 08 99 01 00 0d fe 00 ...t............
000020 84 02 07 20 81 30 b1 84 02 07 91 01 02 1f 8a c5 ... .0..........
000030 ed ff 27 8a 20 e4 02 89 70 99 04 00 80 d6 ..'. ...p.....

The dump always shows the hexadecimal byte value per address. Sometimes however, this is not possible. First of all, it is possible that a certain byte cannot be determined because it is not yet relocated. In this case the byte is represented as rr.

Secondly, it is possible that there is no section image allowed. This is for instance the case for sections that are cleared during startup. After the invocation (verbose on) the reader prints:

Section CALC_CLR_NE:
====================

No image allowed, cleared during startup

It is possible that you read an absolute file. In the absolute file it is possible to combine different sections to new clusters. These clusters do not have the same attributes as the sections and the reader does no longer know where the overlay area is positioned:

Section code_clstr:
===================

000000 8f 00 ff 04 ss ss ss ss ss ss ss ss ss ss ss ss ................
000010 ss ss ss ss ss ss ss ss ss ss ss ss ss ss ss ss ................
000020 ss ss ss ss ss ss ss ss ss ss ss ss ss ss ss ss ................
000030 ss ss ss ss ss ss ss ss ss ss ss ss ss ss ss ss ................
....

As you see, the reader only prints bytes that it actually can read from the object file. The ss in the dump means scratch memory. It may or may not be initialized by the start-up code. This information is not available anymore to the reader. The start-up code can use a locator generated table to get the information. See the Locator chapter.

11.6.2.8 Option -il4, produce disassembly

With the option combination -il4, prxa can produce disassembly output. It disassembles all code image parts which are executable.

11.6.3 Viewing an Object at Lower Level

11.6.3.1 Object Layers

As with the well known OSI layer model for communication, you can also distinguish layers in an object file. The object file is a medium for the compiler which lets the compiler communicate with the debugger or the target board. The lowest level can be classified as mass storage, mostly the disc. The lowest viewable level for the readers concern are the raw bytes.

prxa knows this layer as level 0.

Of course, the bytes in level 0 have a meaning. Because the object format is an format according to IEEE 695, the object file is a collection of MUFOM commands. The general idea is, that an object producing tool sends commands to a object consuming tool. These commands are described in detail by the official IEEE standard (IEEE Trial Use Standard for Microprocessor Universal Format for Object Modules (IEEE std. 695), IEEE Technical Committee on Microcomputers and Microprocessors of the IEEE Computer Society, 1990) . The raw bytes from level 0 appear to be encoded MUFOM commands. The MUFOM commands are interpreted in a layer just above the raw bytes layer.

prxa knows this layer as level 1.

The next layer is the MUFOM environment, the type and section tables are built, values are assigned, attributes are set just by performing the MUFOM commands. The IEEE document describes also some predefined meanings about scope, section attributes naming conventions for MUFOM variables. This knowledge is available in the highest MUFOM layer.

prxa knows this layer as level 2.

With these first layers, the compiler and debugger/target board have a perfect communication channel. The next layers (not supported by the reader at this moment) define a protocol between compiler and debugger about target and language specific information.

In the next sections you can find some examples about the use of the reader at lower levels. Until now, you used the default level of the reader, level 2.

11.6.3.2 The Level Option -ln

Level 1

Switching to another level is simple. You can use the -l option with the level you want to see. As an example, the section part of calc.out at level 1:

If you are not familiar with the MUFOM commands, you can use the verbose switch. The abbreviated commands such as AS, SA or ST are expanded to Assignment, Section alignment and Section type:

The Ln and Sn MUFOM variables are defined as the address and the size of section n. At level 2 you saw (refer to section 11.6.2.2) that the level 2 view did not mention the L and S variables, because at level 2 the meaning of the L and S variables are known!

Level 0

Switching to level 0 is accomplished by using -l0 (as you expected):

The bytes are printed in the MUFOM command structure. It should be easy to find the encoding for the used MUFOM commands. You can use the verbose switch if you want to see file offsets:

0000ad  e6 01 d8 d9 0a c3 07 43 41 4c 43 5f 50 52    .......CALC_PR
0000bb  e7 01 02                                     ...
0000be  e2 d3 01 3e                                  ...>
...
000120  e6 06 d8 d9 0a c3 07 49 4e 49 54 5f 50 52    .......INIT_PR
00012e  e7 06 02                                     ...
000131  e2 d3 06 81 c4                               .....

Viewing Mixed Levels

You can also mix the levels. It is for instance possible to see level 0 and 1 together by specifying option -l01 (equivalent to -l10 or -l0 -l1):

And of course, you can turn on the verbose switch. The switch between level 0 and level 1 is done per MUFOM command. This is because a MUFOM command is the smallest unit at level 1.

If you should display level 1 and 2, the switch is made per object part, because the object parts are the smallest units at level 2. It is not possible to show the results of all section related commands before all these commands are executed:

11.6.3.3 The Verbose Option -vn

As you have read in section 11.6.3.2, you can switch to a lower level with the level switch -ln. If you want a verbose printout, you can use the -v option.

It is also possible to specify -v0 to see a verbose output of level 0, option -vn is a shorthand for options -v -ln (or -vln). The new notation has the advantage that if you want a mixed level output, you are able to choose the verbose option per level. You may specify -l0 -v1, and you get a non verbose level 0 and a verbose level 1:

The general verbose switch -v (without a number) makes all selected levels verbose. The verbose switch -vn selects level n and makes only level n verbose.


Copyright © 2000 TASKING, Inc.