<--  back   Last regenerated: 2010-09-08 15:25:13 kio

zasm - Z80 Assembler

Target files

Information on the ZX Spectrum file formats can be found in the ZX Spectrum FAQ which can be found on WOS: www.worldofspectrum.org/faq/.

General rules

The Target filestarget file format must be set with the Assembler directives: #target, #end#target Source files: Assembler directivesassembler directive.

Assembler directives: #target, #end#target     [pathandfilename.]extension
        ...
Assembler directives: #target, #end#end

Assembler directives: #target, #end#target defines filename, extension and format of the Target filestarget file. typically there is only one Assembler directives: #target, #end#target ... #end section per assembler source, but there may be more. the latter probably requires to supply the full Target filestarget file names in the Assembler directives: #target, #end#target directives. (not yet implemented as of version 3.0.14)

This does not define whether the generated Pseudo instructions: datadata should be written as a plain General rules: Binary filesbinary file or in General rules: Intel hex file formatintel hex file format. This must be selected be the '-b' or '-x' Command line optionscommand line option. The assembler always defaults to binary except if the output is written to a terminal.

Up to version 0.3.13 the Assembler directives: #target, #end#target Source files: Assembler directivesassembler directive is required.

Since version 0.3.14 the Assembler directives: #target, #end#target Source files: Assembler directivesassembler directive may be omitted. Then the default target format is Target files: #target romrom.

Assembler directives: #head#head       <size>

Target filesTarget files which store registers and similar information start with a Assembler directives: #head#head segment. The Pseudo instructions: datadata within the Assembler directives: #head#head segment are set using 'Pseudo instructions: defb, defm, db, dmdefb' and similar instructions. If portions of the Assembler directives: #head#head segment are not set or 'Pseudo instructions: defs, dsdefs' is used with no fill pattern then default values will be filled in which vary depending on the omitted Pseudo instructions: datadata's purpose.

Assembler directives: #code#code       <start>,<size>

This directive defines an object code segment and set's the initial logical code origin to <start> and defines a maximum segment size <size>.

<start> does not neccessarily define the physical position of the code segment in the Target files: #target romrom. Binary output does not contain address information, just the pure Pseudo instructions: datadata. In contrast Intel hex files contain address information. Starting with version 3.0.13 addresses in hex files are biased to <start>. The 'Pseudo instructions: orgorg' assembler Source files: Pseudo instructionspseudo instruction does not affect the hex file addresses.

Multiple code segments are possible and are simply concatenated. Code segments are either padded at the end to the declared maximum segment size or they are truncated, depending on the Assembler directives: #target, #end#target format.

Up to version 0.3.13 the Assembler directives: #code#code Source files: Assembler directivesassembler directive is required.

Since version 0.3.14 the Assembler directives: #code#code Source files: Assembler directivesassembler directive may be omitted. Then the used default values are start=0 and size=$10000.

Intel hex file format

If the file is saved in the General rules: Intel hex file formatintel hex file format, then the unused space at the end of all code segments is never saved (truncated). When reading these files you can decide what to do with the missing Pseudo instructions: datadata. e.g. an eprom burner will simply skip over the gaps, leaving the Pseudo instructions: datadata as is, probably $FF for erased cells.

As stated above, Intel hex files contain address information at which to physically store the generated code. Starting with zasm version 3.0.13 this address is also set to <start>.

Binary files

All code segments are padded with $00 to the declared maximum size, except:

If you want to prevent that a code segment is truncated then you can simply add 'Pseudo instructions: defs, dsdefs' to fill it up to the last byte.

General rules: Binary filesBinary files do not contain information about the address where they should be loaded. Where they are loaded purely depends on the application used to load the file into a simulator or eprom.

#target rom

This file is a plain Target files: #target romrom or eprom image.

Segments are padded with $FF, except for the last code segment, which is not padded but truncated.

Target files: #target rom#target     rom
Assembler directives: #code#code       <start>,<len>
        ...
Assembler directives: #target, #end#end

#target bin

Pretty the same as a Target files: #target romrom file, but rather expected to be loaded somewhere into ram.

Segments are padded with $00, except for the last code segment, which is not padded but truncated.

Target files: #target bin#target     bin
#code       <start>,<len>
        ...
Assembler directives: #target, #end#end

#target sna

