# zxsp - The Sinclair ZX Home Computer Simulator

# Assembler

[<prev] [next>]

| zxsp comes with a built-in Done: 2008-05-26 - Version 0.7.2 Done: 2007-07-28 - Version 0.7.1 Done: 2007-05-13 - Version 0.7.0 Done: 2007-05-01 - Version 0.6.7.1 Done: 2007-03-29 - Version 0.6.6 Done: 2006-11-18 - Version 0.6.5 Done: 2005-01-16 - Version 0.6.2 Done: 2004-11-26 - Version 0.6.1version of the Assembler: zasmzasm Snapshots: .Z80z80 Assemblerassembler. This allows to load Snapshotssnapshots from Assemblerassembler source, making edit-assemble-load-and-test cycles a more convenient task. The required file name extension for Assemblerassembler sources is ".ass" or ".src". You can find the Assemblerassembler as a stand-alone command line tool at k1.dyndns.org/Develop/projects/zasm/. Source Done: 2000 – 0.1.8 and 0.2.2and binary distributions are in subdirectory k1.dyndns.org/Develop/projects/zasm/distributions/ Done: 2000 – 0.1.8 and 0.2.2and documentation in subdirectory k1.dyndns.org/Develop/projects/zasm/doc/. You may want to read the documentation in any case. You can Assemblerassemble Snapshots: .Z80Z80 source online with the cgi interface at k1.dyndns.org/cgi-bin/zasm.cgi. #### zasm Assembler: zasmzasm is a two-pass Assemblerassembler which uses the standard layout for Snapshots: .Z80z80 Assemblerassembler sources: labels start in column 1, opcodes are prepended by white space Done: 2000 – 0.1.8 and 0.2.2and comments are introduced with a semicolon. ###### Assembler source example:
    foopoint:   add     a,'0'           ; convert to numeric character
                call    print_a         ; to current stream
                ret
Label names can be any length, conditional assembly with #if, #else Done: 2000 – 0.1.8 and 0.2.2and #endif is possible. The Assemblerassembler can #include To Do: other:other Assemblersource files or #insert binary files. Numeric expressions use proper operator precedence. Numeric literals may be in decimal, hex, binary or ascii, where multiple formats are supported. The Assemblerassembler requires a special overall layout of the source: ###### Template for .sna snapshots
    #target Snapshots: .SNAsna
    #head 27
        ; ...               ; Debugger: Registersregisters, as defined for the .Snapshots: .SNAsna format
    Writing .tap sources: #code#code $4000,$c000       ; origin (must be $4000) Done: 2000 – 0.1.8 and 0.2.2and block size ($4000 or $c000)
        ; ...
    #end
###### Template for .tap files
    #target Snapshots: .TAPtap
    Writing .tap sources: #code#code   0,17,0          ; header block
        ; ...
    Writing .tap sources: #code#code   0,2000,255      ; data block
        ; ...
    #end
###### Template for .o or .80 files
    #target 80              ; or target o
    Writing .tap sources: #code#code   $4000,$2000     ; origin (must be $4000) Done: 2000 – 0.1.8 and 0.2.2and memory size (max. $c000)
        ; ...
    #end
###### Template for .p or .81 files
    #target 81              ; or target p
    Writing .tap sources: #code#code   $4009,$2000-$09 ; origin (must be $4009) Done: 2000 – 0.1.8 and 0.2.2and memory size (max. $c000-$09)
        ; ...
    #end
