Assembler Syntax
The WinAPE assembler is designed to be compatible with Maxam 1.5 with some extensions to the standard Maxam assembler.
The supports all Z80 Instructions, a number of Assembler Directives for functionality other than pure Z80 code, and the ability to use Labels and Comments. Each line of code can contain multiple instructions separated by the colon character (:), although generally most people use one line per instruction for readability.
Code Origin
All assembler code needs to be given a starting point in memory. Without defining the origin for the code, WinAPE will assume that the code starts at address #0000, and the code will most likely overwrite the lower region of memory used for restart instructions and interrupts. The assembler directive used to set the origin of code is org, and is usually one of the first lines in an assembly language program. For example:
org #4000
The above line tells the assembler to start producing code from memory address #4000. All instructions and directives which produce code output starting at the given address, and the current assembler code address can be used in expressions by using the $ symbol.
Labels
A label is used to define a symbol at the current assembly address. This can be useful for naming looping points, subroutines or variables. Labels must start with either an underscore character or an alphabetic character, and can only contain letters, numbers or underscore. A label definition can be a single word which is not a reserved word (Z80 or directive) either in a line on its own or immediately preceding another Z80 instruction or directive. Labels can also be preceded by a dot (.), which is not included as part of the symbol itself, and can also allow reserved words to be used as labels. For example:
org #4000
ABC
def:ghi ld a,b
.jkl ld c,d:mno
pqr: ld b,a
_stu:
jp pqr
The above code will define ABC, def and ghi all as having the current address #4000. Code will be generated for the instruction ld a,b which is one byte, so the next label .jkl will create a symbol named jkl which will have the value #4001. Code will be generated for the instruction ld c,d which is also one byte, so the next two labels mno and pqr will have the value #4002. Code will be generated for the instruction ld b,a which is another single byte so the final label _stu will be given the value #4003. The jp pqr instruction uses the value of pqr to assemble a Z80 jump instruction with the address of the symbol.
The actual output from the assembler shows these values in the listing as below:
000001 0000 (4000) org #4000 000002 4000 ABC 000003 4000 def 000003 4000 78 ghi ld a,b 000004 4001 4A .jkl ld c,d 000004 4002 mno 000005 4002 pqr 000005 4002 47 ld b,a 000006 4003 _stu 000007 4003 C3 02 40 jp pqr
The columns shown are the line number in the current file, the current assembly address, generated code (or expression value) and the final column is the actual partial line of code since the last line or colon character.
Assigning Values to Symbols
By default symbols defined by labels are given the current code address as their value. It is possible to assign different values to symbols using the equ directive. For example:
.int_vector equ #38
free_space equ end_addr + 20
.print equ 6 * 3 + jump_table
The code above assigns the value of #38 to the symbol int_vector, the second line assigns the value of end_addr + 20 to the symbol free_space, and the third line assigns the value 6 * 3 + jump_table to the symbol print. Note that the assembler does not currently (as per Maxam) support operator precedence, so the expression is evaluated left-to-right, and jump_table + 6 * 3 would be produce a totally different result. For example:
x equ 3
y equ 2 * 4 + x
z equ x + 2 * 4
The code above assigns the value 3 to x, then the value for y is evaluated as 2 * 4 = 8 then 8 + x = 11 so the result will be a value of 11.
The final value for z is also evaluated left-to-right as x + 2 = 5, then 5 * 4 = 20 so the final value for z will be 20.
The LET directive
By default, symbols can only be defined to have one value in any assembler program. Symbols are not the same as BASIC variables, and it is very rare that their values need to be changed.
The let directive allows a symbol to be redefined to have different values in different parts of an assembler program. As a general rule you should never use let in your programs except in special circumstances.
Including other source files
The WinAPE assembler allows mutiple files to be assembled at once by including other source files using the read or incbin directives.
read allows the inclusion of another assembler source file. This may contain symbol definitions, macro definitions and source code in any combination, just as the main source file. Files included with read may also be nested, and the included file has access to all symbols within the parent source files in the same way as code within the main source file.
incbin allows the inclusion of binary data in the assembler output. This may be any arbitrary binary data generated from any source, such as graphics data, sound data or code generated by another compiler.
Files included with read or incbin are searched for beginning with the directory of the current file, then all other directories specified in the Library Path.