A ZX Spectrum snapshot file. This consists of a ram dump from location $4000 to $FFFF. Snapshot files also contain information about the machine state, most namely the Target files: #target z80Z80 registers. The Assembler directives: #head#head Source files: Assembler directivesassembler directive is required to set interrupt mode and all Target files: #target z80Z80 registers.

Target files: #target sna#target sna
Assembler directives: #head#head   27
    ...
Assembler directives: #code#code   <start>,<len>
    ...
Assembler directives: #target, #end#end

The Target files: #target snaSNA snapshot file describes a ZX Spectrum 16k or 48k serving an nmi request.

<start> should be $4000 and <len> should be $4000 or $C000. at least later it's loaded that way. when Assembler directives: #target, #end#end is reached, the file is padded with $00 to $4000 bytes (if possible) or $C000 bytes, which implicitely defines a ZX Spectrum 16k or ZX Spectrum 48k.

The RAM contents are written to the file in the uncompressed Target files: #target snaSNA format. the Target files: #target snaSNA file format is an NMI snapshot. the instruction pointer PC is not stored in the header section but on the return stack in RAM.

Default values for header data:
Pseudo instructions: defb, defm, db, dmdefb    $3f         ; i
Pseudo instructions: defw, dwdefw    0,0,0,0     ; hl',de',bc',af'
Pseudo instructions: defw, dwdefw    0,0,0,0,0   ; hl,de,bc,iy,ix
Pseudo instructions: defb, defm, db, dmdefb    $04         ; bit 2 = iff2 (iff1 before nmi) 0=di, 1=ei
Pseudo instructions: defb, defm, db, dmdefb    0,0,0       ; r,f,a
Pseudo instructions: defw, dwdefw    0           ; sp
Pseudo instructions: defb, defm, db, dmdefb    1           ; irpt mode
Pseudo instructions: defb, defm, db, dmdefb    7           ; border color: 0=black ... 7=white

#target z80

zasm version 3.0.7: not yet implemented

This ZX Spectrum snapshot format may contain a snapshot for the ZX Spectrum or the ZX 128. It contains all of the .Target files: #target snasna file's information and optionally some more. It is preferred over the .Target files: #target snasna format by some people, because it does not store the instruction pointer pc on the Target files: #target z80Z80 machine stack. The .Target files: #target z80z80 file may also contain one or two Target files: #target romroms and Pseudo instructions: datadata for the paged ram of the ZX 128.

Target files: #target z80#target z80
Assembler directives: #head#head   <size>      ; vs.201 = 55;  vs.300 = 86;  xzx = 87
Assembler directives: #code#code   <start>,<len>
    ...
#page   <index>
    ...
Assembler directives: #target, #end#end

The Target files: #target z80z80 format describes a ZX Spectrum 16k, 48k, 128k or, in versions written by the warajewo and xzx emulator, a Timex 2068, a ZX Spectrum +3, a Pentagon or a Scorpion.

The object code from the code segments is written to the paged-in RAM according to the value stored for the paging control register at address $1FFD. start should be $4000, len should be $4000 or $C000. at least, this is how it get's loaded later.

Note: $4000 = bank 5; $8000 = bank 2; $C000 = bank 0 after reset.

The #page directive defines a RAM page in which the following object code is stored. it set's start to $C000 and len to $4000. this directive is only allowed for models which are capable of paging.

The RAM contents are written to the file in the compressed Target files: #target z80Z80 format.

Default values for header data:
    Pseudo instructions: defb, defm, db, dmdefb    0,0         ; a,f
    Pseudo instructions: defw, dwdefw    0,0         ; bc,hl
    Pseudo instructions: defw, dwdefw    0           ; flag idicating vs.201 header or later
    Pseudo instructions: defw, dwdefw    0,0         ; sp
    Pseudo instructions: defb, defm, db, dmdefb    $3f         ; i
    Pseudo instructions: defb, defm, db, dmdefb    0           ; r & 0x7f
    Pseudo instructions: defb, defm, db, dmdefb    (7<<1)      ; (r>>7) + (border_color<<1)
    Pseudo instructions: defw, dwdefw    0,0,0,0     ; de,bc',de',hl'
    Pseudo instructions: defb, defm, db, dmdefb    0,0         ; a',f'
    Pseudo instructions: defw, dwdefw    0,0         ; iy,ix
    Pseudo instructions: defb, defm, db, dmdefb    1           ; iff1: 0=di, 1=ei
    Pseudo instructions: defb, defm, db, dmdefb    1           ; iff2
    Pseudo instructions: defb, defm, db, dmdefb    1+(1<<6)    ; (irpt_mode) + (issue_2<<2) + (joystick_emu<<6)
