home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
cpm
/
utils
/
asmutl
/
m80str11.lbr
/
STRUCT.DZC
/
STRUCT.DOC
Wrap
Text File
|
1988-02-16
|
8KB
|
199 lines
Z80 structured programming macro library.
-----------------------------------------------------------------------------
Version 1.10
Fixed a bug in the expansion of ".case" and ".cond" macros that
cropped up when ".switch" constructs were nested inside each other.
-----------------------------------------------------------------------------
This is a macro library that implements a small number of very open ended
structured programming constructs for the Microsoft M80 macro assembler. The
code has been tested using version 3.44 (which is dated 09-DEC-81 in the page
headers of its *.PRN output listings.) Since I have access to no other
assemblers, I was unable to test it for any others, nor for other releases of
M80. I am fairly confident, however that it should run on M80 generally and
perhaps less confident that it could easily be ported to other macro assemblers.
The macros were written using Zilog Z80 mnemonics. All that is required to
convert it to Intel 8080 mnemonics id to remove the ".Z80" switch at the top of
the file (or replace it with ".8080") and to replace all occurrences of the "jp"
instruction (used in macros "@jump" and "@ijump" only) with "jmp". That's the
only machine executable instruction used in the file, the rest of it consisting
of assembler symbol manipulations to keep track of what's next and to generate
labels in appropriate locations.
I did originally write the macros used for jumping to use relative jumps
wherever possible for the smaller and quicker code they produce, but
unfortunately this only works if the label has been defined already, and there
is no way to get around the problem that I can see (at least not a worthwhile
one) so the generic jump instruction was used throughout. The jump instructions
themselves could be generated more quickly using "db" assembler directives,
but the string comparison method used generates more readable assembler
listings, which can be useful for debugging.
The possible combinations of these constructs are virtually endless. The macros
were designed with the intention of leaving as much versatility as possible
in their structure. There is no reason, for instance, that a single .do loop
couldn't have both a .while condition clause at the top and a .until condition
clause at the top, although I wouldn't recommend doing so. By the same token,
that same .do loop could be set up without any condition clause (in which case
you better be doing SOMETHING to leave it, because that is an infinite loop
by design...)
While I have not had much opportunity to use these macros extensively yet,
I do use a set of such macros in a mainframe assembler environment. They have
the ability to relieve the programmer of the drudgery of working out the exact
details of many nested loops, multi-condition routines and the invention of
various and sundry labels. (Face it - making up lots of meaningless and similar
sounding labels is a pain in the ...)
All constructs may be nested within any other constructs to what is, for
practical purposes an infinite degree. The only condition is the same as in any
language that implements them: their individual elements must be kept together
in the sense that you cannot begin a .do loop in an .if clause and end it
outside.
Macros included:
@getput macros starting with "@" are intended for use
@push internally to other macros only. This doesn't
@pop preclude using them otherwise, however.
@jump
@ijump
@lbl
.ifndf semi-internal macro - not really necessary, but nice.
.if if ... else ... endif construct
.else
.endif
.break applies to ths constructs below - terminates
.do and .switch
.do loop construct
.while
.until
.enddo
.switch case select construct
.case
.cond
.endsw
Usage:
In the following descriptions, the <condition> can be one of:
z nz c nc po pe p m
which are the standard Z80 branch instruction conditions.
The if...then...else construct requires that you precede it with some code that
sets the flags. Once the flags are set and you wish to base conditional
execution on them, you can code:
--- code that sets flags ---
.if <condition>
--- code to execute if <condition> true ---
.else
--- code to execute if <condition> false ---
.endif
The ".else" clause is completely optional.
The ".break" macro applies to any ".do" loop and/or any ".switch" case. It can
be specified with a <condition> or without. More on this one later.
The ".do" constructs all implement loops, but quite a variety are possible.
A simple:
.do
--- body of loop ---
.enddo
provides you an inifinite loop. You can include a ".break" (with or witout) its
optional <condition> to exit the body of the loop.
The ".while" is used like so:
.do
--- code to set the flags ---
.while <condition>
--- body of loop ---
.enddo
The ".until" is used like:
.do
--- body of loop ---
.until <condition>
Note that the ".until" REPLACES the ".enddo".
Either of the above can have a ".break" for early termination. While I haven't
actually tried it, I see no reason why you couldn't create a ".do" loop that
contained BOTH an ".until" AND a ".while".
The ".switch" construct has the basic structure:
.switch
.case
--- code to set the flags ---
.cond <condition>
--- body of case ---
.break
.case
--- code to set the flags ---
.cond <condition>
--- body of case ---
.break
.case
--- code to set the flags ---
.cond <condition>
--- body of case ---
.break
.otherwise
--- code to execute otherwise ---
.endsw
Note the ".break" statements at the end of each case/cond. I swiped the basic
layout of the switch statement from the C language, and decided to include this.
The case/cond pairs simply provide a test and an entry point to the code. Thus
if you left the ".break" statements out, control would enter the code at the
first test that was satisfied, then continue falling thru, skipping subsequent
tests that were not satisfied, until it fell out the ".endsw" statement. The
".break" statements will cause the control to be passed out of the switch/endsw
range. While this requires some extra typing, it adds a variety of flexible
possibilities to the usage of ".switch". The .break statements could have
conditions associated with them, in which you case you can construct .switch
statements that select and execute a single .case under some conditions, and act
as multiple entry point routines with some or complete fall through in other
situations. Pretty weird, but interesting...
Files included:
STRUCT.FOR Short statement of purpose
STRUCT.DOC This doc file.
STRUCT.MAC Full source to the macros.
STRUCT.LIB Same as above, but with comments and extra spaces
stripped out for quicker assembly and less wasted TPA.
Use this as your "INCLUDE" file.
Have fun. Al Grabauskas
I can be contacted at the LILLIPUTE Z-NODE in Chicago if you have any
questions or comments.
(312) 649-1730
(312) 664-1730