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 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 --- code to execute if true --- .else --- code to execute if 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 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 to exit the body of the loop. The ".while" is used like so: .do --- code to set the flags --- .while --- body of loop --- .enddo The ".until" is used like: .do --- body of loop --- .until 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 --- body of case --- .break .case --- code to set the flags --- .cond --- body of case --- .break .case --- code to set the flags --- .cond --- 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