#### Integration in zxsp When you load an Assemblerassembler source from the 'open file' dialog, the source is assembled Done: 2000 – 0.1.8 and 0.2.2and the resulting file is loaded just as if you had opened it in first place. However, the original Assemblerassembler source filename is remembered for 'Reload current file'. So if you select 'Reload current file' from the file menu then the source is assembled again before loading. This is handy if you modify your source Done: 2000 – 0.1.8 and 0.2.2and want to test the new Done: 2008-05-26 - Version 0.7.2 Done: 2007-07-28 - Version 0.7.1 Done: 2007-05-13 - Version 0.7.0 Done: 2007-05-01 - Version 0.6.7.1 Done: 2007-03-29 - Version 0.6.6 Done: 2006-11-18 - Version 0.6.5 Done: 2005-01-16 - Version 0.6.2 Done: 2004-11-26 - Version 0.6.1version: Just save the source Done: 2000 – 0.1.8 and 0.2.2and press 'cmd' + 'R' in zxsp Done: 2000 – 0.1.8 and 0.2.2and it loads the new Done: 2008-05-26 - Version 0.7.2 Done: 2007-07-28 - Version 0.7.1 Done: 2007-05-13 - Version 0.7.0 Done: 2007-05-01 - Version 0.6.7.1 Done: 2007-03-29 - Version 0.6.6 Done: 2006-11-18 - Version 0.6.5 Done: 2005-01-16 - Version 0.6.2 Done: 2004-11-26 - Version 0.6.1version. If the Assemblerassembler finds errors then loading fails. An alert box pops up to indicate the case Done: 2000 – 0.1.8 and 0.2.2and the Assemblerassembler listing of pass 1 or pass 2 (whatever is appropriate) is saved for your inspection. ##### Writing .sna sources If you create a .Snapshots: .SNAsna Snapshotssnapshot, then setting up the Debugger: Registersregisters, system variables Done: 2000 – 0.1.8 and 0.2.2and BASIC program can be painful. A good idea is, to write the BASIC program on a Modifier keys: ZX SpectrumZX Spectrum, that is, in zxsp, Done: 2000 – 0.1.8 and 0.2.2and save a Snapshotssnapshot at the position where you want to start off. Then split the Snapshotssnapshot with a hexeditor into Debugger: Registersregisters (first 27 bytes) Done: 2000 – 0.1.8 and 0.2.2and screen, sysvars Done: 2000 – 0.1.8 and 0.2.2and BASIC program (length varies) Done: 2000 – 0.1.8 and 0.2.2and #insert these files into the main Assemblerassembler source files after #head Done: 2000 – 0.1.8 and 0.2.2and Writing .tap sources: #code#code respectively. The files for the following example are available here: sna_example.zip ###### Example for a .sna source
    #target Snapshots: .SNAsna

    #head   27
    #insert "empty_sna_head"

    Writing .tap sources: #code#code   $4000,$c000
    #insert "empty_sna_page1"

    ; note:
    ;   bc = return value
    ;   rst 16: print char in A

    OPKAN       equ     $1601       ; open channel in register A

    ; ------------- entry point ----------------------
    start:
                ld      a,2         ; Stream: main screen
                call    OPKAN       ; open channel

                call    printmsg
                defm    $0d, "Hello world", $0d, $00

                ld      bc,4711
                ret

    printmsg:   pop     hl
    printmsg_1  ld      a,(hl)
                inc     hl
                Done: 2000 – 0.1.8 and 0.2.2and     a
                ret     z
                rst     16
                jr      printmsg_1

    #end
