A macro file to simplify interfacing assembly language programs
with higher level programs.
This file was tested with the Microsoft MACRO Assembler version 3.00.
All identifiers that are of no interest to a programmer when using
the macro file have the form @[email protected]@: where 'aaa' represents three
letters. No one is likely to redefine these symbols.
A few of the macroes exist for cosmetic purposes only. None of the
@[email protected]@ words appear in a listing when the normal switches are in
effect. Also every identifier generated in the macro file or in the
macro expansions are deleted from the symbol listing with .XCREF,
with the exception of the procedure names.
The file begins with the definitions of TRUE, FALSE and some
frequently used control characters. TRUE = NOT FALSE (-1).
A few structures are defined to give size attributes and high byte
or word offsets to operands. The operand:
is equivalent to
BYTE PTR WOMBAT
is equivalent to
WORD PTR [BX] + 2
The modifiers defined are B, LB, HB, W, LW, HW & D.
Most of the file consists of macro definitions. The assembler manual
states that macro expansionss should not be recursive. However I
have had no problem with this. The depth is limited to five by
limiting the number of parameters to ten. I have even found that
string equates can be redefined (to other strings) without causing
errors. While this permits redefining identifiers for the parameters
of different procedures, I would not reccommend it. This may be
an oversight in the assembler. If so, it might occasionally have
some unpredictable side-effects; furthermore it might have been
corrected in later versions.
When using this file, some attention must be given to whether a
particular parameter has a value to be used or the address of that
value. It is also necessary to know something about how a specific
compiler passes parameters. Regardless of which calling convention
is used, the $PARM macro defines the parameters in the inverse of
the order in which they were pushed.
The $PASCAL macro tells any $PRET macro following it to clean up
the stack. The $C macro tells it not to clean up the stack.
Each remains in effect until the other is invoked. Near the
end of the macro file the statement @[email protected]@ = TRUE sets $PASCAL
as the default.
This macro needs at least two parameters. The first is the
procedure name; the second is NEAR or FAR. $PROC declares the
procedure PUBLIC and depending whether it is NEAR or FAR,
determines where the first parameter (the last one pushed)
is located on the stack. It also executes the PROC directive.
If $PROC has more than two parameters, it executes $PARM with
the remainder of its parameters.
This declares an interrupt procedure. It takes one or two
parameters. The first is the procedure name, which is declared
as a FAR procedure. The second, if used, is an identifier for
the position on the stack where the flags are saved. $PROC may
be used in situations where this is inadequate.
$PARM takes from one to five pairs of parameters. The first of
each pair, becomes an identifier for a position on the stack
representing one of the procedure's parameters. The second of
each pair, is an integer or integer identifier that tells how
many bytes of stack space the parameter occupies. It does NOT
give a size attribute to the procedure's parameter; it determines
where the next parameter will be located on the stack, and adds
to the count of bytes to be popped from the stack, when applicable.
The modifiers mentioned above are convenient for specifying size
attributes. A procedure may have more than one $PARM expansion,
and any parameters after the first two in the $PROC expansion
become $PARM parameters.
The special parameter $LAST is not one of a pair, and is used to
tell $PRET to pop only the parameters preceeding it. In Turbo
Pascal, in some circumstances (differing in the earlier and later
versions) not all parameters will be popped from the stack.
When the $C macro has been used, the number of parameters defined
in $PARM expansions does not have to match the number of parameters
passed to the procedure.
This macro is used to assign identifiers to local variables on the
stack. Like $PARM, it does NOT give size attributes to these
identifiers. Also like $PARM, it takes pairs of parameters; the
first an identifier and the second an integer indicating the number
Since identifiers defined in $PARM and $VAR are [BP] relative,
they can only be indexed by [DI] or [SI] and/or a constant.
REMEMBER TO $SAVE; otherwise procedures do stupid things.
$SAVE should be used whenever $PARM parameters or $VAR variables
need to be accessed in the procedure. It generates the instructions:
MOV BP, SP
and reminds $PRET or $IRET that this has been done. In addition,
if any $VAR variables have been defined, it makes room for them on
Normally $SAVE is used after all $VAR variables have been defined.
However $VAR may be used after $SAVE to reference variables that
will be pushed onto the stack by the procedure. A little caution
is needed if register values from the calling procedure are also
pushed onto the stack. $PRET and $IRET assume that any such values
have already been popped.
$RET executes $PRET if the procedure was defined in $PROC, or
$IRET if it was dfined in $IPROC.
Both $PRET and $IRET clean up the local stack and pop the calling
procedure's BP if $SAVE was executed.
$PRET then generates a return instruction. If the procedure had
$PARM parameters and the $PASCAL convention was in effect, the
return pops the parameters. If $LAST appeared in the $PARM
parameters, only the parameters defined before it are popped.
$IRET then generates the IRET instruction.
If $RET, $PRET or $IRET have a parameter, the $TERM macro is
executed and the parameter passed to it.
The $TERM macro must have a parameter which must be the procedure
name. It generates the ENDP directive then sets up default values
except the $PASCAL/$C value for the next procedure.
This supports a personal preference of restarting a listing
appear on the listing, when the listing control switches are in
their usual modes.