Spencer's Z80 Assembler Manual

Sections
General Information
Specific Instructions
Terminal Use
#comment
#include
.echo
.org

Background Information
This assembler was written not add another generic tool to the oversaturated assembler "marketplace," but to actually do something different. I needed a fast assembler. TASM wasn't cutting it. When you're impatient, you debug often, or are writing too much code for other assemblers to handle, this assembler is your new best friend.

Examples in this readme are going to be written in z80-assembly, as this is the intended target. Though, with other table files, other architectures are certainly possible.

General Information
Labels:
Labels in SPASM are much like TASM 3.2. The prefered style of label is the colon terminated, like this:
Label:
	ld a,30
	ret

;With labels, you can use this syntax:

Label2:	ld a,25 \ ret
Also permitted is the non-colon terminated line label.
label
	xor a
	ld (ram_loc),a
	ret

;Like above, the following is acceptable:

label2	inc a
	ld (ram_loc+1),a
	ret

Arithmetic:
Numbers can be expressed in three bases, decimal (by default), hexidecimal, or binary. There are prefix and postfix input methods for the latter two:
;Decimal:
 ld a,15
 ld a,15d
;Hexidecimal:
 ld a,$10
 ld a,10h     ;ld a,16
;Binary:
 ld a,%1011
 ld a,1011b   ;ld a,11
Note that with postfix in hex, you must start the value with a number, e.g. hex AA should be expressed as 0AAh, since AAh would be interpreted as a label.

SPASM uses no-questions-asked order of operations: left-to-right. This is prefered for speed reasons as well as ambiguity between operators -- who really knows which of these operators should come first? % or &?

The operators available are as follows:  * / - + % ^ & | << >>

 ld a,10*15		;= 150  multiply
 ld b,254/12		;= 12   integer divide (it truncates)
 ld b,254%12		;= 2    modulo (remainder of 254/12)
 ld c,10-30		;= -20  subtract
 ld d,-(10-23)		;= 13   negate
 ld e,10+10		;= 20   add
 ld h,10^3		;= 9    bitwise exclusive or
 ld l,17 & 1		;= 1    bitwise and
 .db 10 | 5		;= 15   bitwise or
 .dw 1<<4		;= 16   arithmetic shift left
 ld hl,16>>4		;= 1    arithmetic shift right

;Example of order of operations:

 ld hl,25*256+10	;h = 25, l = 10
 ld hl,10+25*256	;h = 35, l = 0
 ld hl,10+(25*256)	;h = 25, l = 10

Macros:
SPASM macros were built to be fast, more than anything else. I generally preserve the functionality of other assemblers while keeping it simple. There are three types of macros, all invoked by the preprocess keyword #DEFINE:
  • Dimensionless Macros (Boolean Defines)
  • Replacement Macros (Defines)
  • Argumented Replacement Macros
Dimensionless:
Macros of this nature are not defined explicitly by the programmer, rather they are set to an arbitrary default, which simply notifies the assembler that a macro of the given name has been created. SPASM uses these as a quick Boolean Define for the #IFDEF preprocess.

#define on_emulator

#ifdef on_emulator
	push de   ;these two lines will be assembled
	pop ix
#else
	ld ixl,e  ;these two lines will be omitted from the output file
	ld ixh,d
#endif

Replacement: Replacement macros are the equivalent of a "named" copy and paste. They are not parsed until they are substituted, so they're ideal for making forward label references. Keep in mind that they can only make forward references to other defines as long as the define does not reference them in return.
#define value 56
#define other_value value+10

;Defines like these can be used in the #IF preprocess:
#if other_value > value
	.echo other_value
#else
	.echo value
#endif

Spencer's Assembler, April 2006
Beginning assembly ...
Pass 1 ...
66
Done.
Pass 2 ...
Done.

Argumented Replacement:
The most complex of the macros, argumented replacement macros allows certain values of replacement macro to be changed before parsing. This allows the same macro to be used under multiple circumstances.
#define my_modulo(base, mod) (base - (mod*(base/mod)))
#define dbl(val) (val*2)

 .echo dbl( my_modulo(11,3) )
 .echo my_modulo(11,3)
Spencer's Assembler, April 2006
Beginning assembly ...
Pass 1 ...
4
2
Done.
Pass 2 ...
Done.
Completely unlike other assemblers, SPASM does not do macros entirely in preprocess, rather in a form of coprocess. Besides being several times faster, this also allows an argumented macro to be aware of the value it is receiving.
#macro display_text(time, text) 
  #if time=0
    xor a
  #else
    ld a,time
  #endif
  call draw_text
  .dw text
#endmacro

 display_text(0,string1) 

 display_text(40,string2) 
draw_text: 
;some text drawing code here
 ret  

string1: 
 .db "hello!",0 
string2: 
 .db "world!",0
display_text(0,string1) -> xor a \ call draw_text \ .dw string1
display_text(40,string2) -> ld a,40 \ call draw_text \ .dw string1

Example code
label:
	ld hl,20
	ld a,20		;20's for everyone!
#comment
	This is a block comment.
	Woohoo.
#endcomment
Terminal Use
Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.

C:\assembly>dir
03/20/2006  03:19 AM  52,000 assembler.exe
03/23/2006  03:04 PM   4,000 assemblyfile.asm
03/20/2006  03:19 AM  23,080 tasm80.tab

C:\assembly>assembler assemblyfile.asm -T
Spencer's Assembler, March 2006
Beginning assembly ...
Pass 1 ...
Done.
Pass 2 ...
Done.
C:\assembly>dir
03/20/2006  03:19 AM  52,000 assembler.exe
03/23/2006  03:04 PM   4,000 assemblyfile.asm
03/23/2006  03:09 PM     900 assemblyfile.bin
03/23/2006  03:09 PM   4,800 assemblyfile.lst
03/20/2006  03:19 AM  23,080 tasm80.tab