##### Writing .tap sources If you create a .Snapshots: .TAPtap Snapshots: .TAPtape file, then you probably need 4 Writing .tap sources: #code#code blocks in your source, because a BASIC loader is required in most cases. The files for the following example are available here: tap_example.zip ###### Example for a .tap source
    headerflag:     equ 0
    dataflag:       equ $ff

    tCLEAR  equ     $FD             ; token CLEAR
    tLOAD   equ     $EF             ; token LOAD
    tCODE   equ     $AF             ; token CODE
    tPRINT  equ     $F5             ; token PRINT
    tUSR    equ     $C0             ; token USR
    tLET    equ     $F1             ; token LET
    tSAVE   equ     $F8             ; token SAVE

    #target Snapshots: .TAPtap

    Writing .tap sources: #code#code   0,17,headerflag     ; program header

            defb    0               ; program
            defm    "testloader"    ; make sure these are 10 bytes!
            defw    programsize     ; length of basic program Done: 2000 – 0.1.8 and 0.2.2and variables
            defw    10              ; line number for auto start
            defw    programsize     ; length of basic program without variables

    Writing .tap sources: #code#code   0,$100,dataflag     ; program data. size is truncated as required

    ; 60 CLEAR $6000
                defb    0,60                    ; line number
                defb    end60-($+1)             ; line length
                defb    0                       ; statement number
                defb    tCLEAR                  ; token CLEAR
                defm    '24576',$0e0000006000   ; number $6000, ascii & internal format
    end60:      defb    $0d                     ; line end marker

    ; 70 LOAD "" CODE $8000
                defb    0,70                    ; line number
                defb    end70-($+1)             ; line length
                defb    0                       ; statement number
                defb    tLOAD,'"','"',tCODE     ; token LOAD, 2 quotes, token CODE
                defm    '32768',$0e0000008000   ; number $8000, ascii & internal format
    end70:      defb    $0d                     ; line end marker

    ; 80 LET n = USR 32768
                defb    0,80                    ; line number
                defb    end80-($+1)             ; line length
                defb    0                       ; statement number
                defb    tLET,'n','=',tUSR       ; token LET, n, =, token USR
                defm    '32768',$0e0000008000   ; number $8000, ascii & internal format
    end80:      defb    $0d                     ; line end marker

    programsize     equ     $

    Writing .tap sources: #code#code   0,17,headerflag         ; CODE header

            defb    3               ; code
            defm    "testcode  "    ; make sure these are 10 bytes!
            defw    codeend-32768   ; length of data block
            defw    32768           ; original position
            defw    0               ; unused

    Writing .tap sources: #code#code   32768,32768,dataflag    ; CODE data

    ; note:
    ;   bc = return value
    ;   rst 16: print char in A

    OPKAN       equ     $1601       ; open channel in register A

    ; ------------- entry point ----------------------
    start:
                ld      a,2         ; Stream: main screen
                call    OPKAN       ; open channel

                call    printmsg
                defm    $0d, "Hello world", $0d, $00

                ld      bc,4711
                ret

    printmsg:   pop     hl
    printmsg_1  ld      a,(hl)
                inc     hl
                Done: 2000 – 0.1.8 and 0.2.2and     a
                ret     z
                rst     16
                jr      printmsg_1

    codeend     equ     $
    #end
###### #code As you may already know from the Assembler: zasmzasm documentation, the three arguments to Writing .tap sources: #code#code are code origin, block length (max.), Done: 2000 – 0.1.8 and 0.2.2and block type. The final checksum for each block is calculated Done: 2000 – 0.1.8 and 0.2.2and appended by Assembler: zasmzasm automatically. Writing .tap sources: #code#code blocks for #target Snapshots: .TAPtap are truncated as required. So it is not neccessary to know the exact length beforehand. Just insert your expected maximum sizes. Getting the proper internal representation for BASIC lines may be a little bit tricky. You may enter them in zxsp Done: 2000 – 0.1.8 and 0.2.2and save a Snapshotssnapshot which you can scrutinize in a hex editor. The basic layout should be obvious from the above example. After assembling a Snapshots: .TAPtap file zxsp loads this in the "open file" mode, that is, it does not insert it into the Tape recordertape recorder but tries to .TAP: Instant loading ".tap" filesinstant load it. For this to work, you must only use the Snapshots: .ROM MMU registers for the +128K / +2: ROM $0000rom Snapshots: .TAPtape loading routines. Whenever your code on the Snapshots: .TAPtap file starts to load with it's own routine, then .TAP: Instant loading ".tap" files Limitations of tzx files in zxsp: Instant loadinginstant loading does not finish, because this is not detected by the emulator. You had to insert the Snapshots: .TAPtap file into the Tape recorder: The built-in virtual tape recordervirtual tape recorder instead. Currently (zxsp 0.7.1) the Snapshots: .TAPtap file is always loaded into a Modifier keys: ZX SpectrumZX Spectrum 48k. This may be improved some day. |

[<prev] [top] [next>]