Dec 062017
PIC 16CXX assembler.
File ASPIC.ZIP from The Programmer’s Corner in
Category Assembly Language
PIC 16CXX assembler.
File Name File Size Zip Size Zip Type
AB.EXE 15907 8241 deflated
ASPIC.DOC 142061 36847 deflated
ASPIC.EXE 76482 36525 deflated
CLOPS.ASM 3900 1194 deflated
CSET.ASM 945 444 deflated
DATE.ASM 1990 700 deflated
ECHO.ASM 1215 508 deflated
ENV.ASM 640 267 deflated
ERR.ASM 640 288 deflated
EXPR.ASM 384 182 deflated
LOOP.ASM 2304 734 deflated
MAP.ASM 768 370 deflated
MENU.ASM 3278 1145 deflated
NEWFNS.ASM 251 150 deflated
NEWOPS.ASM 445 207 deflated
PICTEST.EXE 20912 9718 deflated
SEGDEF.ASM 1792 613 deflated
SEGMACS.ASI 8960 2206 deflated
TABLEPIC.H 9334 2203 deflated
TPCREAD.ME 199 165 deflated

Download File ASPIC.ZIP Here

Contents of the ASPIC.DOC file

Macro+ Assembler Version 5 i

MACRO+ Assembler Version 5

For uPD78C10 Series Microcontrolers
Mitsubishi 507xx, 374xx 8 bit Microcontrolers
Mitsubisi 377xx 16 bit Microcontrolers
Microchip PIC 16Cxx, 17cXX Microcontrolers

User's Manual

Revised: May, 1993

This manual and the accompanying software are copyright (C)1988, 1993
Don Lekei, ALL RIGHTS RESERVED. This manual may not be reproduced, in
any manner without prior written permission of Don Lekei. Permission
is granted to the purchaser of this software ONLY, to make a
reasonable number of copies of THE EXECUTABLE PROGRAM ONLY, for the
sole use of the purchaser. This program contains a unique serial
number which will identify the source of any copy of the program.


(C)1993 Don Lekei

ii Macro+ Assembler Version 5

Table of Contents

1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.1 Shareware Licence . . . . . . . . . . . . . . . . . . 1
1.2 Philosophy . . . . . . . . . . . . . . . . . . . . . 2
1.3 Microprocessors supported . . . . . . . . . . . . . . 2
1.4 System requirements . . . . . . . . . . . . . . . . . 3

1.5 Notation used in this manual . . . . . . . . . . . . . . . . 3
1.6 Assembler Operation . . . . . . . . . . . . . . . . . 4
1.7 Error Return . . . . . . . . . . . . . . . . . . . . 4
1.8 Command line parameters . . . . . . . . . . . . . . . 4

2 Source Code Format . . . . . . . . . . . . . . . . . . . . . . 7
2.1 Source line format . . . . . . . . . . . . . . . . . 7
2.1.1 Opcode parsing . . . . . . . . . . . . . . 7
2.2 Labels . . . . . . . . . . . . . . . . . . . . . . . 7
2.3 System defined labels . . . . . . . . . . . . . . . 8
2.4 Expression evaluation . . . . . . . . . . . . . . . . 10
2.4.1 Constants . . . . . . . . . . . . . . . . . 10
2.4.2 Unary operators . . . . . . . . . . . . . . 11
2.4.3 Arithmetic operators . . . . . . . . . . . 11
2.4.4 Boolean operators . . . . . . . . . . . . . 12
2.4.5 Relational and logical operators . . . . . 12
2.4.6 Functions . . . . . . . . . . . . . . . . . 12
2.5 String expressions . . . . . . . . . . . . . . . . . 14
2.5.1 Special environment variables . . . . . . . 14

3 Assembler Directives . . . . . . . . . . . . . . . . . . . . . 15
3.1 Data definition directives . . . . . . . . . . . . . 15
3.2 Special data directives . . . . . . . . . . . . . . . 16
3.3 Translation directives . . . . . . . . . . . . . . . 16
3.4 Translated data directives . . . . . . . . . . . . . 18
3.5 Packed data directives . . . . . . . . . . . . . . . 18
3.5.1 3-to-2 packing . . . . . . . . . . . . . . 19
3.5.2 4-to-3 packing . . . . . . . . . . . . . . 19
3.6 Assignment directives . . . . . . . . . . . . . . . . 20
3.7 Address control directives . . . . . . . . . . . . . 21
3.8 Conditional assembly directives . . . . . . . . . . . 24
3.8.1 IF/THEN/ELSE/ENDIF structure . . . . . . . 24
3.8.2 SWITCH/CASE/ELSE/ENDIF structure . . . . . 25
3.9 Macros and User-Defined Functions . . . . . . . . . . 26
3.9.1 Macro parameters . . . . . . . . . . . . . 26
3.9.2 Regular macros . . . . . . . . . . . . . . 28
3.9.3 Function macros . . . . . . . . . . . . . . 30
3.9.4 DO loops . . . . . . . . . . . . . . . . . 31
3.10 System and file control directives . . . . . . . . . 32
3.11 Listing control directives . . . . . . . . . . . . . 35
3.12 Assembler control directives . . . . . . . . . . . . 37

(C)1993 Don Lekei

Macro+ Assembler Version 5 iii

Appendix A: Errors and Warnings . . . . . . . . . . . . . . . . . 39

Appendix B: Assembler Directives Alphabetically . . . . . . . . . 47

Appendix C: Assembler Directives by Function . . . . . . . . . . 49

Appendix D: Converting From Other Assemblers . . . . . . . . . . 52

Appendix E: CPU Specific Enhancements - PIC . . . . . . . . . . . 55
E.1 Data / Strings . . . . . . . . . . . . . . . . . . . 55
E.2 Enhanced Instruction Set . . . . . . . . . . . . . . 55
E.3 Model Specific Resource Limits . . . . . . . . . . . 55
E.4 Output Files . . . . . . . . . . . . . . . . . . . . 55
E.5 Assembler Test Files . . . . . . . . . . . . . . . . 56

(C)1993 Don Lekei

Introduction 1

1 Overview

Welcome to the Macro+ assembler. The purpose of this manual is to
familiarize you with the features and capabilities of this powerful
development tool, it assumes that you are familiar with the operation
of your computer, and the target microprocessor, and is not designed
to be a tutorial on programming or software design. It tries to be
organized in a format which should maximize its usefulness as a
reference document.

1.1 Shareware Licence

The Macro+ Assembler program and miscelaneous included files ("the
software") are the copyrighted work of their author, Don Lekei. They
are distributed under the "SHAREWARE" concept, which allows you to try
the program in actual use for a period of time before you pay for it.

All rights under Canadian and international copyright law are
reserved. You are hereby granted a limited license to use the
software, and to make copies of and distribute said copies of the
software, as long as the following conditions are met:

1) Distributed copies must contain the complete set of files as
provided here, with no changes, deletions or additions
(archive format excepted).

2) Copies may not be distributed by any person, group or business
which has as its primary purpose the distribution of free and
"shareware" software for profit. BBS distribution is allowed
as long as no fee is charged specifically for this software.

Non-profit user's groups, clubs and other organizations may
copy and distribute the software as long as no charge is made
for such service beyond a nominal disk/duplication fee or
normal line charges.

Other organizations or businesses wishing to distribute the
software must contact the author for licensing agreements.
Reasonable licencing for inclusion in other developement
systems is available.

3) The use of this program is not for profit. If you use this
program for professional or business use, (i.e. for product
developement or consulting) you are required to pay a license
fee of $100 (CDN). This covers all computers at a single

(C)1993 Don Lekei

2 Macro+ Assembler Version 5

You may evaluate the software for a 30-day period, or for use
in ONE project, whichever is longer, at the end of which you
must either pay the license fee or cease using the software.

Registration provides access to updates on the athors BBS at (604)
597-3479. Future enhancements and technical support will only be
available to registered users.

Please send Check or Money order with your Name and return address to:

Don Lekei
8678 110A Street,
Delta, B.C.
V4C 4K7

1.2 Philosophy

