Programming with Ophis | ||
---|---|---|
<<< Previous | Ophis Command Reference | Next >>> |
Assembly language is a powerful tool—however, there are many tasks that need to be done repeatedly, and with mind-numbing minor modifications. Ophis includes a facility for macros to allow this. Ophis macros are very similar in form to function calls in higher level languages.
Macros are defined with the .macro and .macend commands. Here's a simple one that will clear the screen on a Commodore 64:
.macro clr'screen lda #147 jsr $FFD2 .macend |
To invoke a macro, either use the .invoke command or backquote the name of the routine. The previous macro may be expanded out in either of two ways, at any point in the source:
.invoke clr'screen |
or
`clr'screen |
will work equally well.
Macros may take arguments. The arguments to a macro are all of the "word" type, though byte values may be passed and used as bytes as well. The first argument in an invocation is bound to the label _1, the second to _2, and so on. Here's a macro for storing a 16-bit value into a word pointer:
.macro store16 ; `store16 dest, src lda #<_2 sta _1 lda #>_2 sta _1+1 .macend |
Macro arguments behave, for the most part, as if they were defined by .alias commands in the calling context. (They differ in that they will not produce duplicate-label errors if those names already exist in the calling scope, and in that they disappear after the call is completed.)
Unlike most macro systems (which do textual replacement), Ophis macros evaluate their arguments and bind them into the symbol table as temporary labels. This produces some benefits, but it also puts some restrictions on what kinds of macros may be defined.
The primary benefit of this "expand-via-binding" discipline is that there are no surprises in the semantics. The expression _1+1 in the macro above will always evaluate to one more than the value that was passed as the first argument, even if that first argument is some immensely complex expression that an expand-via-substitution method may accidentally mangle.
The primary disadvantage of the expand-via-binding discipline is that only fixed numbers of words and bytes may be passed. A substitution-based system could define a macro including the line LDA _1 and accept as arguments both $C000 (which would put the value of memory location $C000 into the accumulator) and #$40 (which would put the immediate value $40 into the accumulator). If you really need this kind of behavior, a run a C preprocessor over your Ophis source, and use #define to your heart's content.
<<< Previous | Home | Next >>> |
Memory Model | Up | Assembler directives |