// vs.201 header:
    Pseudo instructions: defw, dwdefw    headsize-32 ; size of header extension; should be 23 or 54
    Pseudo instructions: defw, dwdefw    0           ; pc
    Pseudo instructions: defb, defm, db, dmdefb    0           ; ZX Spectrum model     1)
    Pseudo instructions: defb, defm, db, dmdefb    0           ; 128k: last out to $7ffd (bank switching)  2)
    Pseudo instructions: defb, defm, db, dmdefb    0           ; if1 paged in?     2)
    Pseudo instructions: defb, defm, db, dmdefb    7           ; proper r and ldir emulation, 48k ay emulation 3)
    Pseudo instructions: defb, defm, db, dmdefb    0           ; last out to $fffd (ay register select)
    Pseudo instructions: defs, dsdefs    16,$ff      ; ay registers
// vs.300 header:
    Pseudo instructions: defb, defm, db, dmdefb    0,0,0       ; T state counters
    Pseudo instructions: defb, defm, db, dmdefb    0           ; misc.
    Pseudo instructions: defb, defm, db, dmdefb    0,0,$ff,$ff ; MGT/Multiface/SamRam paging
    Pseudo instructions: defs, dsdefs    20,0        ; keyboard mapping for joystick emulation
    Pseudo instructions: defb, defm, db, dmdefb    0,0,0       ; Disciple flags
// xzx header extension:
    Pseudo instructions: defb, defm, db, dmdefb    0           ; +3: last out to $1ffd (bank switching)    3)

1)  0   = 48k
    3   = 128k in vs.201
    4   = 128k in vs.300
    128 = Timex 2068        (warajewo)
    7   = +3                (xzx)
    9   = pentagon          (xzx)
    10  = scorpion          (xzx)   16 ram pages!

2)  Timex 2068:
    last out to 244
    last out to 255

3)  Bit 2: enable ay emulation even in 48k mode (xzx)

#target tape

A ZX Spectrum Target files: #target tapetape file. This file may and should contain several code segments. Any time a Assembler directives: #code#code segment is finished, it is appended to the Target files: #target tapetape file.

Target files: #target tape#target     tape
Assembler directives: #code#code       <start>,<len>,#target tape: <flag><flag>
    ...
Assembler directives: #target, #end#end

The Target files: #target tapetape file format represents programs and Pseudo instructions: datadata saved to a music compact cassette by the original ZX Spectrum Target files: #target tapetape saving routines.

Each code segment defines a block on the Target files: #target tapetape. the flag argument defines the type of block, which is typically $00 for a header block and $FF for the subsequent Pseudo instructions: datadata block.

The code segments are never padded but always truncated. the blocks are written to the file in the uncompressed Target files: #target tapeTAP format.

Any kind of Pseudo instructions: datadata is typically saved in two blocks: a header block, containing information about the following Pseudo instructions: datadata, and a Pseudo instructions: datadata block, containing Pseudo instructions: datadata as described by the preceding header.

A complete game is typically saved in two parts: a basic loader, which consists of a header and a Pseudo instructions: datadata block and the machine code part, which consists of a header and Pseudo instructions: datadata block too.

All blocks in the .Target files: #target tapetap file start with two bytes specifying how many bytes will follow. Then raw Target files: #target tapetape Pseudo instructions: datadata follows, starting with the flag byte and ending with the checksum byte. A Target files: #target tapetape file is a simple sequence of any number of these blocks.

Layout of a block in a tape file:
Pseudo instructions: defw, dwdefw    #target tape: <length><length>
Pseudo instructions: defb, defm, db, dmdefb    #target tape: <flag><flag>
Pseudo instructions: defb, defm, db, dmdefm    #target tape: <data><data>
Pseudo instructions: defb, defm, db, dmdefb    #target tape: <checksum><checksum>
<length>

This is the number of bytes that follow: including the #target tape: <flag><flag>, #target tape: <data><data> and #target tape: <checksum><checksum>; not counting the #target tape: <length><length> itself. Byte order is little endian, this means, the low byte is first. The ZX Spectrum save routine cannot save 0 bytes or more than $ff00 bytes, thus the minimum #target tape: <length><length> is 3, which means 1 byte flag + 1 byte Pseudo instructions: datadata + 1 byte checksum.

