home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
mbug
/
mbug113.arc
/
ZASM.DOC
< prev
Wrap
Text File
|
1979-12-31
|
30KB
|
960 lines
ZASM ASSEMBLER USER INFORMATION
-------------------------------
FOREWORD
--------
This documentation assumes that the reader has some familiarity with
assembly language for the Z-80: it is not a primer. The best Z-80
assembly language book that I have found is Rodnay Zaks' "How to Program
the Z-80". Another excellent book to supplement it is "Z80 Assembly
Language Subroutines" by Lance A. Leventhal and Winthrop Saville.
There are also occasional references herein to the standard CP/M
assembler ASM. For example the DL pseudo of ZASM is compared to the SET
statement of ASM. Many of the pseudo instructions are the same or
similar in the two assemblers, although ZASM is far more powerful.
Finally two note on the examples in this file:
* They have NOT all been tested and I do make mistakes.
* They have been written in uppercase only to make them stand out.
There seems to be a covenant among assembler language programmers to
do everything, except comments, in uppercase. The fact is that, as with
any other programming language, lowercase is easier to read and
comprehend. ZASM will accept either case.
GENERAL
-------
ZASM is a Macro Assembler for the Z-80 instruction set. It recognizes
Zilog Z-80 instruction mnemonics and produces either .HEX or .REL
(Microsoft standard) output. In short, it is a very powerful and very
cheap (free) assembler. Found on a CP/M bulletin board without
documentation, these notes are based on a disassembly as well as
experimentation. There is no guarantee that they are entirely accurate
or comprehensive.
Some features of note in ZASM are:
* The assembler builds a symbol table in pass one. In pass two the
listing and code are generated. Because of its two pass nature, forward
references in EQU and DL statements are permitted although they may
result in 'Error in Pass 1' messages.
* Conditional assembly (IF/ELSE/ENDIF) nested to eight levels is
permitted.
* Macros including REPT, IRP and IRPC. Nesting to eight levels is
permitted. Macro libraries are supported.
* Include file nesting to four levels. Files may be included on pass
one only if desired.
* Up to 15 named common blocks are allowed.
* Library search directives are allowed.
* Identifiers may include the special characters $ @ _ ? . which are
regarded as significant. Names must begin with a letter or special
character and may contain digits thereafter.
* Names are considered significant to eight characters BUT only
seven characters are written to a .REL file and hence passed to the
linker. Hence only seven characters can be trusted if you are linking
several modules. Furthermore, I am told that L80 (a Microsoft product
only uses six characters so that identifiers differing only in the
seventh character will look the same to it.
COMMAND LINE
------------
The source file name must have the .Z80 extension. The command line is
then of the form:
ZASM PROG.sol ARG1 ARG2 ...
where the allowable arguments are given below and the letters 'sol' are:
s - Source device. This must be a disk drive in the range A-H.
o - Output device. This must be:
Z no output
A-H disk for output (.REL or .HEX)
l - List device. This must be:
X console
Y printer
Z no listing
A-H disk for .PRN file
An exception to the above rules is that if any of 'sol' are blank, the
default disk drive is assumed. Hence:
B>A:ZASM PROG = A:ZASM.BBB
B>A:ZASM PROG.A = A:ZASM.ABB
B>A:ZASM PROG.BZ = A:ZASM.BZB
Command Line Arguments
----------------------
RANGE Mark instances where JR could be used
PARITY Mark all PE/PO/V/NV conditions (POTENTIAL 8080/Z80 conflict)
XREF Produce a symbol cross reference in listing
NOXREF Don't
SYMB Print a symbol table
PAGE = decno Set page size for listing
TOP = decno Set top of form margin
WIDTH = decno Set page width
TRUNC = decno Set page width and truncate
MACRO = name Specify a macro library to load
COND List conditionals
NOCOND Don't
GEN List macro generated code
NOGEN Don't
TEXT Show all bytes generated by instruction
NOTEXT Show at most four bytes per instruction
LISTON List source code
LISTOFF Don't
OPCODE Produce an opcode cross reference in listing
DEBUG Does nothing but set an unused bit
HEX Produce HEX output rather than REL
HEX = hexno Hex load address (sets HEX also)
DATE = mmddyy Set date for listing
TIME = hhmmss Set time for listing
Instruction Formats
-------------------
The assembler differentiates between the label and the opcode fields by
assuming that the instruction is of one of the following forms:
LABEL: OPCODE PARAMS ;COMMENT
LABEL OPCODE PARAMS ;COMMENT
OPCODE PARAMS ;COMMENT
LABEL: OPCODE PARAMS ;COMMENT
The thing to note is that an identifier that begins in the first column
is assumed to be a label even though it may lack a colon. Hence opcodes,
whether instructions or pseudo-instructions, should be tabbed over at
least one. For example, the statements:
TITLE Test Program
CR EQU 13
will be flagged as errors. They should have been written:
TITLE Test Program
CR EQU 13
Assembler Pseudo Instructions
-----------------------------
The following pseudo instructions require no special prefix characters
as in some assemblers. There are four pseudo instructions, discussed
later, that do require a special asterisk prefix.
In determining how to interpret the contents of the opcode field, ZASM
searches in the following order:
- macro (hence macros may replace builtin opcodes)
- builtin opcodes
Most of these pseudos may not have a label - those that can are shown
explicitly.
ABS Absolute program segment
COM name Common block
CONMSG text Displayed during pass 2 of assembly
DATA Data segment
[lbl] DB bytes Define bytes
[lbl] DEFB bytes Same
lbl DL value Define label - same as SET in ASM
lbl DEFL value Same
[lbl] DM bytes Same as DEFB but sets bit 7 of last byte high
[lbl] DEFM bytes Same
[lbl] DS size Reserves size bytes of storage
[lbl] DEFS size Same
[lbl] DW words Define words (16 bit)
[lbl] DEFW words Same
EJECT Page eject on listing
ELSE Used with IF and ENDIF
[lbl] END [lbl] End statement (optional entry point)
ENDIF Used with IF ELSE
ENDM End of macro (includes REPT IRP IRPC)
ENTRY labels Entry label - same as PUBLIC in RMAC
lbl EQU value Equates label to fixed value (DL for variable)
EXITM Exit from macro before ENDM statement
EXT labels Same as EXTRN
EXTRN labels External labels
FORM Page eject (same as EJECT)
GLOBAL labels Either EXTRN or ENTRY - assembler will decide
IF expr Used with ELSE ENDIF
IRP #a,b,c, Indefinite repeat
IRPC #a,'abc' Indefinite repeat by character
[lbl] JSYS value Strange - RST 1 followed by byte value
LIST params Introduces list options
macnam MACRO #a,#b,... Macro definition
MEND Macro end (same as ENDM)
MEXIT Macro exit (same as EXITM)
NAME name Name module - else same as name of source file
macnam OMACRO #a,#b,... Like MACRO but name shows up in opcode listing
ORG value Origin - set program counter instruction
REL Relocatable code segment
REM text Remarks statement (semicolon just as good)
REPT value Repeat statements
STRUCT value Define data structure
SUBTTL Subtitle for listing
TITLE Title for listing
TITLE2 Same as SUBTTL
Standard Z-80 Mnemonics
-----------------------
The following are the Zilog mnemonics for the Z-80. The reader is
referred to Rodnay Zaks' "How to Program the Z-80" for their syntax.
One special note is that index register offsets are calculated to 16
bits before testing to ensure that they are in the range (-128 to +127).
Hence:
LD A,(IX + 0FFH) is illegal
LD A,(IX + 0FFFFH) is legal, as is
LD A,(IX - 1)
Another note is that conditional jumps and calls have a somewhat
expanded syntax, illustrated below.
JP C, = JP LT,
JP NC, = JP GE,
JP Z, = JP EQ,
JP NZ, = JP NE,
JP PE, = JP V,
JP PO, = JP NV,
JP M, = no other
JP P, = no other
For example:
LD A,SAM
CP 20
JP GE,DEST
means jump if SAM GE 20 - i.e. if A >= 20.
ADC ADD AND BIT CALL CCF CP CPD
CPDR CPI CPIR CPL DAA DEC DI DJNZ
EI EX EXX HALT IM IM0 IM1 IM2
IN INC IND INDR INI INIR JP JR
LD LDD LDDR LDI LDIR NEG NOP OR
OTDR OTIR OUT OUTD OUTI POP PUSH RES
RET RETI RETN RL RLA RLC RLCA RLD
RR RRA RRC RRCA RRD RST SBC SCF
SET SLA SRA SRL SUB XOR
Expressions
-----------
Expressions are evaluated to 16 bits and may use the following operators
as well as parentheses or brackets - i.e. () or []. Mnemonics that
require parentheses such as LD A,(HL) or ADD A,(IX+3) may not use the []
form.
The priorities shown below are such that lower numbers connote higher
priorities. For equal priorities evaluation is left to right.
Unary operators
---------------
OP PRI COMMENTS
+ 1 unary plus
- 1 unary minus
^ 1 2 ^ power (i.e. ^11 is a 16 bit word with bit 11 set)
~ 4 not (ones complement)
NOT 4 not (ones complement)
LOW 8 low byte (high byte set to zero)
HIGH 8 high byte (swap bytes and set new high byte to zero)
Binary operators
+ 3 add
- 3 subtract
* 2 multiply
/ 2 divide
% 2 modulus (e.g. 13 % 5 = 3, 15 % 5 = 0)
& 5 and (bitwise)
| 6 or (bitwise)
>> 2 shift right (e.g. 80h >> 2 = 20h)
<< 2 shift left (e.g. 7h << 8 = 700h)
>= 7 ge
<= 7 le
<> 7 not equal
> 7 gt
< 7 lt
= 7 equal
MOD 2 mod - same as %
SHL 2 shift left - same as >>
SHR 2 shift right - same as <<
AND 5 and - same as &
OR 6 or - same as |
XOR 6 exclusive or - exclusive or (bitwise)
LT 7 lt - same as <
GT 7 gt - same as >
EQ 7 equal - same as =
NE 7 not equal - same as <>
LE 7 le - same as <=
GE 7 ge - same as >=
Expressions may use the $ symbol to refer to the value of the program
counter. In such usage, $ = the PC at the beginning of the line in
question. For example:
START DL $
DS 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
NCHRS DL $ - START ;number of characters
Furthermore, relational operators may be used with character strings
contained in double quotes. E.g.
IF "SAM" < "GEORGE"
is meaningful (and false).
The mixing of types - e.g. absolute, relocatable, external etc in
expressions is usually expressed in a number of complicated rules. A
little common sense will normally suffice to see what will work. For
example, the difference of two internal relocatable references is OK
and will produce an absolute quantity (example - NCHRS above) since
they will be given the same offset at link time. The sum of two such
quantities is a no-no as is multiplication or division involving
non-absolute quantities.
Listing Options
---------------
These can be embedded in the source file in the form:
LIST NOGEN,NOCOND,TEXT
When so embedded, they are overridden by contrary listing options contained in the command line.
GEN NOGEN Macro generated code
ON OFF Source code
COND NOCOND Conditionals (IF/ELSE/ENDIF)
TEXT NOTEXT Complete byte listing
(else max 4 per instruction)
Detailed Discussion of Instruction Mnemonics
--------------------------------------------
ABS This specifies that the following code or data is to be placed
into the absolute program section. The syntax is simply:
ABS
COM This specifies that the following code or data is to be placed
into the common section of the given name. Presumably, common
blocks of the same name declared in different modules will be
assigned the same start address by the linker. The syntax is:
COM BLKNAME
where BLKNAME is a legal identifier of at most seven characters.
CONMSG
------
This is used to generate a message to the console during the second pass
of the assembler. It does not generate any code and can hence not be
used to generate run-time messages. For example:
CPM EQU 1
...
IF CPM = 1
CONMSG Assembly is for CP/M
ELSE
CONMSG Assembly is for non-CP/M system
ENDIF
...
DATA
----
This specifies that the following data is to be placed in the DATA area
by the linker. It is normally used to separate dynamic data from
program code. Such is essential when generating code to run in ROM.
The syntax is simply:
DATA
DB and DEFB
-----------
These are synonyms used to initialize data to given byte values. Note
that if the initial value is meaningless, the DS statement is more
appropriate, simply defining the number of bytes to be reserved.
Examples are:
DB 'THIS IS A STRING WITH A NULL BYTE',0
DB 1,2,3,'SAM',4FH
DL and DEFL
-----------
This is like the SET statement in ASM. In several cases the writer of
ZASM seems to have been relieving himself in a windward direction in his
choice of names. It is used when the same symbol must be assigned more
than one value at assembly time. This is of the greatest importance in
writing macros but is useful elsewhere also. For example:
BASE DL 0
IF NOT STANDARD
BASE DL 4100H
ENDIF
Of course in this case, an IF..ELSE..ENDIF construct would have allowed
the use of EQU rather than DL.
In writing macros it is often necessary to have the value of a label
vary. Two examples follow:
COUNT? MACRO #STRING
N? DL 0
IRPC #Z,#STRING
IF '#Z' = '?'
N? DL N? + 1
ENDIF
ENDM
ENDM
invoked as, say:
COUNT? 'A?BB???C'
IF N?
CONMSG Found some queries.
ENDIF
would set N? to the number of ? characters in the argument string. In
the macro expansion, N? occurs L + 1 times as a label where L is the
length of the string. Futhermore, COUNT? may be invoked at more than
one place. The example seems trivial because anyone can see that there
are several ?'s in the string. The string might itself, however, be a
macro parameter which sometimes contains queries and sometimes does not.
A final example is shown below. The LENGTH macro sets the symbol LEN to
the length of the parameter. For example, after the statement:
LENGTH ABCDEFGHIJKLMNOPQRSTUVWXYZ
the symbol LEN will have the value 26. This macro, like the last,
generates no code - it simply sets a value which may then be used in
expressions in the following code.
LENGTH MACRO #NAME ;length of a string
LEN DL 0 ;initialize to zero
IRPC #Z,'#NAME' ;for each character in string
LEN DL LEN + 1 ;...bump len
ENDM ;end of irpc
ENDM ;end of macro
DM and DEFM
-----------
This is just like DB except that the last byte specified, in a line, has
bit 7 set to 1. The chief usage of this is providing character strings
for use by routines that detect 'end of string' by checking bit 7 rather
than using the more traditional method of following strings by null
bytes. For example, using DM we can write:
DM 'THE LAST BYTE HAS BIT 7 HIGH'
rather than
DB 'THE LAST BYTE HAS BIT 7 HIG','H'+80H
This method of indicating the end of character strings was extensively
used by the writer of ZASM. It is also used in a number of text editors
- for example, in its swap file Perfect Writer sets bit 7 on line feed
characters. Wordstar does a lot with bit 7, even on the end of words.
DEFS and DS
-----------
These are used to specify only the amount of storage needed without
providing initial values. It would be meaningless, for example, to
initialize the contents of a disk input buffer. Areas specified by the
DS statement may or may not be included in the .COM file by the linker.
The syntax is as below:
SAM: DS 128
This assigns the label SAM to the start of a block of 128 bytes. No
assumptions may be made about the initial value of locations specified
by a DS directive. Some linkers will initialize such areas to zero and
other linkers will simply leave garbage in them. Indeed such areas will
not necessarily even be included in the final .COM file.
In this assembler, DS seems to have another function which will be
discussed later under STRUCT.
DEFW and DW
-----------
This is used to reserve and initialize one or more words (16-bit) of
storage. The syntax is:
DW 32,SAM,'AB'
Note that this initializes the second word to contain a pointer to label
SAM.
EJECT and FORM
--------------
These both cause a page eject on the listing.
IF/ELSE/ENDIF
-------------
These are used in conditional constructs which may be nested to a depth
of eight. It is used to control which portions of the program will
actually be assembled. A typical use might be:
KAYPRO EQU 1 ;set your computer to 1, the rest to zero
OSBORNE EQU 0
IBM EQU 0
WORTH: IF KAYPRO
CONMSG This is for a Kaypro - Hurrah !
ELSE
IF OSBORNE
CONMSG This for an Osborne - Why ?
ELSE
IF IBM
CONMSG This is for an IBM - What's that ?
ELSE
CONMSG Improper Computer Definition !
ENDIF
ENDIF
ENDIF
Note that all of that code will only generate one byte of code - in fact
none at all if the CONMSG portion is reached. Note also that the
indents are not necessary - indeed they seem to be uncommon in assembly
programming.
END
---
This is used to mark the end of the source file, but ZASM is not very
picky - if you leave it out it will be assumed. Note that only one
source module is permitted in a .Z80 source file. You cannot stack a
number of modules and separate them with END's. The syntax is:
END or
END ZORK
where ZORK is a label at which you want execution to start. The usage
of this option in CP/M is unclear to me since the CCP always transfers
control to the start of the TPA when a program is run. In other systems
- e.g. RT11 in PDP machines - the start address of a program is not
necessarily its load address.
ENDM / MEND
-----------
These two statements are identical in function. They are used to end
the scope of a MACRO, OMACRO, REPT, IRP, IRPC or STRUCT block of code.
The syntax is simply:
ENDM
ENTRY
-----
This is identical to the PUBLIC statement in RMAC. It is used to inform
the linker which labels in the module are to be made accessible to other
modules. See also the GLOBAL and EXTERNAL statements. The syntax is:
ENTRY LABEL1,LABEL2,...
EQU
---
This is like the DL statement except that once a label is equated to a
value it can not be changed to another value with another EQU or DL.
The EQU statement should be used for values that are truly constant in
the module. The syntax illustrated below:
BDOS EQU 5 or
BUFLEN EQU BUFEND - BUFBEG or
BUFLEN EQU $ - BUFHED
Note that if the labels BUFEND or BUFBEG are defined below the EQU
statement an 'Error in Pass 1' message will occur. It will disappear in
pass 2.
EXITM
-----
This is used to exit from a macro definition before the closing ENDM
(which must still exist). This can be used to simplify logical
structures and perhaps speed processing. For example:
SPCLCH MACRO #CHAR
IRPC #TEST,'._$?@'
IF '#TEST' = '#CHAR'
CONMSG Special character detected.
ENDIF
EXITM
ENDM
EXT / EXTRN
-----------
These synonyms are used to declare labels that are defined external to
the current module. They are used to tell the linker which labels must
be found elsewhere and to ensure the assembler that a value will be
provided for the label at link time. This is the opposite of the ENTRY
statement. For each label shared between modules there should be one
ENTRY statement, in the module defining it, and an EXTRN statement in
each module referencing it. The syntax is:
EXTRN LBL1,LBL2,...
See also the ENTRY and GLOBAL statements.
FORM
----
Same as EJECT.
GLOBAL
------
The GLOBAL statement is provided for sloppy programmers. It can replace
either the ENTRY or EXTRN declaration. If a label is declared GLOBAL
and the assembler detects it's definition in the current module, it is
assumed to be an ENTRY (public) label. If the assembler does not find
it defined in the current module, it assumes the label to be of EXTRN
type. Using GLOBAL thus short-circuits any chance the assembler might
have had of detecting a typo. Furthermore it makes it very hard for the
programmer to find where a shared label is defined: he has to scan the
code of every module in which the label is declared GLOBAL. If the
ENTRY and EXTRN declarations are used instead, it is only necessary to
scan the ENTRY statements to see which module contains the definition.
IRP
---
This is a special predefined macro and hence takes up one nesting level
and requires an ENDM statement. The IRP stands for 'indefinite repeat'.
The usage is illustrated below as is the ability to compare strings:
POPEM MACRO #R1,#R2,#R3,#R4,#R5,#R6
IRP #REG,#R1,#R2,#R3,#R4,#R5,#R6
IF "#REG" NE ""
PUSH #REG
ELSE
EXITM
ENDIF
ENDM
ENDM
An invocation POPEM HL,BC,IX will expand to
POP HL
POP BC
POP IX
You may prefer the one liner, but remember to pop in reverse order to
pushing. A second example follows:
IRP #ADDR,BUF1,BUF2,BUF3,BUF4
#ADDRP: DW #ADDR
DS 128
ENDM
This will be expanded into:
BUF1P: DW BUF1
BUF1: DS 128
BUF2P: DW BUF2
BUF2: DS 128
BUF3P: DW BUF3
BUF3: DS 128
BUF4P: DW BUF4
BUF4: DS 128
The #ADDR above is a dummy parameter which will take on the macro
equivalents BUF1, BUF2, etc once each.
This example also illustrates a very important consideration with
respect to macro parameter matching. The assembler matched the first
characters of #ADDRP with the parameter #ADDR and assumed that the rest
must be a literal character - i.e. one to be left as is.
IRPC
----
This is very similar to IRP except that the dummy parameter takes on
only on character on each repeat. The syntax is illustrated below in
which the example shown for IRP above is done by an IRPC instead:
IRPC #N,'1234'
BUF#NP: DW BUF#N
BUF#N: DS 128
ENDM
The characters in the substitution string need not be digits.
JSYS
----
This seems a bit strange. I suspect it is a hold over from ZASM used
with some other operating system. It seems as if the syntax:
JSYS BYTVAL
generates the machine instructions:
RST 1
DB BYTVAL
This would be meaningful if location 0008H contained a jump to some code
which would retrieve the BYTVAL, do something with it, and then return
control to the address following BYTVAL (or maybe perform an error exit).
LIST
----
This is used to switch listing options on and off at assembly time. The
listing options have been given above. Note that listing options
specified in the command line override those specified in the source
code. Hence you cannot 'hide' a piece of code - that is, prevent it
from showing up in a listing.
MACRO
-----
The MACRO keyword is used to specify a macro - surprise. Formal
parameters in ZASM begin with a # symbol rather than the ? symbol used
in RMAC. Note that in ZASM, the query is a legal identifier character
instead. This is not a treatise on macros but a few examples below will
demonstrate some simple uses. The macro definition is given only once,
and may even be hidden away in a file called a macro library. It can
then be invoked as often as desired with different actual parameters.
Note that the 'values' of the parameters are the actual character
strings themselves. Note also that macros are assembly time phenomena -
parameters can not depend on values generated at run time.
; This macro moves a 16-bit value from one address to
; another without (seemingly) any effect on registers
MOVE MACRO #SOURCE,#DESTN
PUSH HL
LD HL,(#SOURCE)
LD (#DESTN),HL
POP HL
ENDM
If invoked as MOVE SAM,GEORGE it would expand to:
PUSH HL
LD HL,(SAM)
LD (GEORGE),HL
POP HL
Another example of a form frequently used is shown below. It is used to
invoke CP/M functions in a neat form. As written, the first parameter
is the CP/M function number, the second the contents of the DE register
pair if required. This example also demonstrates the use of the special
symbol #SYM in macros. #SYM expands to the number of parameters
actually specified in the invocation.
CPM MACRO #FN,#PARAM
PUSH BC
PUSH DE
LD C,#FN
IF #SYM > 1
LD DE,#FN
ENDIF
CALL 5
POP DE
POP BC
ENDM
Then parts of the program code could be written as:
CONIN EQU 1
CONOUT EQU 2
SETDMA EQU 26
...
CPM CONOUT, '?' ;display a ? on screen
CPM CONIN ;get a keyboard character
...
CPM SETDMA,DISKBUF ;set dma address to buffer
Of course, macros may not always be the most code-efficient way of doing
things. They get expanded fully at each invocation as opposed to a
subroutine which exists only at one space. If a macro expansion is long
or referenced frequently, consider a subroutine. On the other hand, for
short macros the subroutine linkage (call/ret) may obviate any savings.
NAME
----
This statement tells the librarian that the module name to be inserted
into the .REL file is not the default one - that is, it is not the name
of the .Z80 file which was assembled. The syntax is:
NAME NEWNAME
OMACRO
------
This is a puzzle. It seems to behave just the same as the MACRO keyword
with the exception that the macro name no longer shows up in a symbol
cross reference listing - it does now show up in an opcode cross
reference if such is requested. Nevertheless there is still one piece
of code that has not been fully explored and may show some other
difference between these two. Note that the same symbol may NOT be
declared both as a MACRO and an OMACRO. Also note that defining a
built-in opcode (e.g. LD) as either a MACRO or an OMACRO will replace
the built-in definition.
ORG
---
This is used to force the assembler and linker to place program or data
at specific memory locations. Most .COM files begin at 100H but that is
assumed anyways if no ORG statement is given. The syntax is:
ORG value
REL
---
This signals that the following is to be placed into the relocatable
code program section. The syntax is simply:
REL
REM
---
This seems to be the equivalent of a line beginning with a semicolon -
i.e. pure comment. Why it is included escapes me, unless some unweaned
BASIC programmer insisted on it.
REPT
----
The repeat statement is a predefined macro, taking one nest level and
requiring an ENDM. It repeats a block of statements a fixed number of
times. For example:
ROTLEFT MACRO #REG,#TIMES
LD A,#REG
REPT #TIMES
RLCA
ENDM
LD #REG,A
ENDM
Then the instruction:
ROTLEFT B,5
would expand into:
LD A,B
RLCA
RLCA
RLCA
RLCA
RLCA
LD B,A
which is much more readable in the macro/repeat form above.
STRUCT
------
This is another rather strange thing but perhaps a rather nice one to.
The structure block which this introduces generates no code whatsoever.
Indeed any instruction that would generate code is disallowed. Hence
even DB, DW and DM instructions are illegal. The purpose seems to be to
define the structure of a block of code or data more neatly than in
using ordinary artifices. Some tentative examples of usage follow:
STRUCT 0
DRIVE: DS 1
NAME: DS 8
TYPE: DS 3
EXTENT: DS 1
S1: DS 1
S2: DS 1
RECCT: DS 1
BLOKS: DS 16
CURREC: DS 1
RANREC: DS 2
TOOBIG: DS 1
ENDM
Then one can write, assuming that FCB is the address of a file control
block:
LD A,(FCB+CURREC)
Of course we could have said just as well:
DRIVE EQU 0
NAME EQU DRIVE + 1
TYPE EQU NAME + 8
...
but the STRUCT is clearer.
SUBTTL / TITLE2
---------------
This is the second title that will show up on pages of the listing. The
syntax is:
SUBTTL This is a subtitle.
TITLE
-----
This is the main title that will show up on each page of the listing.
The syntax is as for SUBTTL.
Library Commands
----------------
There are four more special commands allowed, each beginning with an
asterisk:
*INCLUDE filenam
*INCLUDE1 filenam
*MACLIB filenam
*RELLIB filenam
The asterisk must lie in column 1 of the source - no tabbing is
permitted. There are no compulsory or default extensions for the
filenames. The meaning of the commands is:
*INCLUDE
--------
Include the file named into the assembly at this point. This file might
typically contain constant definitions, entry and external declarations,
some documentation detail, or simply more program code. The include
file will be read on both assembler passes. INCLUDE's can be nested to
four levels.
*INCLUDE1
--------
The same as INCLUDE except that it happens only on pass 1. Since the
listing is not generated until pass 2, INCLUDE1 should not be used for
anything to be listed. Also code is not generated until pass 2 so
INCLUDE1 can not be used for source statements that generate code.
Perhaps constant definitions, entry and external declarations, or macro
definitions can be included only in pass 1.
*MACLIB
-------
This declares the named file to contain a number of macro definitions.
I'm not sure just what happens but I think that the macro names only are
loaded into memory together with their location on disk in case they are
needed later.
*RELLIB
-------
This causes a special record to be sent to the .REL file instructing the
linker to automatically search the named file to resolve external
references. This can save typing in the name of a standard library
every time the link command is typed. Any other advantage escapes me.