zxsp comes with a built-in Done: 2008-05-26 - Version 0.7.2 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.spdns.de/Develop/projects/zasm/. Source Done: 2000 – 0.1.8 and 0.2.2and binary distributions are in subdirectory k1.spdns.de/Develop/projects/zasm/distributions/ Done: 2000 – 0.1.8 and 0.2.2and documentation in subdirectory k1.spdns.de/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.spdns.de/cgi-bin/zasm.cgi. zasmAssembler: 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 zxspWhen 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 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 sourcesIf 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 sourcesIf 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 sourceheaderflag: 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 #codeAs 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 |