This assembler is of a type often called "cross-assemblers", which is
used to mean an assembler which is written to operate on one computer
(a "PC" in this case) and generate code for another (semantically, it
should mean an assembler which reads code written for one
microprocessor, and generates code which will execute on another...
but it doesn't).

Since the Macro+ assembler is designed for developing software for a
product (as opposed to a "computer program") it contains features to
make that job much easier. In a product, such as a microwave oven, fax
machine, or photocopier, you are likely to need functions to generate
LCD or ON-SCREEN display controller text, convoluted control data, or
be forced to work within the constraints of very limited memory. Also
included are functions to help in project management, such as module
search path control, report generation capability, and external
utility control.

Assembly language code is especially susceptible to subtle errors
causing problems which are difficult to track down. This assembler
tries to detect many possible errors which may be caused by typos or
differences in the operation of some assembler directives when porting
code from a different cross-assembler.

1.3 Microprocessors supported

This assembler is available in several versions, each of which
supports different microprocessors.

AS10 supports the NEC uPD7810, 78C11, 7810H, 7811H, 78C10, 78C11 and
AS74 supports the 8 bit Mitsubishi Microcontrolers - 507xx, 374xx.

(C)1993 Don Lekei

Introduction 3

AS77 supports the 16 bit Mitsubishi Microcontrolers - 37700.
ASPIC supports the Microchip PIC series Microcontrolers 16CXX and

A directive is provided to reject the instructions for different
flavours in the same microprocessor family which are not supported.

Every attempt was made to maintain maximum compatability with other
assemblers and with the manufacturer's source definition, even where
conflicts occur. For example, in AS10, both the full register-pair
names (as per the user's manual) and the abbreviations used in some
other assemblers are allowed.

1.4 System requirements

The Macro+ assembler is designed to operate on a "PC-compatible"
computer with 640 K of memory and MS-DOS 2.0 or greater (at least 3.1
is recommended). The assembler will, of course, work much faster on a
V20, 80286, 80386, 80486 based computer with a hard drive, but unlike
most other programs these days, this software does not require a 80686
with 3 terabytes of memory and 12 GB of disk space to run.

As with any program which accesses files under DOS, your CONFIG.SYS
file must contain an appropriate FILES statement (FILES=20 is usually
enough), and a BUFFERS statement suitable for your CPU (BUFFERS=18 is

NOTE: It is highly recommended that you use the assembler on your
fixed disk, since the source file(s), hex file, and possible
listing file must be accessed many times in the course of an
assembly. The floppy drives are EXTREMELY slow when changing

1.5 Notation used in this manual

Throughout this manual, the following notation is used when describing
the parameters required by various commands:

Symbol Meaning
expr Arithmetic expression
term Single term of an expression (eg. the 6 in 5*6+2)
value An expression which may have some special options
strexp String expression
addr Address expression
label Label
< > One of the enclosed items is required
[ ] Items inclosed in brackets are optional
Enter the actual character ( [ < > ] )
... An undetermined number of similar items may be

(C)1993 Don Lekei

4 Macro+ Assembler Version 5

? Any character as described in the text
Blank space may be any number of spaces or tabs

All other text must be entered as shown. Capital and lower-case
letters may by used interchangeably, except in label names, where case
is significant.

1.6 Assembler Operation

This is a 2 pass, source module assembler. It assembles one or more
source code files directly into an object code output file (Intel HEX
format) which is accepted directly by most EPROM programmers or emula-
tors. Unlike an object module assembler, there is no extra linking
process required.

On the first pass through the code, the assembler determines which
source files are required and where they are located in the INCLUDE
path (and prints the file list if requested). It checks the syntax,
determines the length of all instructions and data, defines macros and
translation sets, and calculates all addresses.

If the first pass is successful, the second pass fills in any labels
not defined on pass 1 as it reads the source files again, generating
the actual object code and the assembly listing (if requested).

Finally, it prints (optionally) the symbol table, macro table, and
cross reference reports. All reports are sent to the standard output
(normally the display) which may be redirected to a file, printer, or
pipe from the command line (or batch file).

1.7 Error Return

On successful completion, the assembler will return a code of 1. If
errors occurred during compile, the return code will indicate the
number of errors.

Note: warnings will not affect the return code.

1.8 Command line parameters

The Macro+ assembler is designed to be controlled from the command
line or from a batch file. If you invoke ASPIC (if there is a name
conflict with on your system, it may be renamed as something else as
long as the name ends with ".EXE") with no parameters, you will see
the help display as shown below.

(C)1993 Don Lekei

Introduction 5

Usage: ASPIC [-lsxi@] [-...]
-l[,a][,e][,l][,t].. List (ASCII, Epson, Laser, Terse(default))
-s ................. Symbol table
-x ................. XREF Listing
-i ................. Include Listing
-@ ................. Force undefined symbols to AAAA
-[=] User option

Options may be entered in upper or lower case and may be indicated by
a dash ("-") or slash ("/"). Single letter options may be combined
into a single option such as "-lsxi". If an option requires spaces or
special characters, the entire option may be enclosed in quotes.

If the -l option is selected, an assembly listing will be generated to
the standard output. The -i option will cause a list of included
files, their pathnames, and the date and time each file was last
modified, to be printed to the standard output. Output may be fully
formatted for printing to an Epson-compatable, or an HP Laserjet
compatable printer, by adding a comma separated modifier to the list
option. For example, to print a better listing to a laser printer,
use the option "-l,l".

The default listing option , strips the listing to a minimal output.
This is the format to use for PICSIM compatability.

The -s and -x options cause the symbol/macro table and cross-reference
reports to be printed at the end of pass 2.

The -@ option is sometimes useful for debugging. It causes all
undefined symbols to be defined to $AAAA to prevent "Undefined label"

All remaining letters may be used for user-defined options (see
section 2.3.).

The file may be specified as a file or a full drive:path\filename.ext
specification. If no extension is supplied, an extension of ".NEC"
will be added. If no path is specified, the current directory is
searched, followed by the INCLUDE path. If a path is specified, the
specified directory is searched first, then the INCLUDE path. See the
description of the .INCLUDE directive for more details.

In addition to the specified syntax for the assembler invocation, the
normal DOS functions of redirection and piping are available. The
standard input channel (pipe or "<" redirection) supplies input to the
"= [KBD]" function.

The standard output channel (pipe or ">" redirection) receives the
listing, reports, and a copy of the error messages. Although the error

(C)1993 Don Lekei

6 Macro+ Assembler Version 5

channel cannot be redirected from the command line but may be split
with assembler directives (see .ERROR and .ECHO).

Examples of typical command lines would be:


The first example will assemble "PROJECT.ASM" from the current
directory (or somewhere else in the INCLUDE path), generate the object
file "PROJECT.HEX" in the same directory, and generate the full set of
reports to the file "PROJECT.PRN" in the current directory.

The second line would assemble "\ASM\PROJECT.ASM" from the current
drive, and generate and object file in "\ASM\PROJECT.HEX".

(C)1993 Don Lekei

Source Code Format 7

2 Source Code Format

An assembly-language program for the Macro+ assembler consists of a
group of files, each containing a series lines of ASCII text
terminated by carriage-return and linefeed characters. You can create
and edit these files using any ASCII text editor (such as vi, PC-
Write, etc.), or a word-processor capable of editing text without
corrupting the ASCII codes (eg. WordStar Professional 4 in non-
document mode only). Warning: WordStar after 4.0, MS-Word,
Wordperfect are not recommended. The damage they can do to a file may
not easilly be undone.

2.1 Source line format

The general format of a line of source code is:

[label][:] [.][opcode] [operand(s)] [;comment]

Comment-only lines may begin with an asterisk, a semicolon, or be
completely blank. Such lines have no effect on the code, but may
greatly enhance the documentation.

The label may optionally be followed by a colon, which is ignored, but
is useful in searching for the line where a label is defined. With
the exception of a few assembler directives which define labels in
special ways ( = (EQU), SET, .MACRO and .CSET), the label will be
defined to be the current program counter before the opcode (or
directive) is encountered. To make your source code neater an easier
to modify, you may, if you prefer, put the label on the line prior to
the opcode.

2.1.1 Opcode parsing

For all opcodes (machine mnemonics, assembler directives, or macros),
the case of the text is ignored. Upper and lower case are treated the
same. If you like to highlight macros or loops by putting them in
lower case (or enter all of your code in lower case) it will be
interpreted correctly.

Normally the machine mnemonics are checked first, followed by the
macros, then the assembler directives. If the opcode begins with an
optional ".", then the assembler directives are checked, followed by
the macros, and the machine mnemonics are not checked at all. In this
way, you can determine whether a macro will override an assembler
directive or machine mnemonic.

2.2 Labels

A label may begin with A...Z, a...z, underscore ("_"), or period

(C)1993 Don Lekei

8 Macro+ Assembler Version 5

("."), followed by A...Z, a...z, 0...9, $, underscore, or period. In
label names, case is significant. Labels may contain any combination
of upper and lower case letters, but the labels "NAME", "Name", and
"name" are three separate labels. Regular label names have a maximum
length of 15 characters.

If a label name is the same as a register name, it will not be
recognized as the operand of a CPU instruction unless it is enclosed
in parenthesis (or embedded within an expression). There are no
reserved label names (although there are some labels defined by the

If a label begins with ".." it is considered to be a variable, and may
be re-defined at any time. The value of a variable is always the last
value assigned. A warning will be generated if a variable (..NAME) is
referenced before it was defined. On pass 2 it will have the last
value it was given in pass 1.

A label in brackets (eg. "[NAME]") is a LOCAL variable and cannot be
accessed outside of it's level. Each INCLUDE file or MACRO expansion
is assigned it's own level. Of course a label such as "[..LOOP]" is
therefore a local variable label. Local labels are listed in the
symbol table with a level indicator in the form "LABEL]xx". Local
labels have a maximum length of 10 characters.

Several assembler directives use the label in a special way or
generate or use special types of labels (see MACRO, CSET, SET).

The comment field may contain any characters except for NEWLINE ($0A),
NULL ($00) and, under MS-DOS, EOF ($1A). The use of non-printing
characters (except spaces and tabs) is not recommended. All tabs will
be expanded to 8 character stops in the assembly listing, so tab
positions will be correct with respect to the left edge of the source
code column.

The special local variables [0] through [9] are the macro parameters.
Macro parameters may also be named, and the names are assigned
sequentially, starting with variable [0]. Macro variables are
replaced by the text of the invocation parameters as the macro is
expanded. Macro parameters are not TRUE labels, they are actually a
type of in-line macro, and cannot be assigned a value directly (see

2.3 System defined labels

Several labels are pre-defined by the assembler to provide information
to your source code about internal conditions within the assembler.
These labels behave exactly like regular labels defined by your source
code. They only provide information; changing their values will not

(C)1993 Don Lekei

Source Code Format 9

affect the internal information used by the assembler itself.

Label Description

.._pass The current pass number (1 or 2). This is useful for
controlling the use of the .ECHO command so user
generated reports are created only once (on pass 1 or

.._err The return code from the last SHELL command. This is
the same value as would be returned to the DOS "if
errorlevel" batch file command.

All of the following timestamp values are defined in BCD so that they
may be inserted into the code as data and read out later (with an
eprom programmer, etc.) in hex as if they were decimal (eg. January
25, 1988 10:30 am would produce the hex bytes: $01,$25,$88,$10,$30).

_hour The hour of the start of assembly.
_minute The minute of the start of assembly.
_day The day of the start of assembly.
_month The month of the start of assembly.
_year The year - 1900 of the start of assembly.
.._hour The hour of the last modification time of the current
.._minute The minute of the last modification time of the
current file.
.._day The day of the last modification time of the current
.._month The month of the last modification time of the current
.._year The year - 1900 of the last modification time of the
current file.

The following labels are defined based upon the options on the command

clop_l 1 if the -l option selected (list)
clop_x 1 if the -x option selected (cross reference)
clop_s 1 if the -s option selected (symbol table)
clop_i 1 if the -i option selected (INCLUDE file list)
clop_ 1 if the -@ option selected (define undefined labels
to $AAAA)

For other user-defined options, clop_? (where ? is the character from
the format -?[=expr]) will be defined to either 1 or the value of the
optional expression. If the command line option is specified as
-?:expr then the label clop_? will be defined to -1 and the remainder
of the argument will be placed into the environment variable CLOP_?

(C)1993 Don Lekei

10 Macro+ Assembler Version 5

for later evaluation.

.._index Defined to the current loop index of the innermost DO
loop. It is only a copy of the loop index, changing it
will have no effect. If outer counters of nested loops
is required, the source code will need to make its own
copy in the outer loop.

2.4 Expression evaluation

To preserve compatibility with microprocessors which require
parentheses as part of the addressing mode syntax, expressions are
always evaluated left to right (with the exception of unary operators
and prime) unless parenthesis are used. This results in there never
being a case where parentheses are required at the beginning of an
expression. There is no limit on parenthesis nesting (except memory).

Unary operators affect only the term directly following them (eg. 5 +
-3 + 1 = 3), and the prime function affects only the term immediately
preceding it. When several unary operators are used together, they
are evaluated from right to left.

The order of expression evaluation is: unary operators (right to
left), followed by prime, then all other operators (left to right).

Each term may be a numeric or character constant, a label, a function
(pre-defined or macro), the program counter (*), or an expression in
parenthesis. It may be preceded by a unary operator or followed by the
prime (') operator.

Both prefix and post-fix base notation are supported (except for the
very dangerous D and O). The following formats may be used for
defining constants:

2.4.1 Constants

decimal: nnnnn where n = 0-9
hex: $xxxx where x = 0-9, A-F, or a-f
nxxxH or 0xxxxH where x = 0-9, or A-F
binary: %bbbbbbbb where b = 0 or 1 - Must be multiple of
8 bits
bbbbbbbbB where b = 0 or 1 - Must be multiple of
8 bits
ascii: 'c' or "c" where c = any printing char
'cc' or "cc" first digit is high byte
octal: @ddddd where d = 0-7, 5 digits maximum

Warnings will be generated if a binary values are not multiples of 8
bits long, if decimal numbers have more than 9 digits (hex > 8 digits

(C)1993 Don Lekei

Source Code Format 11

is an error) or if address expressions begin with literal constants
(eg. $FF22). This will catch such common errors as :

00010100 (missing '%' (evaluates to $2774, not $1A))
%1111000 (missing bit)

or accidentally using a DIRECT addressing mode, when an IMMEDIATE mode
was intended.

2.4.2 Unary operators

~ term 1's complement of term
- term 2's complement of term
! term logical not of term (1 if 0, 0 if non-zero)
!! term logical true of term (0 if 0, 1 if non-zero)
< term low byte of term (first byte of term)
> term high byte of term (if term is a 16 bit value.
If term is more than 16 bits, the result is
the same as term >> 8)
<> term second lowest byte of term
<>> term third byte of term
>>> term fourth byte of term
>> term high word of term
: term force word mode (forces $xx to be treated as
^ term bit #term eg. ^0 = %00000001, ^6 = %01000000
The high byte of term is ignored so bit labels
(see EQU) will work. For example, (assuming
all of these labels are bit-labels) the
expression "^MOTOR_ON|^SPEED_OK" evaluates to
a byte with bits MOTOR_ON and SPEED_OK set.
term' Value of term at OBJECT address. For example,
if the object address (from *=) is at $C000,
but the program counter (from ORG) is at
$1000, the statement "LABEL:" would define
LABEL as $1000. If "LABEL = *' " was used,
LABEL would have a value of $C000.

2.4.3 Arithmetic operators

These operators perform their normal functions (except for
precedence). Note that multiply and divide operators treat their
operands as unsigned values to prevent confusing or incompatible

+ add
- subtract
* multiply (unsigned)

(C)1993 Don Lekei

12 Macro+ Assembler Version 5

/ divide (unsigned)
% modulo (unsigned)

2.4.4 Boolean operators

Boolean operators perform bit-wise logical operations on 8 or 16 bit
data. The following Boolean operators are supported:

& and
| or
^ exclusive-or
>> term shift right term times (unsigned)
<< term shift left term times

2.4.5 Relational and logical operators

Relational operators compare the preceding expression to the following
term using a signed comparison of numbers in the range -32768 to
+32767. This is best for most cases, when a >0 <0 type result is
desired and when comparing byte values. Beware when comparing ADDRESS
values; the sign of relative comparisons will be reversed when
comparing addresses on opposite sides of the 32K boundary.

The available relational operators are:

< term 1 if the expression is less than term
<= term 1 if the expression is less than or equal to term
= term 1 if the expression = term
== term same as above
! term 1 if the expression not = term
!= term same as above
>= term 1 if the expression is greater than or equal to term
> term 1 if the expression is greater than term

The logical operators:

&& term 1 if the expression AND term are non-zero
|| term 1 if the expression OR term are non-zero

2.4.6 Functions

The following functions are pre-defined:

CHR( expr )
Return the value of expr translated by the current CSET.

ENV( envlabel )
Returns a value from an environment variable. It returns 1 if
the text of the environment string begins with YES, yes, Y, or

(C)1993 Don Lekei

Source Code Format 13

y. The value is 0 if it begins with NO, no, N or n, or null.
Otherwise it evaluates the text as an expression. Low,high
format (as in bit labels) in the string is also accepted. The
term envlabel is the same as used in the DOS command "SET
envlabel=text" (see SETENV).

EXIST( strexpr )
Returns 1 if the file or path defined by the string expression
exists, otherwise 0 is returned.

ISDEF( label )
Returns 1 if label is defined, 0 if undefined.
(Warning: the result may be different on pass 1 and 2)

NEWER( strexpr1 / strexpr2 )
Returns 1 if the file or path specified by strexpr1 is newer
than, or has the same last modification date as the file or
path specified by strexpr2. If the first file does not exist,
the result is always 0. If the second file does not exist,
the result is always 1.

Note: for the "NEWER(" or "STRCMP(" functions, if the last item in the
strexpr is a numeric value, a null string (,"" or ,'') must be added
to signify the end of the string expression.

OFFSET( address )
Returns the low lower 16 bits of an address.

STRCMP( strexpr1 [<=>-/%] strexpr2 )
Perform string comparison. Strings may be text in quotes ("
or '), comma separated bytes, or environment variables
preceded by #. Strings for STRCMP may not have NULLs (0) in
them. All comparisons are case-insensitive.

String operations supported are:
< strexpr1 is less than strexpr2
= strexpr1 is less than strexpr2
> strexpr1 is greater than strexpr2
- 0 if equal, positive if strexpr1 is greater than
strexpr2, or negative if strexpr1 is less than
/ 1 if strexpr2 is the beginning of strexpr1
% 1 if strexpr2 is a substring of strexpr1

Also the special, "select" function, which is more like a cross
between a function and an operator:

expr1 ? expr2 : expr3
if expr1 is TRUE, the value is the result of expr2.

(C)1993 Don Lekei

14 Macro+ Assembler Version 5

if expr1 is FALSE, the value is the result of expr3.

In addition to the above functions, function macros may be defined.
Function macros are described in detail in the section on macros.

2.5 String expressions

Certain assembler directives, and the STRCMP() function, accept a
special type of operand called a string expression (referred to as
strexp). A string expression consists of one or more comma-separated
items from the following list:

Text in single or double quotes is interpreted as a
list of the ASCII codes of the enclosed text. Within
the body of a macro, macro parameters within single
quotes will be expanded, while parameters within
double quotes will not).

Expressions which evaluate to byte values (a warning
will be given if the value is truncated to 8 bits).

If the item begins with a "#" symbol, it is
interpreted as an environment variable in the form
"#envlabel" and the text assigned to that variable
will be interpreted as if it were text enclosed within
double quotes.

For example, the string expression:

"The current DOS PATH is ", $2A, #PATH, $2A, $A

would evaluate to the ASCII codes for the message "The current DOS
PATH is ", followed by the actual DOS search path at time of assembly,
within quotes, and a NEWLINE character.

2.5.1 Special environment variables

To aid in project management and reporting macros, several internal
environment variables have been defined.

_LABEL The name of the last defined label.
_FILE The name of the current file.
_ROOTFILE The invocation file of this compile.
_TIME The date and time of the start of compile as
an ASCII string.
_FTIME The modification date and time of the current
file as an ASCII string.

(C)1993 Don Lekei

Assembler Directives 15

3 Assembler Directives

The Macro+ assembler supports an extremely powerful set of assembler
directives. Assembler directives affect the way in which the code is
generated, they do not generate executable code. The purpose of
assembler directives is to make programming faster and easier, and to
make the code easier to understand and maintain.

In an assembler, structures such as IF... ELSE... ENDIF, CASE...
SWITCH... ELSE... ENDIF, and DO... LOOP cause the selected code to be
assembled if (or while) the appropriate conditions exist. They do not
create code which makes decisions.

Defined functions and expressions produce constant values which may
become part of the code, but the expressions used to create those
constants are not available to your program.

Macros may generate code because macros ARE (usually) code, the assem-
bler directives help you to define macros (if you were to write enough
macros, you could conceivably turn the assembler into a compiler).

In this section, the directives are grouped by function, Appendix B
provides a listing in alphabetical order. The optional label field
(and [:]) is implied to be as described in section 2 unless otherwise
specified. The comment field is used to give the brief description of
the command. The leading period on all directives is shown, but is
always optional.

In several cases there are alternate names for functions which are
provided for syntax compatibility with other assemblers. These are
shown in parentheses. Their use is not generally recommended, as they
warn the assembler to check for portability problems, and may result
in additional warnings or errors.

3.1 Data definition directives

.BYTE strexp ;Byte/string data (untranslated)

.WORD expr [,...] ;Word data (low,high)

.DBYTE expr [,...] ;Double-Byte data (H,L)

(.DB) (same as .BYTE)
(.DW) (same as .WORD)

These directives place a series of bytes of data into the code. They
all accept, as their arguments, comma separated lists of data. The
.BYTE directive accepts a special type of list called a "string
expression" (see 2.5.).

(C)1993 Don Lekei

16 Macro+ Assembler Version 5

The .WORD directive places the word data in the native
microprocessor's storage format (low byte, high byte) suitable for
vectors, while .DBYTE puts the data into high byte, low byte format
for special applications.

3.2 Special data directives

.CHK ;Balance vertical parity

The .CHK directive puts a single byte of data into the code to balance
the vertical parity (the result of all bytes exclusive-ored together)
to zero. This directive should be used as close to the highest
location as possible, after all code or forward references. It will
incorporate any .BYTE, .WORD, etc. bytes which may follow it.

.FILL byte,length ;Fill range with a repeated byte

.ZMB length ;Fill range with 0 (same as .FILL 0,)

These directives generate a specified number of identical bytes, to
pad a block of code. The .ZMB directive is a special case of the .FILL
directive, which is provided for compatibility.

A common use of the .FILL directive is to pad unused EPROM area with
$FF to ensure that a PROM test will succeed, and that the checksum is
not dependant upon what data was previously in the EPROM programmer's
memory, for example:

.FILL $FF,PROM_END-*-1 ;Pad EPROM with $FF (reserve 1 byte)
.CHK ;make vertical parity = 0

Filling the unused area of an EPROM to $FF will also reduce the time
to program, since an EPROM starts with all locations set to $FF, and
any good programming algorithm should not even bother to program them.

3.3 Translation directives

name .CSET [strexp] ;Define character set for translation
.CSET strexp ;Add to character set
.CSET = cset name ;Select character set for translation

The .CSET directive allows you to specify the order of the characters
in the character set for a particular device (it may also be used to
help manage any other types of translation tables). For example, the
NEC uPD6105 on-screen chip has a character set which has no letter "O"
and begins with the number "0" being the character-code zero. The
translation set for this chip might look something like:

CS6105 .CSET "0123456789:x,-./"

(C)1993 Don Lekei

Assembler Directives 17

.CSET "}{])([*'rl _+!ud"

After this character set is defined, you could use the directive

.CSET = CS6105

to set the active translation set to the defined set, then the .TEXT
set of directives will automatically translate the string expression
to the appropriate codes. For example, assuming the environment
variable MYVER is set to "MYVER=1.2", the statement


would generate the HEX codes, 26, 15, 22, 23, 19, 00, 1E, 3A, 01, 0E,
82 (note that the number "0" is used in place of the letter "O"). This
makes handling such devices much easier and more maintainable.

To aid in generating translation tables for packing, unpacking, and
set translation, the .XTABLE directive is provided. It has the form:

.XTABLE [(start),],length,name1,name2
;make CSET to CSET translation table
(start) is an optional starting number ("()," are required)
length is the number of bytes to generate
name1 is the "from" CSET name
name2 is the "to" CSET name

A warning will be generated if any of the first CSET are not defined
in the second CSET. If there is no second CSET specified, the output
will be ASCII. If no first CSET is specified (,,) then the range of
values will be translated. If no sets are
specified, the sequential values will be output.

X1 CSET "AaBbCc"
X2 CSET "ABCabc"
0000 00 03 01 04 XTABLE 4,X1,X2 ;CSET X1 to
0004 42 62 43 63 XTABLE (2),4,X1 ;CSET X2 to
0008 00 01 02 XTABLE ('A'),3,,X2 ;ASCII to CSET
;(starting from 'A')
000B 10 11 12 13 XTABLE (16),4, ;sequence of

(C)1993 Don Lekei

18 Macro+ Assembler Version 5

On the PIC 16Cxx parts, the XTABLE directive will generate a table of
retlw instructions. An example of a routine to return a translation or
encoding table might be:


These translation tables have many uses other than shown above. Many
type of translation tables and data-set tables may be generated by
using creative applications of the .CSET and .XTABLE directives.

Another use for translation sets, is to pick which characters will be
supported in the limited character set size of the 3-to-2 and 4-to-3
text packing directives.

Character/data set translation is supported by the .TEXT, .TEXTZ,
.TEXTX, and .TEXTL directives, and by the CHR() function.

For more examples of the translation directives, see the file

3.4 Translated data directives

.TEXT strexp ;Translated: character data
.TEXTZ strexp ;Translated: charters, followed by a 0
.TEXTX strexp ;Translated: last char. xor $80
.TEXTL strexp ;Translated: length,characters

These directives put byte data into the code similar to the .BYTE
directive, except that the text is translated using the current CSET
(see 3.3.). Several optional forms are provided, depending on how you
want the strings delimited.

The basic .TEXT directive places the characters from the string
expression into memory in sequential order. The difference between
.TEXT and .BYTE is that the .TEXT directive translates the character
codes as necessary. This offers the added flexibility of changing the
character set of the output device freely, yet in a portable manner to
accomodate non-ASCII devices.

3.5 Packed data directives

.PK32 strexp[...] ;Packed (3-to-2): characters
.PK32X strexp[...] ;Packed (3-to-2): with end flag
.PK32 = cset ;Select translation set for 3-to-2

.PK43 strexp[...] ;Packed (4-to-3): characters

(C)1993 Don Lekei

Assembler Directives 19

.PK43L strexp ;Packed (4-to-3): length (0-63),
.PK43 = cset ;Select translation set for 4-to-3

The packed data directive are similar to the .TEXT... directives,
except that they compress the data using 3-to-2, or 4-to-3 packing.
The data bits (5 or 6 bits of each character) are packed into
consecutive bytes from the highest bit of the first character to the
lowest bit of the third (or fourth) character.

The character set to be used for packing in each mode is set by
assigning a previously defined translation set (from a .CSET
directive) to the base directive. For example, to set the 3-to-2
translation set to a previously defined character set "PKSET", you
would use:


3.5.1 3-to-2 packing

Since there is a spare bit in each group of three characters in 3-to-2
packing, the .PK32X option sets the spare bit to indicate the end of
the string. In this mode, the string is padded with 0's to the end of
the current 2 bytes.

The .PK32 directive is used to generate fixed-length strings. It will
generate a warning if the number of bytes generated is not a multiple
of 2. An ellipsis (...) may be added after the string expression if
the packing is to be continued in the next directive, and remaining
bits will be preserved.

Normally, 3-to-2 packing would be of little use, since there are few
uses for a character set of less than 32 characters, however if the
codes 0 and 32 are reserved, the .PK32 and .PK32X directives support
character-set shifting, using the 0 code to switch between the lower
and upper 32 characters in the set. The translation always begins
based upon the lower 32 characters, and the first 5 bits will be 0 if
the first character is from the upper 32.

3.5.2 4-to-3 packing

The process for 4-to-3 packing is the same as 3-to-2 packing, with 6
bits per character instead of 5. No shift character is used in 4-to-3
packing, so the character set is limited to 64 characters.

In 4-to-3 packing there are no spare bits, so the .PK43L directive is
provided to give the length of the string in the first 6 bits. Since
.PK43L format text cannot be concatenated, the ellipsis is not

(C)1993 Don Lekei

20 Macro+ Assembler Version 5

supported. An error is generated if the output is not a multiple of 3
bytes long.

3.6 Assignment directives

label = expr [,bit addr] ;Assign a value to a label
label = [KBD] [,prompt] ;Input a value from the keyboard

The normal use of the "=" directive is to assign a value to a label.
Optionally, the value may be specified in "bit-label" format, which
is: bit-number (0-7), address.

Bit-labels may be used directly in BIT instructions to convey both the
address and the bit number, or the address may be overridden by
specifying it directly. The high byte of the address must either be 0
or equal to the current VDEF setting. Using one of the bit-labels
defined in the example in 3.7., you could use:


which is exactly the same as (but more maintainable than) writing:


Bit labels may be used in other instructions which do not support bit-
labels, as seen in the example in 3.7.

Bit-labels format may also be used to define a label in low byte, high
byte format if the value can be more easily be understood in that

The special parameter "[KBD]" causes the assembler to pause on pass 1
and prompt the user to supply the value from the keyboard. You may
optionally supply a prompt as text following [KBD] or as a string
expression beginning with quotes. If no prompt is supplied, the
default prompt is "Enter the value for label XXXXX: ", (where XXXXX is
the label name).

If input has been redirected (from the DOS command line using "<"),
then the prompt will not be printed, and the input will come from the

The assigned value will be 1 if the response is YES, yes, Y, or y. The
value will be 0 if the response is NO, no, N or n, or null. Otherwise
the text is evaluated as an expression. Low,high format (as in bit
labels) in the string is also accepted. Forward references will
produce an error.

.EXT label[,label...] ;declare a label as undefined

(C)1993 Don Lekei

Assembler Directives 21

This will declare the labels in the list as being external. They will
be flagged as forward references, and the value will be assumed to be
a number > 255. If a label is declared as EXT, a value of zero will be
assumed if the value is never defined, but no error will be given.

.GLOBAL label[,label...] ;declare a label as global,
for export

At the end of the compile, if any labels are declared as GLOBAL, they
will be output to a global symbol file with the name rootname.sym
(rootname is the invocation filename). On ASPIC, the filename will be
rootname.xfr as the .sym extension is required for a simulator
transfer file.

This file is formatted as an assembler source file and may be
.INCLUDED into another source (with the ".INCLUDE" directive).

The primary purpose of this directive is to transfer symbols between
one program and another, such as external devices which must
communicate references to internal variables of a host processor, or
which must know about system limits.

The format of this file is compatable with all ASxx series assemblers,
and also with many other assemblers.

label .SET expr[,bit addr] ;Redefine a constant

This will allow you to redefine a constant. In general it is advisable
to use variables (..NAME) if a label is to be re-defined (see section

(.EQU) (same as =)

3.7 Address control directives

*= addr ;Set Program Counter

.ORG addr ;Origin ASSEMBLY address only

.DS length ;Define storage space (no bytes

(* =) (Same as *=)
(.BLKB) (same as DS) sets OLD syntax mode

The "*=" directive is used to set the assembly address of a program.
An include file "SEGMACS.ASI" is provided (along with some other
demonstration files) to aid in managing the various special areas of

(C)1993 Don Lekei

22 Macro+ Assembler Version 5

memory used by the CPU. The program counter must be set at least once,
or a PC overflow error will be generated. For this initial setting of
the program counter, the .ORG directive may also be used (to be
portable from other assemblers), this is the only time that the .ORG
directive behaves the same as "*=".

The Macro+ assembler generates object code primarily designed to be
put into EPROM or ROM memory, so RAM storage areas cannot be directly
initialized. The .ORG directive may be used to create initialization
tables which may be copied into RAM, yet appear in the source code as
if they are actually assembled into RAM. This makes memory (or memory-
mapped I/O) initialization much more intuitive and maintainable.

If an internal ROM area address is required, the prime (') operator
may be used to return the address of a label (or the program counter)
at the actual ROM address. This may only be done while within the
adjusted ORG area.

Consider the following code fragment (see SEGMACS.ASI for a
description of the segment management macros):

; <<< the program counter is currently in a CODE area >>>
; <<< which has been selected by a previous SEG macro >>>

.CPU 16C71

SEG RAM ;switch to RAM area to get the next
RAM_TABLE: ;define label for start of table area

OLDSEG ;return to previous (CODE) segment

; << NOTE: on 16C5X parts, FSR must be masked here >>

MOVFW FSR ;get indirect file pointer
ADDLW -RAM_TABLE ;offset to start of table
ADDWF PC ;return corresponding initialization

* Ram initialization table (in code)

INIT_TABLE: ;This label is defined to the actual
.ORG RAM_TABLE ;now all labels will be generated for

(C)1993 Don Lekei

Assembler Directives 23

;although any data generated will
;be put into the CODE at INIT_TABLE

.VDEF * ;Assume this area may be used for bit
FLAGS: ;Miscellaneous flags
F.STEP = 7,* ;Bit labels for use with BIT
F.ACT = 6,* ;instructions
F.IDLE = 5,*
F.M1 = 4,*
F.M2 = 3,*
.BYTE ^F.IDLE|^F.M1 ;IDLE and M1 flags initially set

.BYTE 3 ;initial value for MODE (3)
.BYTE 0 ;initial value for UNIT (0)
NULL_MESSAGE: = *' ;NULL_MESSAGE is defined to ROM
;of this initialization string, while
;MESSAGE_OUT is the address of the
;RAM buffer.
.PK32X "------" ;initial message (4 bytes)

.ORG ;now back to normal addressing
INIT_LEN = *-INIT_TABLE ;length of initializing table

.SEG RAM ;switch to RAM area
.DS INIT_LEN ;Reserve room for above data
.OLDSEG ;Back to ROM area

The code to initialize the RAM table area would be:

MOVLW RAM_TABLE ;destination pointer
MOVWF FSR ;to indirect
CALL GET_INIT ;get the initialization data
MOVFW IND ;write initialization data
INCF FSR ;NEXT address
XORWF FSR,W ;Check if done...
BTFSS Z ;skip if done
GOTO ..loop ;loop until done

This makes for much more maintainable code as the initialization data
and the memory definitions are kept in a single location, ensuring
that all locations have a defined initialization value.

(C)1993 Don Lekei

24 Macro+ Assembler Version 5

The above example also demonstrates the automatic code generation
feature for 16CXX processors, as the example generates all of the
necessary initialization RETLW instructions for the lookup table.

3.8 Conditional assembly directives

Conditional assembly directives select code to be generated based upon
the result of an expression. If the expression is NON-ZERO, it is
considered to be TRUE; a value of ZERO is considered to be FALSE.

There are two basic types of conditional assembly structures:

The code which is not assembled, is marked with an "s" in the assembly
listing. The skipped code may be omitted from the listing by executing
a .IXP OFF directive in your source code.

The basic syntax of each of the conditional assembly directives is:

.IF expr ;IF/ELSE/ENDIF conditional assembly

.ELSE ;End of case in conditional assembly

.ENDIF ;End of conditional assembly


.CASE (default) ;Case of no other match

3.8.1 IF/THEN/ELSE/ENDIF structure

The IF/THEN/ELSE/ENDIF structure is:

.IF expr ;expr is evaluated for TRUE/FALSE

... ...

[.ELSE] ;optional FALSE condition

[... ...]

.ENDIF ;end of conditional code

The IF/THEN/ELSE/ENDIF structure assembles the code if the expression
is TRUE (or an optional second block of code if the expression is
false). If any labels in the expression of an IF statement are
undefined (or forward references) they will be defined to 0 (to
prevent accidentally creating code which is different on pass 1 and

(C)1993 Don Lekei

Assembler Directives 25

pass 2. This may be defeated through the use of the ISDEF() function
(see 2.4.6.).

There are several system-defined variables which may be used in
conditional assembly statements (see 2.3.).

3.8.2 SWITCH/CASE/ELSE/ENDIF structure

The SWITCH/CASE/ELSE/ENDIF structure assembles one of several blocks
of code selected by comparing the result of each CASE expression with
the result of the SWITCH expression. The first CASE expression which
is equal to the SWITCH expression is assembled.

A special .CASE expression is provided which will always match: ".CASE
(other)". Since this will always match any SWITCH expression, it must
be the CASE in the list.

Individual CASE blocks are separated with the .ELSE statement. If the
.ELSE statement is omitted, the first CASE will also assemble the code
of the second CASE.

The normal SWITCH/CASE/ELSE/ENDIF structure:

.SWITCH expr ;initiate structure
.CASE expr1 ;first CASE
... ...
.CASE expr2 ;second CASE
... ...
.CASE (other) ;default CASE
... ...

Although the SWITCH/CASE comparisons test for equality, it is
sometimes desirable to make the selection based upon a relational
comparison (ie. >, <, =, etc.) or on a series of un-related
conditions. In these cases, you may use the expression 0 or 1
(depending upon whether you want true or false conditions) in the
SWITCH statement, then use the full logical expressions in the CASE
statements. NOTE: you can convert an expression to logical (1 or 0) by
using !!(expr).

An example of a SWITCH/CASE structure using relational CASE

.SWITCH 1 ;Select the one which is true
... ...

(C)1993 Don Lekei

26 Macro+ Assembler Version 5

... ...
.CASE (other) ;did not match either of above
... ... ;this code is also
assembled if
;LIMIT < 25.
.ENDIF ;end of conditional assembly

3.9 Macros and User-Defined Functions

name .MACRO [*][mlab][mlab...][] ;Macro definition
name( .MACRO [*][mlab][mlab...]) ;Function definition

.EXITM ;Forced end of level (Same as .END)

.ENDM ;End of macro definition

.DO [*][start#,] end# ;Start of repeated code

.LOOP ;End of repeated code

A macro is a group of assembler commands (directives, opcodes, or
functions) which is treated as if it is a single assembler command.

The Macro+ assembler provides three types of macros:

a) Regular macros: this is the only type provided by most assem-
blers. They behave as if they are assembler directives or

b) Function macros: they behave as arithmetic functions in an

c) Loops: special type of macros which are expanded immediately
(rather than being defined and invoked separately), a number
of times, generating multiple copies of the same code (or

Macros may be nested (or recursive) to more than 100 levels deep. The
exact number depends on the complexity of the macros and/or
expressions involved.

3.9.1 Macro parameters

Parameters are passed to regular and function macros by text substitu-
tion. In fact, macro parameters are in themselves a form of in-line
macro (somewhat similar to #define macros in C). This form of
parameter passing is very powerful, it allows you to pass pieces of

(C)1993 Don Lekei

Assembler Directives 27

instructions, label names, text, to a macro (The file SEGMACS.ASI is
an advanced example of the uses of this feature).

There are 10 macro labels, defined as a single digit number within
brackets. ([0] ... [9]). The macro labels are local to the particular
invocation of the macro, and are not available to nested macros unless
they are passed in the invocation of the child macro (even if it is
another copy of the parent macro).

A macro label is actually a tag for the text from the invocation line;
it is not a real label. Wherever a macro label is used in the body of
the macro, the associated text from the command line is substituted in
its place.

If the parameter contains a local label (eg. [NAME]), the value is
passed to the macro as a string representing a hexadecimal constant
(eg. $240). You can also force a value to be passed in this way by
enclosing an expression within parenthesis (there are several examples
of this in the sample programs provided). If such an expression
contains a forward reference, it will be passed with a leading colon
(eg. :0 on pass 1 and :$23 on pass 2) so that any instructions using
the value will treat it appropriately.

Macro labels may optionally be declared with pseudonyms. These will
appear to be real labels in the source code, but are actually macro
labels, so they will behave differently. Named macro labels are
assigned to the macro labels [0] to [9] in the order in which they are
declared in the macro definition. Named macro labels will not be
expanded when embedded within other text.

Macro labels enclosed in double quotes (") are not expanded, but macro
labels (including named macro labels) within single quotes are. This
allows macros to build strings such as:

.TEXT 'Version [1]'

Parameters may optionally be expressed in the format: [n.s.l]
where s = the offset into parameter string (defaults to 0)
l = the number of characters to allow (defaults to

Named parameters may be expressed in the format name[s.l] with the
same effect.

This lets you use pieces of the macro label text. For example:

.IF '[1.2.1]' == 'X'

will provide a true condition if the second character of the parameter

(C)1993 Don Lekei

28 Macro+ Assembler Version 5

[1] is "X".

3.9.2 Regular macros

The definition syntax for a regular macro is:

name .MACRO [*][mlab][mlab...][] ;Macro definition
... ...

mlab is a macro label, either explicitly [0] to [9] or a
pseudonym to be used within the macro.

is any single character to be used as a delimiter,
generally comma, but may be some other character if
commas are required in the parameter.

Note: when used as delimiters, BLANK, NEWLINE, EOS, TAB are

If parameter list is preceded by an asterisk (*) the macro will always
be expanded as if MXP OFF was in effect. This allows macros to be
defined which behave exactly like machine opcodes or assembler
instructions (including the way in which object bytes are printed),
except that the cycle count is not printed. Use of this feature will
result in much cleaner assembly listings.

If an .MXP pseudo-op is executed within a macro, its scope will be to
the end of the macro only.

When the MACRO is defined, the assembler checks internal
"IF/SWITCH...ENDIF" and "DO...LOOP" structures and embedded macro
definitions for completeness. Macros defined within other macros are
not defined until the first macro is invoked.

If it is necessary to terminate the expansion of a macro prematurely
(ie. with conditional assembly) the .EXITM directive may be used.

Regular macro usage syntax is:

[label][:] NAME parmparm...parm[]

where == in definition.

If a parm contains a local variable, or is in parenthesis it will be
evaluated and the VALUE will be passed to the macro as a string repre-
senting a HEX constant (eg. $F123). Otherwise, in place of each
[0]...[9], the raw text will be passed.

(C)1993 Don Lekei

Assembler Directives 29

An example of macro usage:

* Some MACRO definitions

* Get unit parameter into accumulator (A or EA)
* HL must point to base of table
GET .MACRO [1],[2] ;get parameter [2] into reg [1] for
table @ HL
LD[1]X HL+[2] ;get relative item into [1]
.ENDM ;end of macro

* Set unit parameter from accumulator (A or EA)
* HL must point to base of table
PUT .MACRO [1],[2] ;set parameter [2] into reg [1] for
table @ HL
ST[1]X HL+[2] ;get relative item into [1]
.ENDM ;end of macro


.ORG 0 ;this makes labels referenced to 0
;but space is allocated in RAM area

.DS 1 ;device type (=0)
.DS 1 ;flag bits (=1)
F.ACT = 7 ;bit 7 = active
F.BUSY = 6 ;bit 6 = busy

.DS 2 ;transfer address (=2)
DEV_len: ;length of device table (=4)
.ORG ;restore label addresses to actual ram
.DS DEV_len ;reserve space for device 2

SEG CODE ;Set to CODE area
* Code to process devices

(C)1993 Don Lekei

30 Macro+ Assembler Version 5

LXI HL,DEVICE_1 ;check device 1
CALT PROCESS ;Process unit

LXI HL,DEVICE_2 ;check device 2
;<<< ... more of main program goes here ... >>>

* Subroutine (called with CALT) to process a device pointed to by HL
* uses the TSUB macro defined in MACROS.NEC to manage CALT table

GET A,DEV.FLAGS ;get device flags
;( assembles as LDAX HL+DEV.FLAGS )
;( which is the same as HL+1 )
ONI A,^F.ACT ;check if active
RET ;not active

OFFI A,^F.BUSY ;only process if not busy
;now process the device
GET EA,DEV.INDEX ;get transfer pointer to EA
;( assembles as LDEAX HL+DEV.INDEX )
;( which is the same as HL+2 )
PUSH HL ;save device index
DMOV HL,EA ;move pointer to HL
LDAX HL+ ;get device byte
DMOV EA,HL ;back to EA
POP HL ;restore device index
PUT EA,DEV.INDEX ;set new index
;( assembles as STEAX HL+DEV.INDEX )
;<<< ... rest of subroutine ... >>>

3.9.3 Function macros

The definition syntax for a function macro is:

name( .MACRO [*][mlab][mlab...]) ;Function definition
( expr )

For function macros, only the first line is evaluated although a .ENDM
is still required.

A function is internally expanded and evaluated as an expression, then
the resulting value is returned as a term in the original expression.

(C)1993 Don Lekei

Assembler Directives 31

Although the internal expansion process is the same as a regular
macro, the expansion is never printed in the assembly listing.

Function macros are useful for simplifying expressions and to reduce
time and the risk of error in constantly retyping commonly used

As in regular macros, parameters are passed through text substitution,
and the parameters [0] through [9], or pseudonyms may be used. In
light of this fact, macro parameters in the macro expression should
always be enclosed within parenthesis if there is any possibility of

Functions may be nested to about 100 levels deep. They may not
contain code or assembler directives. The last delimiter must always
be a closing parenthesis.

An example of a function macro:

* Function to return the higher of two (signed) values
MAX( .MACRO A,B) ;return the higher of a or b
( (A) > (B) ? A : B )
* Usage of above macro:
LOW = 3
HIGH = 100
NEG = -2

VAL1 = MAX( LOW,HIGH ) ;VAL1 is set to 100
VAL2 = MAX( LOW,NEG ) ;VAL2 is set to -2 ($FFFE)

3.9.4 DO loops

A DO loop is a special type of macro. It generates multiple copies of
the code (or directives) within the loop. Although DO loops do not
provide parameter passing, they may be included within macros, or
invoke (or even define) macros to provide equivalent capability.

The current loop index is provided within the loop in a special
variable ".._index" (lower-case is important). This is a real
variable, which is defined by the first DO loop encountered. It is
only a copy of current loop index, changing it will have no effect.

There are two ways to invoke a DO loop. If you specify a count only,

(C)1993 Don Lekei

32 Macro+ Assembler Version 5

the loop will expand that many times. If 2 values are given, the loop
will be expanded for the range of integer values specified.

The general syntax of a DO...LOOP structure is:

.DO [*][start#,] end# ;Start of repeated code
... ...
.LOOP ;End of repeated code

Like a regular macro, if an asterisk precedes the range parameters,
the expanded code will not be put in the listing (only the
definition). If there is no asterisk, the definition will not be
printed, but the generated code will be.

An example of a use of a loop:

* Generate a parity look-up table
PARITY( .MACRO [1] ) ;function to return parity of a 0-127 value
( [1>>6+([1>>5)+([1>>4)+([1>>3)+([1>>2)+([1>>1) + [1] & 1 << 7 + [1] )

.DO *0,127 ;do for 0 to 127 and don't
.BYTE PARITY(.._index) ;1 byte of parity look-up

A DO loop may be terminated prematurely with the .EXITM directive.
This will terminate the innermost loop only.

3.10 System and file control directives

These are special directives which allow the assembler to interface
with its environment. Through the use of these features, an assembler
source file can control its environment to provide extensive automatic
reporting and version maintenance capabilities.

.END ;Forced end of level

The .END command forces the end of the current level (file, macro, or
loop). It may be used to conditionally terminate a file (saving time
over skipping the rest of the file with an IF statement). The .EXITM
command is actually a pseudonym for the .END command.

.ECHO text ;Print line to console or file
.ECHO "",strexp[,$A] ;Print string expression
.ECHO {<=+>"file"}[,text] ;Set ECHO output file

(C)1993 Don Lekei

Assembler Directives 33

The echo directive allows you to print messages to the console or a
file. This can be very useful for printing lists of options for a "=
[KBD]" directive, or for generating custom assembly reports to the
screen or a file (or device).

The .ECHO command accepts the text to print as raw text, or as a
string expression which must begin with a single or double quote (this
syntax requirement is another attempt to provide compatibility with
other assemblers). If a string expression is used, a newline is NOT
automatically added, you must explicitly declare one in the string
expression. NOTE: the code for NEWLINE is $A. This allows $D
(carriage return) to be used to over-print lines.

The .ECHO command allows redirection to a file or device. If you put,
a filename preceded by "+" or "=", in braces after the echo command,
the output will be redirected to that file. A "+" indicates that
output will be appended to the end of the file, while a "=" causes the
file to be replaced on pass 1 (output will be appended on pass 2).

If there is output text (or a string expression as described above)
after the redirection, that text ONLY will be output to the file, then
the console output will be restored.

If there is no text to output, the redirection will be left in place
until explicitly changed. To explicitly restore the output to the
console, use empty braces.

.ERROR text ;Force error
.ERROR "",strexp ;Force error
.ERROR {<=+>"file"} ;Set error output file.

.FATAL text ;force FATAL error
.WARN text ;force warning (see above other

The .ERROR command functions in a similar manner to the .ECHO command,
except that it generates an error (if text is supplied). If a
redirection file (only) is designated, all error messages are sent to
the specified file (or device), generating a separate error report

The .FATAL and .WARN are identical to .ERROR, except that the severity
of the error produced varies.

The .INCLUDE directive inserts an external source file into the code.

(C)1993 Don Lekei

34 Macro+ Assembler Version 5

Each included file is assigned its own level for local variables, so
that local variables (outside of macros) are local to the included

When a new file is included into the source, a new page is normally
fed (unless there is only 1 line on the page). If this is not desired,
you may specify the maximum number of lines from the bottom of the
page that a page feed will occur. For example:


will only force a new page if there are less than 10 lines left on the
current page.

If no extension is given, the default extension of ".NEC" will be

The assembler searches the for INCLUDE files in the directory
specified on the command line, or the current working directory. If
the file is not found, it then checks for the environment variable
"INCLUDE". If "INCLUDE" exists, the drives and/or paths in the
"INCLUDE" variable are scanned, from left to right.

The "INCLUDE" variable is specified in exactly the same format as the
DOS "PATH" variable, with semicolon separated drive and/or pathnames.
The "INCLUDE" path may be specified from the DOS command line (or
batch file) with:

SET INCLUDE=[drive:]path[;drive:path2][;...]

or from within the assembler with:

.SETENV "INCLUDE=[drive ]: path1[;...]" ;(a strexp may also
be used)

When the "INCLUDE" path is set from within the assembler, it is
restored to its original value on completion.

.OBJFIL "file" ;Split / re-define object file
.OBJFIL INTELHEX16 ;set output format to INTEL HEX 16
(PIC only)
.OBJFIL INTELHEX8M ;set output format to INTEL HEX 8M
(PIC only)

The first occurrence of the .OBJFIL directive re-defines the name of
the object file produced by the assembler. Output may also be
redirected to a device (eg. COM1) allowing the assembler to output
directly to an emulator or EPROM programmer.

(C)1993 Don Lekei

Assembler Directives 35

If a second .OBJFIL directive is encountered, the object file will be
split at that point, and continued in the new file. You cannot
continue adding to the old file, since a HEX format file has a special
end sequence which would make concatenating them useless.

With ASPIC, the OBJFIL directive may also be used to specify the
output file format for 16bit data.

.SETENV "envlabel=",strexp ;Set environment variable

The .SETENV directive allows you to set or change DOS environment
variables from within the assembler. The new environment is passed to
child processes (called with the .SHELL directive, but the original
environment is restored upon completion of the assembly.

Environment variables can also be a convenient and powerful way to
transfer and hold string information within a source file. Within a
source file, environment variables may be evaluated with the ENV()
function, or used within string expressions with the "#" sign (see
also sections 3.3. and 2.3.).

.SHELL command line ;Execute external dos command
.SHELL "",strexp ;Execute external dos command

The .SHELL directive allows a source file to invoke an external DOS
command (a child process). If the command is not found in the DOS
PATH, or if DOS piping or redirection is used, then a copy of the
command interpreter specified by COMSPEC is invoked to handle the
internal DOS commands.

The return code (as in errorlevel) is available in the variable
.._err. Due to a limitation of DOS, ..err contains no useful
information when a copy of COMMAND.COM is invoked, so no error is
returned if the command is in error, or the external command is not

The functions EXIST() and NEWER() are also useful when interfacing
with DOS (see section 2.4.6.).

3.11 Listing control directives

.COL width ;Set printer width for symbol table

.LINE length ;Set lines per page

.LIST ON ;Listing on

(C)1993 Don Lekei

36 Macro+ Assembler Version 5

.LIST OFF ;Listing off

The .LIST directive turns the assembly listing on and off. The
variable clop_l will be defined to 1 if the -L option was selected
from the keyboard. This may be used in conditional assembly.

.PAGE [< maxskip,]["title"][,n] ;New page and/or title

The .PAGE directive allows you to change the main title on the
assembly listing and/or force a new page. If the ",n" option is
specified, it causes the control characters for the bold title and
compressed main text to be suppressed.

If the optional number of lines is specified, the page will only be
fed if there are less than that many lines left on the page. For

.PAGE <10

will feed the page if there are less than 10 lines left on the page.

.COUNT on ;Cycle count on / total
.COUNT off ;Cycle count off
.COUNT cont ;Cycle count continue / total
.COUNT ;Cycle count reset

The cycle count for each instruction is normally printed in brackets
to the left of the source code column on the assembly listing. If an
instruction may be skipped as a result of the previous instruction,
the number of cycles if skipped is printed in parentheses beside the
normal cycle count.

Any time a program jump or a return instruction is encountered, the
total number of cycles is printed, and reset to 0. The .COUNT
directive gives you control over this feature. With this directive you
can turn the counting off (.COUNT OFF), resume counting or print a
sub-total (.COUNT CONT), or reset the total to 0 (.COUNT). Normally,
though, the automatic totalling should be adequate.

.MXP [on] ;Macro listing expansion on
.MXP off ;Macro listing expansion off

Macro expansion is normally on, unless a macro is defined with an
asterisk before parameter list. The .MXP directive allows you to
globally disable macro expansion.

If a .MXP directive is encountered within a macro, its scope is only
to the end of the macro, then the previous setting is restored.

(C)1993 Don Lekei

Assembler Directives 37

When a macro is expanded with MXP off (or *), the invocation line is
not printed until the macro is completed (so all of the object bytes
have been collected).

.IXP [on] ;Display skipped conditional code
.IXP off ;Don't display skipped code

Normally, lines not assembled due to conditional assembly are marked
with an "s" on the assembly listing. If .IXP OFF is in effect, lines
which are not assembled are not printed.

(.NOLIST) (same as .LIST OFF)
(.PRINT) (same as .LIST)
(.TITLE) (same as .PAGE)
(.EJECT) (same as .PAGE)
(.SKIP) ;Blank line unless at

3.12 Assembler control directives

.BANK bank ;define register bank assumption
(ASPIC only)

This directive allows the programmer to define what value to assume is
in the file bank control bits for 16C57, 16C71, 16C84, and 17C42
CPU's. The assembler will automatically generate bank changes as
required for 16C71 and higher processors. It will track the value in
the RP0 bit (71/84) or BSR (42) as long as it is DIRECTLY modified.
If it's value is modified indirectly, the .BANK directive should be

Since there is no way to directly set the bank in the 16C57, only
warnings are generated. The current bank assumption may be read with
the BANK() function.

Bank tracking may be prevented by using ".BANK -1".

.VDEF ram page ;Define V register page (AS10 only)

The .VDEF directive assigns a value to assume for the V register. This
allows working register addresses to be given as labels to actual
memory locations. It also provides a reference point for bit-labels.

The page may be specified with either the actual address (in which
case the high byte is used) or as the page number (0-$FF).

.CPU 78C10 ;Allow CMOS instruction set
.CPU 7810 ;Use NMOS instruction set

(C)1993 Don Lekei

38 Macro+ Assembler Version 5

.CPU 50747 ;select microprocessor
.CPU 50734
.CPU 37450 ;mul, div
.CPU 6502N ;nmos 6502 base set only.
.CPU 16C54 ;select different models
.CPU 16C55 ;select different models
.CPU 16C56 ;select different models
.CPU 16C57 ;select different models/regs
.CPU 16C71 ;extended instructions/regs
.CPU 16C84 ;extended instructions/regs
.CPU 17C42 ;extended instructions

These select the CPU to be supported (defaults are 78C10(as10),
16C54(aspic), 50747(as74)). For example, the .CPU 7810 directive
causes the assembler to reject the ZCM register and the STOP instruc-

.SYNTAX FULL ;Allow full syntax
.SYNTAX OLD ;Warn of incompatible syntax

The .SYNTAX option will force the assembler to be wary of possible
portability conflicts when porting code from another assembler. This
directive should not be used once the code is fully converted to the
Macro+ assembler.

(C)1993 Don Lekei

Appendix A 39

Appendix A: Errors and Warnings

Normal Errors

Error: Bad RPA mode '???'
An illegal Register Pair Addressing mode was used (eg.
LDAX C++).

Error: Bad address mode
The operand format is not compatible with the opcode.

Error: Bad label
The label contains invalid characters. A label must begin with
a letter, underscore, period, or (local labels) an opening

Error: Bit address range
The high byte of a bit label address must either be 0, or
equal to the current setting of VDEF.

Error: Bit range
The requested bit number exceeded 8 in a bit instruction or 16
in an evaluated expression.

Error: Branch out of Range
The address is outside of the branch range of the instruction.

Error: Buffer not empty
In 4-to-3 packing with .PK43L, data was left from a previous
packed string, making the length value invalid.

Error: Can't evaluate expression
An expression contains invalid characters or missing

Error: Can't set '???'
A .SETENV directive was not able to create, change or delete
the requested environment variable.

Error: Character set overflow
An attempt was made to define a CSET with more than 256

Error: Code 32 reserved
In 3-to-2 packing with a 64 character CSET, characters 0 and
32 are reserved as shift characters.

Error: Code >32
If character 0 of the .PK32 CSET is defined, then only the

(C)1993 Don Lekei

40 Macro+ Assembler Version 5

first 32 characters of the CSET are available in 3-to-2

Error: Code >64
In either 3-to-2 or 4-to-3 packing, only the first 64
characters of the current packing CSET may be used.

Error: Duplicate Parm in definition
A macro has the same explicit parm ([0]...[9]) defined more
than once on the definition line.

Error: Forward reference in bit # '???'
A bit label has a forward reference in the bit value. This may
cause it to be misinterpreted later.

Error: Invalid string operation
The operator in a STRCMP() function is invalid.

Error: Invalid table address
An attempt was made to access a CSET entry >256.

Error: Label '???' redefined
A normal label was redefined to a different value. Use the SET
directive or, preferably, define the label as a variable (use

Error: Label too long
A label name is longer than 15 characters.

Error: Long branch out of range
A long branch exceeds +-256.

An error in the macro definition was detected when the macro
was invoked.

Error: MACRO definition parm
An error in a macro parameter definition was detected when a
line of the macro was being expanded.

Error: MACRO definition syntax
There is an error in the macro definition which was detected
when a line of the macro was being expanded.

Error: Macro Name
The macro name contains invalid characters.

Error: Macro expansion
A line of a macro would become to long if expanded.

(C)1993 Don Lekei

Appendix A 41

Error: Missing ')' in function '???'
The last delimiter in a function macro must be ')'.

Error: Missing ']'
A local variable name has no trailing bracket.

Error: Missing delimiter
A character or string does not end with the same type of
quotation mark (single or double), or a character constant is
longer than 2 characters.

Error: Missing delimiter in Macro
A macro line does not have balanced quotation marks.

Error: Missing parenthesis
An expression does not have the same number of opening and
closing parenthesis.

Error: More than 10 parms in definition
The macro definition contains more than 10 named parameters.

Error: No RPA addressing mode
No parameters were given for an instruction which expects
Register Pair Addressing.

Error: No active PK32 set
A .PK32 or .PK32X directive was given before the translation
set was declared.

Error: No active PK43 set
A .PK43 or .PK43L directive was given before the translation
set was declared.

Error: No active character set
An attempt was made to add to or modify the current CSET when
none is active.

Error: No char
There is nothing after a quotation mark in an expression.

Error: No digits
There are no digits in a binary or octal expression.

Error: No label to assign
There is no label to the left of an "=" or .EQU directive.

Error: No name
No name was given for a macro or .CSET definition.

(C)1993 Don Lekei

42 Macro+ Assembler Version 5

Error: Not a register pair
The register given is not a register pair.

Error: Octal numbers 5 digits max
An octal number exceeded 5 digits.

Error: PC overflow
Code is generated before the assembly address is defined, or
the program counter has wrapped from $FFFF to 0.

Error: PK32 set not defined
An attempt was made to generate 3-to-2 packed text using an
undefined CSET.

Error: PK43 set not defined
An attempt was made to generate 4-to-3 packed text using an
undefined CSET.

Error: Range
An expression is outside the valid range for the opcode or
function (remember that you must take the low byte of negative
byte values).

Error: Redefined Macro '???'
An attempt was made to define two macros with the same name.

Error: Redefined character set '???'
An attempt was made to define two CSETs with the same name.

(C)1993 Don Lekei

Appendix A 43

Error: Short branch out of range
A short branch exceeded +-32 bytes.

Error: Special page range
The high byte of the working register address did not match
the current setting of VDEF.

Error: Syntax
An expected character was not found.

Error: Syntax mode
An invalid syntax mode was specified in .SYNTAX or the
directive is not available in the current mode.

Error: Syntax mode conflict
A directive was used which may indicate improper syntax
parsing based on previous coding patterns.

Error: Undefined character set '???'
An attempt was made to reference a CSET which has not been

Error: Undefined function '???'
A function macro which has not been defined was used in an

Error: Undefined label '???'
A label was referenced which has not been defined by pass 2.

Error: Undefined macro '???'
The opcode does not match any machine instruction, assembler
directive, or defined macro.

Error: Unexpected EOF
The end of the current file was encountered before the
expected .ENDIF, .ENDM, or .LOOP directive. This error will
also occur if a DO loop or macro ends without completing the

Error: Unexpected End of Macro
The end of the macro was encountered before the expected
.ENDIF directive.

Error: Unrecognized CPU
The .CPU directive was given a CPU not supported by this
version of the assembler.

Error: Unterminated DO...LOOP within Macro
The number of .LOOP directives did not match the number of .DO

(C)1993 Don Lekei

44 Macro+ Assembler Version 5

directives in the macro definition.

Error: Unterminated IF or SWITCH within LOOP
The number of .ENDIF directives did not match the number of
.IF and .SWITCH directives in the .DO loop definition.

Error: Unterminated IF or SWITCH within Macro
The number of .ENDIF directives did not match the number of
.IF and .SWITCH directives in the macro definition.

Error: Unterminated MACRO DEFINITION within LOOP
The number of .ENDM directives did not match the number of
.MACRO directives in the .DO loop definition.

Error: Value overflow
A hex number exceeded 4 digits.

Error: Value range
An attempt was made to use a value outside the valid range for
an instruction.

Error: Wrong CPU
An instruction, addressing mode or register was used which is
not valid for the current CPU.

Fatal Errors

Fatal Error: Bad input
A [KBD], ENV(), or command line parameter was given which
could not be evaluated, or contained a forward reference.

Fatal Error: Can't create '???'
The requested file could not be opened for writing.

Fatal Error: Can't open '???'
The requested file could not be opened for reading or for

Fatal Error: Division by zero
An expression attempted to divide by 0.

Fatal Error: Does not match Pass 1 value
The value of a label during pass 2 was not the same as during
pass 1. This means that a different number of bytes were
generated on pass 2 than pass 1, or SET and = (or EQU) were
used interchangeably on the same label. Variables (..NAME)
will avoid this error.

Fatal Error: File

(C)1993 Don Lekei

Appendix A 45

An error occurred accessing a file.

Fatal Error: File '???' not found
A .INCLUDE directive tried to read a file not in the active
directory or the INCLUDE path.

Fatal Error: Forward reference
A directive could not be processed on pass 1 because the
expression contained a forward reference.

Fatal Error: Label too long
A label exceeded 15 characters and could not be processed.

Fatal Error: No bytes
A CSET definition had no valid data.

Fatal Error: Opcode too long
The length of the opcode field or macro name exceeded 15

Fatal Error: Out of memory
No more memory to store macros, labels, character sets, etc.

Fatal Error: Ran out of input
An end of file was encountered while using redirected input to
a [KBD] definition.

Fatal Error: String overflow
A string expression evaluated to more than 127 bytes.

Fatal Error: Symbol table full
Same as out of memory.

Fatal Error: Syntax
A syntax error occurred in a place which would prevent
meaningful processing of the rest of the file.

Fatal Error: Too many bytes requested
An offset into a CSET exceeded the end of the set.


The following warnings ar not actually errors, but they flag
suspicious constructs which may, in fact, be subtle errors. It is not
a wise idea to ignore these warnings. All can be avoided with proper

Syntax undefined - high byte used
Some functions in the code indicated that the code might have

(C)1993 Don Lekei

46 Macro+ Assembler Version 5

been written for an assembler which used "<" to indicate the
high byte, while others did not. The assembler has therefore
used the convention ">" = high byte and warned that it should
be checked.

Warning: Syntax mode undefined - low byte used
Some functions in the code indicated that the code might have
been written for an assembler which used ">" to indicate the
low byte, while others did not. The assembler has therefore
used the convention "<" = low byte and warned that it should
be checked.

Warning: Value suspect
A decimal value has more than 6 digits. It is probably a
binary value missing the "%" or "B".

Warning: Value truncated
A byte-oriented command (such as .BYTE or .TEXT) has encoun-
tered a word value and discarded the high byte. This warning
may be avoided by explicitly using the high byte (">") or the
low byte ("<") of the value.

(C)1993 Don Lekei

Appendix A 47

Appendix B: Assembler Directives Alphabetically

*= (or * =)Set Program Counter
= Equate a label to a value
.BANK Define file bank assumption (ASPIC only)
.BYTE Byte/string data (untranslated)
.CASE Next case in SWITCH/CASE/ELSE/ENDIF conditional
.CHK Place vertical parity equalization byte into code
.COL Set printer width for symbol table
.COUNT Cycle count control
.CPU CPU selection
.CSET Define/set character set for text translation
.DATA Define data size assumption (8/16) (AS77 only)
.DBYTE Double-Byte data (H,L)
.DWORD Double-Word data (4 bytes L...H)
.DO Start of repeated code
.DS Define storage block (no bytes generated)
.ECHO Print line to console or file
.ELSE End of case in conditional assembly
.END Forced end of level (File, Macro, or Compile)
.ENDIF End of conditional assembly
.ENDM End of macro definition
.EQU Equate (same as =)
.ERROR Force error or set error output file.
.EXITM Forced end of level (Same as .END)
.EXT Declare label as externally defined (not defined in
this source)
.FATAL Force fatal error or set error output file.
.FILL Fill memory range with a repeated byte
.GLOBAL Declare a label as global - for export
.IF Initiate IF/ELSE/ENDIF conditional assembly
.INCLUDE Include external file
.INDEX Define index size assumption (AS77 only)
.IXP IF listing expansion control
.LINE Set lines per page
.LIST Listing on/off
.LOOP End of repeated code (see .DO)
.LWORD Long word data (3 bytes L...H)
.MACRO Macro definition
.MXP Macro listing expansion control
.OBJFIL Split / re-define object file
.ORG Origin (ASSEMBLY address but NOT OBJECT address)
.PAGE New page and/or title
.PK32 Packed (3-to-2): characters
.PK32X Packed (3-to-2): with end flag (spare bit set)
.PK43 Packed (4-to-3): characters
.PK43L Packed (4-to-3): length (0-63), characters

(C)1993 Don Lekei

48 Macro+ Assembler Version 5

.SET Redefine a constant
.SETENV Set environment variable
.SHELL Execute external dos command
.SWITCH Initiate SWITCH/CASE/ELSE/ENDIF conditional assembly
.SYNTAX Syntax option OLD / FULL
.TEXT Translated: character data
.TEXTL Translated: length,characters
.TEXTX Translated: last character exclusive-or $80
.TEXTZ Translated: charters,0
.VDEF Define V register page (AS10 only)
.WARN Force warning or set error output file.
.WORD Word data (low,high)
.XTABLE Put CSET to CSET translation table into code
.ZMB Fill memory range with 0 (same as .FILL 0,)

Additional directives provided for syntax compatibility:

(.BLKB) (same as DS) sets OLD syntax mode
(.DB) (same as .BYTE)
(.DW) (same as .WORD)
(.EJECT) (same as .PAGE)
(.NOLIST) (same as .LIST OFF)
(.PRINT) (same as .LIST)
(.SKIP) Blank line unless at top-of-page
(.TITLE) (same as .PAGE)

(C)1993 Don Lekei

Appendix C 49

Appendix C: Assembler Directives by Function

Data definition:

.BYTE Byte/string data (untranslated)
.WORD Word data (low,high)
.DBYTE Double-Byte data (H,L)
.DWORD Double-Word data (4 bytes L...H)
.LWORD Long word data (3 bytes L...H)
(.DB) (same as .BYTE)
(.DW) (same as .WORD)

Special data:

.CHK Place vertical parity equalization byte into code
.FILL Fill range with a repeated byte
.ZMB Fill range with 0 (same as .FILL 0,)

Translated data:

.CSET Define/set character set for text translation
.XTABLE Put CSET to CSET translation table into code

.TEXT Translated: character data
.TEXTZ Translated: charters,0
.TEXTX Translated: last character exclusive-or $80
.TEXTL Translated: length,characters

Packed data:

.PK32 Packed (3-to-2): characters
.PK32X Packed (3-to-2): with end flag (spare bit set)
.PK43 Packed (4-to-3): characters
.PK43L Packed (4-to-3): length (0-63), characters


= Equate a label to a value
.EQU Equate (same as =)
.EXT Declare label as externally defined (not defined in
this source)
.GLOBAL Declare a label as global - for export
.SET Redefine a constant

Address control:

*= (or * =) Set Program Counter
.ORG Origin (ASSEMBLY address but NOT OBJECT address)
.DS Define storage space (no bytes generated)

(C)1993 Don Lekei

50 Macro+ Assembler Version 5

(.BLKB) Byte data (same as DS) sets OLD syntax mode

Conditional assembly:

.IF Initiate IF/ELSE/ENDIF conditional assembly
.ELSE End of case in conditional assembly
.ENDIF End of conditional assembly
.CASE Next case in SWITCH/CASE/ELSE/ENDIF conditional
.SWITCH Initiate SWITCH/CASE/ELSE/ENDIF conditional assembly

Macros and User-Defined Functions:

.MACRO Macro definition
.EXITM Forced end of level (Same as .END)
.ENDM End of macro definition
.DO Start of repeated code
.LOOP End of repeated code

System and file control:

.SHELL Execute external dos command
.SETENV Set environment variable
.ECHO Print line to console or file
.ERROR Force error or set error output file.
.FATAL Force fatal error or set error output file.
.WARN Force warning or set error output file.

.INCLUDE Include external source file
.END Forced end of level (File, Macro, or Compile)
.OBJFIL Split / re-define object file

Listing control:

.LIST Listing on/off
.PAGE New page and/or title
.LINE Set lines per page
.COL Set printer width for symbol table
.COUNT Cycle count control
.MXP Macro listing expansion control
.IXP IF listing expansion control
(.NOLIST) (same as .LIST OFF)
(.PRINT) (same as .LIST)
(.TITLE) (same as .PAGE)
(.EJECT) (same as .PAGE)
(.SKIP) Blank line unless at top-of-page

Assembler control:

(C)1993 Don Lekei

Appendix C 51

.BANK Define file bank assumption (ASPIC only)
.BANK() Returns current assumed bank (ASPIC only)

.DATA Define data size assumption (8/16) (AS77 only)
.INDEX Define index size assumption (AS77 only)
.DP Define direct page assumed value (AS77 only)
.DT Define data bank assumed value (AS77 only)
.VDEF Define V register page for working-register instructions (AS10
data() Function to return the current assumption (as77 only)
index() Function to return the current assumption (as77 only)
dp() Function to return the current assumption (as77 only)
dt() Function to return the current assumption (as77 only)

.CPU CPU selection
.SYNTAX Syntax option OLD / FULL

(C)1993 Don Lekei

52 Macro+ Assembler Version 5

Appendix D: Converting From Other Assemblers

There are a few minor differences between the syntax of some other
assemblers and the MACRO+ assembler which should be taken into account
when converting source code files.


There are two main ways of getting code to execute on a system: LOADER
modules, and LOAD modules. A LOADER module reads in the code under the
control of an operating system, and distributes code and data to the
appropriate areas.

A LOAD module places the code into a fixed block of memory, then the
code itself must move any sections which must be in other areas. A ROM
is an example of a LOAD module; any sections which are not in the
right place (such as RAM initialization) must be moved to another

In a LOAD module assembler, there can only be ONE "true" ORG
statement. Any sections of code with other ORGs (operating address)
must be relocated by the code.

Some other assemblers use the ORG statement to move the program
counter around. So these ORG statements should all be changed to "*=".

Using your word processor (or SED, if you have it available) change
all ORG directives to "*=". The first ORG may be either ORG or *=.

$ and *

The "$" symbol indicates the program counter in many assemblers. This
assembler uses the "*" symbol. "$" is processed correctly, but it
produces a warning because it may be a null HEX number.

CASE sensitivity

One other assembler allows case insensitive labels. If a label is
defined in upper case, then used in lower case, the cases will need to
"Label" OR "label".


The operators for logical functions are symbols, not words. The
following operators should be substituted:


(C)1993 Don Lekei

Appendix D 53

====== ==
OR |
SHR >>
SHL <<

Note lso that precedence does NOT exist between normal operators in
this assembler, so parentheses may be needed to enforce precedence in
a few cases.


This assembler allows post-fix (0c9H, 11001001B) notation or prefix
($C9, %11001001, @311) notation to be used. The use of prefix notation
will reduce assembly time since the assembler knows in advance, what
base it is working in.

If assembly directives are preceded by a "." the assembler will be
able to process them faster, since it will not bother checking
opcodes, and will then check the assembler directives before checking
the macros.


The program RPFIX is a filter to convert the register-pair
abbreviations (V, B, D, H) to the full names (VA, BC, DE, HL) allowed
by the MACRO+ assembler. This program is provided with AS10. Other
versions of the assembler are provided with a more generic version --

It has an additional option, -t to tidy-up comments and tabs, (like an
'ASM beautifier'). When run with the -t option, source code columns
are aligned, and source-line comments (comment blocks are exempt) are
converted to Upper and lower case. Common acronyms are also parsed
for and capitalized.

For example, the line:


would be converted to:

LXI HL,LAMPS ;Point HL to LED buffer base

It is used as a filter, so if you do not redirect output, it will
merely display the converted file to the screen. A little help is
available by just typing the word RPFIX. The normal usage of RPFIX is:

(C)1993 Don Lekei

54 Macro+ Assembler Version 5

TYPE sourcefile | RPFIX [-t] > sourcefile



(C)1993 Don Lekei

Appendix B 55

Appendix E: CPU Specific Enhancements - PIC

E.1 Data / Strings

Data and string directives (.TEXT, .BYTE, .PK32, .PK43 and
derivatives) geterate strings of RETLW instructions, since there is no
other way to read data tables from ROM due to the strict Harvard
archetecture constraints. This feature is not active when the 17C42
CPU is selected.

E.2 Enhanced Instruction Set

The instruction set has been enhanced to support most of the alternate
syntax sypported by the manufacturer's assembler. The pseudo-
instructions which produce variable code or multiple register access
have not been supported, since the use of macros is more maintainable.
These functions can, of course, be completely replaced by macros.

A utility, "PICTAB", is provided which will printout the entire
register and instruction set for each of the base cpu settings (i.e.
16C54, 16C71, 16C84, 17C42).

Several additional instruction mnemenonics have been added for your
convenience, mainly to enhance the functionality of bit-labels. For
example BBS and BBC expand to two instructions each (test and goto).

If any of these compound 'instructions' is in a position to be
skipped, a warning will be generated.

E.3 Model Specific Resource Limits

Model specific resource limits can be more flexibly supported via the
segment macros. This permets full segment overflow checking, while not
putting westrictions on lables which may be necessary for other
functions such as external system reference.

E.4 Output Files

To support the simulator, the file with .SYM extension is a symbol
transfer file in the simulator's format. To fix a bug in the
simulator, symbol types are tentatively defined. To force the
assembler to send the appropriate symbol types to the simulator, you
can add a double colon after the first lable in code (eg: LABEL::) to
force a code label, or change the program counter without assigning
code (eg. * = *) to force a file definition).

The Transfer file, which would normally have the extension ".SYM" is
now called ".XFR".

(C)1993 Don Lekei

56 Macro+ Assembler Version 5

E.5 Assembler Test Files

To aid in learning the syntax of this assembler, the program
TESTPIC.EXE is provided for your convenience. It will generate a test
source file for the selected processor (TESTPIC -? for help) to
standard output.

(C)1993 Don Lekei


.._err 9 .MXP 28, 36
.._hour 9 .NOLIST 37
.._index 10 .OBJFIL 34, 35
.._month 9 .OLDSEG 23
.BANK 37 .ORG 21-23, 29
.BLKB 21 .PAGE 36
.BYTE 15, 18, 23, .PK32 18, 19
32 .PK32X 18, 19, 23
.CASE 15, 24, 25 .PK43 18
.CASE (other) 25 .PK43L 19
.CASE(other) 25 .PRINT 37
.CHK 16 .SEG 23
.COL 35 .SET 7, 21
.COUNT 36 .SETENV 34, 35
.CPU 37 .SHELL 35
.CSET 16 .SKIP 37
.DB 15 .SWITCH 15, 24,
.DBYTE 15 25
.DO 15, 26, 32 .SYNTAX 38
.DS 21, 23, 29 .TEXT 18, 27
.DW 15 .TEXTL 18
.ECHO 6, 9, 32, 33 .TEXTX 17, 18
.ELSE 15, 24-26 .TITLE 37
.VDEF 23, 37
.END 26, 32 .WARN 33
.ENDIF 15, 24-26 .WORD 15
.ENDM 26, 28-30 .ZMB 16
, ' 22
31, $ 52
32 * 52
.EQU 7, 21 * = 21
.ERROR 6, 33 *= 21, 52
.EXITM 28, 32 _day 9
.EXT 20 _FILE 14
.FILL 16 _hour 9
.IF 15, 24, 27 _minute 9
.INCLUDE 5, 33, 34 _month 9
.LINE 35 _TIME 14
.LIST 35 _year 9
.LOOP 15, 26, 32 1's complement 11
.MACRO 7, 26, 28, 2's complement 11
29, 3-to-2 packing 18
31, ,
32 19

(C)1993 Don Lekei

4-to-3 packing 19 14, 34
Addressing mode 11 Environment variab
AND 53 le
As 37 s
Ascii 10, 14 14
Bank changes 37 EOS 28
Base notation 10 EPROM 22, 34
Binary 10 Error channel 6
BIT 20 Errorlevel 9
Bit-labels 20 EXIST( 13, 35
Bold 36 Expression 10
Boolean operators Expression evaluat
12 io
Brackets 8 n
CALT 30 10
Case 7, 8, 13, 52 Forward references
CHR( 12 24
Clop_ 9 Function 10
Clop_i 9 Function macros
Clop_l 9, 36 14
Clop_s 9 ,
Clop_x 9 26
Command line 4, 34 ,
Comment-only lines Hex 10, 35
7 INCLUDE 4-6, 8,
Conditional assembl 34
y Input 20
24 Intel HEX format
Console 32 4
Constant 10 INTELHEX16 34
CSET. 17 ISDEF( 13
Decimal 10 ISDEF() 25
Default extension Label 7, 10
34 Label names 8
Delimiter, 28 Linking 4
Directives 8, 14, Local labels 8
15 LOCAL variable 8
DO loop 10 Local variables 8
DO loops 31 LOOP 15
DOS 9, 14, 35 Loop index 10
DOS command line Loops 26
20 MACRO 8, 37
Ellipsis 19 Macro labels 27
ENV( 12 Macro nesting 26
Environment variabl Macro parameters
e 8
9, Macros 7, 15, 26

(C)1993 Don Lekei

MAX( 31 SHL 53
Memory 22 SHR 53
Microprocessors 2 Skipped code 24
MOD 53 Source code 4
NEWER( 13, 35 Standard input 5
NEWLINE 8, 28, 33 Standard output 5
Non-printing charac STOP 38
ter STRCMP( 13, 14
s String expression
8 14
NULL 8, 13 String operations
Object code 4, 22 13
Object file 6 Syntax compatibili
Octal 10 ty
Opcodes 7 15
Options 5 System-defined var
OR 53 ia
ORG 22, 52 bl
Origin 21 es
Parentheses 10, 53 9,
Pass number 9 10
PATH 14, 34 ,
PATH, 35 25
Paths 34 TAB 28
Piping 5, 35 Tabs 8
Post-fix 53 Text editor 7
Precedence 53 Time 9
Prefix 10, 53 Timestamp 9
Program Counter 21 TSUB 30
Pseudonyms. 27 Unary operators
Quotes 27 10
RAM 22 ,
Redefine a constant 11
21 User-Defined Funct
Redirection 5 io
Register-pair names ns
3 26
Regular macro 28 User-defined optio
Regular macros 26 ns
Relational operator 5,
s 9
12 Variable 8
Return code 9, 35 Variables 21
ROM 22, 52 Warning 10
SEG macro 22, 23 ZCM register 38
SEGMACS.ASI 21, 27 [KBD] 20, 33
Select 13
SET 34

(C)1993 Don Lekei

 December 6, 2017  Add comments

 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>