<flag>

This is the value of the A register when the ZX Spectrum save routine was called. A value of $00 normally indicates, that this is a header block, a value of $FF indicates, that this is a Pseudo instructions: datadata block, which contents are described by the preceding header block.

<data>

Contains a header (if #target tape: <flag><flag>==$00 and #target tape: <length><length>==19) or Pseudo instructions: datadata. These are the bytes which will be loaded into RAM.

<checksum>

this is the bitwise XOR of all bytes including the flag byte.

To create a program which consists of a basic loader and a machine code part as described above, write an assembler program which consist of 4 code segments:

A header block is always 17 bytes long.

The headers for a basic program and for binary Pseudo instructions: datadata are layed out as follows:

Header for basic program:
Pseudo instructions: defb, defm, db, dmdefb    0       ; this indicates a basic program
Pseudo instructions: defb, defm, db, dmdefm    name    ; the 'file' name, 10 bytes long
Pseudo instructions: defw, dwdefw    length  ; length of block, that is basic program plus variables
Pseudo instructions: defw, dwdefw    auto    ; line number for auto-start, $8000 if none
Pseudo instructions: defw, dwdefw    proglen ; length of the basic program without variables
Header for binary data:
Pseudo instructions: defb, defm, db, dmdefb    3       ; this indicates binary Pseudo instructions: datadata
Pseudo instructions: defb, defm, db, dmdefm    name    ; the 'file' name, 10 bytes long
Pseudo instructions: defw, dwdefw    length  ; length of Pseudo instructions: datadata block which follows
Pseudo instructions: defw, dwdefw    origin  ; original location from where the binary Pseudo instructions: datadata was saved
Pseudo instructions: defw, dwdefw    0       ; unused
A sample framework for a tape file assembler source:
;****** Target files: #target tapeTAPE FILE ASSEMBLER SOURCE SAMPLE ************************************
headerflag:     Pseudo instructions: defl, equequ 0
dataflag:       Pseudo instructions: defl, equequ $ff

tCLEAR  Pseudo instructions: defl, equequ     $FD             ; token CLEAR
tLOAD   Pseudo instructions: defl, equequ     $EF             ; token LOAD
tCODE   Pseudo instructions: defl, equequ     $AF             ; token CODE
tPRINT  Pseudo instructions: defl, equequ     $F5             ; token PRINT
tUSR    Pseudo instructions: defl, equequ     $C0             ; token USR

Target files: #target tape#target tap

;------ PROGRAM HEADER -------------------------------------------------------
Assembler directives: #code#code   0,17,headerflag
        Pseudo instructions: defb, defm, db, dmdefb    0               ; program
        Pseudo instructions: defb, defm, db, dmdefm    "testloader"    ; make sure these are 10 bytes!
        Pseudo instructions: defw, dwdefw    programsize     ; length of basic program and variables
        Pseudo instructions: defw, dwdefw    10              ; line number for auto start
        Pseudo instructions: defw, dwdefw    programsize     ; length of basic program without variables


;------ PROGRAM Pseudo instructions: dataDATA ---------------------------------------------------------
Assembler directives: #code#code   0,$100,dataflag         ; size is truncated as required

; 10 CLEAR 24000
        Pseudo instructions: defb, defm, db, dmdefb    0,10                    ; line number
        Pseudo instructions: defb, defm, db, dmdefb    end10-($+1)             ; line length
        Pseudo instructions: defb, defm, db, dmdefb    0                       ; statement number
        Pseudo instructions: defb, defm, db, dmdefb    tCLEAR                  ; token CLEAR
        Pseudo instructions: defb, defm, db, dmdefm    '24000',$0e0000c05d00   ; number 24000, ascii & internal format
end10:  Pseudo instructions: defb, defm, db, dmdefb    $0d                     ; line end marker

; 20 LOAD "" CODE 24000
        Pseudo instructions: defb, defm, db, dmdefb    0,20                    ; line number
        Pseudo instructions: defb, defm, db, dmdefb    end20-($+1)             ; line length
        Pseudo instructions: defb, defm, db, dmdefb    0                       ; statement number
        Pseudo instructions: defb, defm, db, dmdefb    tLOAD,'"','"',tCODE     ; token LOAD, 2 quotes, token CODE
        Pseudo instructions: defb, defm, db, dmdefm    '24000',$0e0000c05d00   ; number 24000, ascii & internal format
end20:  Pseudo instructions: defb, defm, db, dmdefb    $0d                     ; line end marker

; 30 PRINT USR 24000
        Pseudo instructions: defb, defm, db, dmdefb    0,30                    ; line number
        Pseudo instructions: defb, defm, db, dmdefb    end30-($+1)             ; line length
        Pseudo instructions: defb, defm, db, dmdefb    0                       ; statement number
        Pseudo instructions: defb, defm, db, dmdefb    tPRINT,tUSR             ; token PRINT, token USR
        Pseudo instructions: defb, defm, db, dmdefm    '24000',$0e0000c05d00   ; number 24000, ascii & internal format
end30:  Pseudo instructions: defb, defm, db, dmdefb    $0d                     ; line end marker
programsize     Pseudo instructions: defl, equequ     $


;------ CODE HEADER ----------------------------------------------------------
Assembler directives: #code#code   0,17,headerflag

        Pseudo instructions: defb, defm, db, dmdefb    3               ; code
        Pseudo instructions: defb, defm, db, dmdefm    "samplecode"    ; make sure these are 10 bytes!
        Pseudo instructions: defw, dwdefw    codeend-24000   ; length of Pseudo instructions: datadata block
        Pseudo instructions: defw, dwdefw    24000           ; original position
        Pseudo instructions: defw, dwdefw    0               ; unused


;------ CODE Pseudo instructions: dataDATA ------------------------------------------------------------
Assembler directives: #code#code   24000,40000,dataflag

        ret                     ; insert your machine code here

codeend:
Assembler directives: #target, #end#end
;****** END OF CODE SAMPLE ***************************************************

#target 80 / #target o

This creates a Target files: #target tapetape file for use with an ZX80 emulator. There is only one Assembler directives: #code#code segment allowed, which is not padded but truncated. The Target files: #target tapetape file will allways be loaded to ram start at address $4000.

Assembler directives: #target, #end#target 80
Assembler directives: #code#code   <start>,<len>
    ...
Assembler directives: #target, #end#end

"o" can be used instead of "80". This will create a Target filestarget file with extension "o" or "80" respectively, which are fully identical.

The Target files: #target tapetape Pseudo instructions: datadata is always loaded to $4000, so this is the only choice for the <start> address in the Assembler directives: #code#code directive. The <size> may be any value up to a maximum of $C000, but note that most ZX80 had maximum 16 kB ram if extended with an external memory expansion, only 1 kB if none.

The ram starts with system variables from $4000 to $4028, which must be set to proper values. The variable E_LINE at $400A, which contains the end of ram address, is set by the assembler. You need not to calculate it, just skip it with "Pseudo instructions: defs, dsdefs 2" or "Pseudo instructions: defw, dwdefw 0".

#target 81 / #target p

This creates a Target files: #target tapetape file for use with an ZX81 emulator. There is only one Assembler directives: #code#code segment allowed, which is not padded but truncated. The Target files: #target tapetape file will allways be loaded to ram start + $09 at address $4009.

Assembler directives: #target, #end#target 81
Assembler directives: #code#code   <start>,<len>
    ...
Assembler directives: #target, #end#end

"p" can be used instead of "81". This will create a Target filestarget file with extension "p" or "81" respectively, which are fully identical.

The Target files: #target tapetape Pseudo instructions: datadata is always loaded to $4009, so this is the only choice for the <start> address in the Assembler directives: #code#code directive. The <size> may be any value up to a maximum of $C000 minus $09, but note that most ZX81 had maximum 16 kB ram if extended with an external memory expansion, only 1 kB if none.

The ram starts with system variables from $4009 to $403C, which must be set to proper values. The variable E_LINE at the address $4014, which contains the end of ram address, is set by the assembler. You need not to calculate it, just skip it with "Pseudo instructions: defs, dsdefs 2" or "Pseudo instructions: defw, dwdefw 0".

This file also contains the screen file, which basically means, that the video memory must contain 25 HALT Z80 Instructions: Legal instructionsopcodes if the file was saved in SLOW mode.

Here are few important variables:
$4014   defines the end address (used to calculate the file length)
$4029   points to the next executed (autostarted) BASIC line
$403B   bit 6 indicates if program runs in SLOW or FAST mode
$403C++ may be misused for whatever purpose

Valid HTML   Valid CSS