--- title: "Zunk Assembler" id: 71696 type: "computer_media" slug: "zunk-assembler" url: "http://localhost/computer_media/zunk-assembler/" markdown_url: "http://localhost/computer_media/zunk-assembler.md" published_at: "2026-10-03T07:04:55+00:00" modified_at: "2026-10-03T07:17:46+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2026/10/image-11.png" excerpt: "A Z80 assembler for people who would rather not work in hex. Type mnemonics with decimal numbers and each line is assembled into memory as you enter it, with labels, a live disassembly, insert and fill, block moves between banks, CALL and JP relocation and a hex/decimal/binary converter. A short program at 57344, with the…" category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 2068" slug: "ts2068" taxonomy: "post_tag" url: "http://localhost/tag/ts2068/" - name: "Zunk Custom Electronics" slug: "zunk-custom-electronics" taxonomy: "post_tag" url: "http://localhost/tag/zunk-custom-electronics/" model: - name: "Timex/Sinclair 2068" slug: "ts-2068" taxonomy: "model" url: "http://localhost/model/ts-2068/" indiv: - name: "Larry Zunk" slug: "larry-zunk" taxonomy: "indiv" url: "http://localhost/indiv/larry-zunk/" genre: - name: "Programming" slug: "programming" taxonomy: "genre" url: "http://localhost/type/programming/" media_type: "Program" programmers: - name: "Larry Zunk" slug: "larry-zunk" taxonomy: "indiv" url: "http://localhost/indiv/larry-zunk/" download_url: "https://archive.org/download/timex-sinclair-software-archive/Zunk%20Assembler%20%281987%29%28Zunk%2C%20Larry%29%28TS2068%29%28US%29%28Program%29.zip" mediadate: "1987" producer_company: - id: 25169 title: "Zunk Custom Electronics" type: "company" url: "http://localhost/company/zunk-custom-electronics/" images: - url: "http://localhost/wp-content/uploads/2026/10/image-11.png" - url: "http://localhost/wp-content/uploads/2026/10/image-12.png" - url: "http://localhost/wp-content/uploads/2026/10/image-11.png" - url: "http://localhost/wp-content/uploads/2026/10/image-13.png" - url: "http://localhost/wp-content/uploads/2026/10/image-13.png" - url: "http://localhost/wp-content/uploads/2026/10/image-14.png" - url: "http://localhost/wp-content/uploads/2026/10/image-15.png" - url: "http://localhost/wp-content/uploads/2026/10/image-16.png" - url: "http://localhost/wp-content/uploads/2026/10/image-17.png" - url: "http://localhost/wp-content/uploads/2026/10/image-18.png" - url: "http://localhost/wp-content/uploads/2026/10/image-19.png" - url: "http://localhost/wp-content/uploads/2026/10/image-20.png" related_products: - id: 27936 title: "Assembler" type: "product" url: "http://localhost/product/assembler-6/" media_type_tags: "Programming" license: false --- # Zunk Assembler A Z80 assembler for people who would rather not work in hex. Type mnemonics with decimal numbers and each line is assembled into memory as you enter it, with labels, a live disassembly, insert and fill, block moves between banks, CALL and JP relocation and a hex/decimal/binary converter. [![Image](http://localhost/wp-content/uploads/2026/10/image-11.png)](http://localhost/wp-content/uploads/2026/10/image-11.png)A short program at 57344, with the label LOOP shown beside the line it marks. ### Loading The whole assembler is one BASIC program, `ASSEMBLER` (27,705 bytes). Its machine code is held in a REM at line 0. 1. Insert `Zunk Assembler.tap`. 2. Type LOAD "" and press ENTER. 3. The program sets RAMTOP to 57343 and starts the assembler. The listing opens at address 0, a disassembly of the ROM. It runs on a standard 2068 with no extra hardware. #### Memory | Address | Used for | | --- | --- | | 26710–55300 | The assembler (BASIC plus its machine code) | | 49209–51597 | Label table, inside the assembler; saved by Save Labels | | 57344–65367 | Free for your machine code, above RAMTOP | | 65368– | User-defined graphics, as normal | Assemble your code at 57344 or higher. Below that it would overwrite the assembler or BASIC’s workspace. [![Image](http://localhost/wp-content/uploads/2026/10/image-12.png)](http://localhost/wp-content/uploads/2026/10/image-12.png)The assembler as it starts: ROM address 0, with system variable names such as CHADD in place of numbers. ### The screen The top 20 lines are a listing of memory. The highlighted line at the top is the current location. While you are assembling, the magenta address marks the end of your code, and a bar shows ORG (where the program starts), END and LEN. A line the assembler can’t understand is shown in red. The three rows at the bottom are the menu: press the highlighted first letter of a command. #### Moving through memory | Key | Does | | --- | --- | | ENTER | Scrolls the listing up a line | | arrow keys | Step the current location | | CAPS SHIFT with an arrow | Fast scroll | | G Goto | Asks for an address and lists from there | | O Orig | Back to the start (ORG) of the program you’re assembling | | R Recl | Back to the last address you gave Goto | | J Jib | Asks for a DISPLAYED OFSET ADDR. and lists from it. The help calls it “changes displayed address”. | #### Display options | Key | Does | | --- | --- | | M Mode | Switches between disassembly and a byte listing: address, decimal value, and the character or keyword that byte would be | | SYMBOL SHIFT+B (`*`) | Names on or off: `LD HL,(CHADD)` or `LD HL,(23645)` | | SYMBOL SHIFT+M (`.`) | Relative jumps shown as a target address (`JR NZ,57346`) or as the raw byte (`JR NZ,251`) | | SYMBOL SHIFT+N (`,`) | In byte mode, show values as 1 or 2 bytes | | SYMBOL SHIFT+Z (`:`) | Sends the listing, starting at the top of the screen, to the 2040 printer, scrolling until you press a key | [![Image](http://localhost/wp-content/uploads/2026/10/image-11.png)](http://localhost/wp-content/uploads/2026/10/image-11.png)Byte mode: the same program as decimal values. 62 is the LD A opcode; the column on the right shows each byte as a character or keyword. ### Writing code 1. Press G and type the address to start at, for example `57344`. 2. Press A (Asem). The screen says BEGIN NEW ASSEMBLY PROGRAM and the prompt MNEMONIC-> 57344, shows where the next instruction goes. 3. Type one instruction and press ENTER. It is assembled into memory at once and the prompt moves on. 4. Press ENTER on an empty line to get the menu back. C (Cont) picks up at the end of the program and adds more lines (CONTINUE ASSEMBLY PROGRAM). [![Image](http://localhost/wp-content/uploads/2026/10/image-13.png)](http://localhost/wp-content/uploads/2026/10/image-13.png)Assembling. The red bar shows ORG, END and LEN; the prompt shows the next address. #### Rules for what you type | Write | Meaning | Example | | --- | --- | --- | | Numbers | Decimal, and **at least three characters long**. Pad with zeros or add `.0`. | `LD A,007` · `LD B,5.0` · `OUT (254),A` | | `£NAME` | Defines a label, 3 to 10 letters, at the current address. Type it on its own line before the instruction it marks. The `£` is SYMBOL SHIFT+X. | `£LOOP` then `JR NZ,LOOP` | | `LET` | Gives a label a value | `LET POOP=16384` | | `BYT` | Puts one byte into the code | `BYT 230` | | `NUM` | Puts a 16-bit number into the code | `NUM 16384` | | `RSV` | Reserves *n* bytes; useful when editing a block | `RSV 032` | | `TBL` | A table of 16-bit numbers or labels | `TBL 003,465,DEFIL,5436,LOOP` | | `IX;``IY;` | Turns the HL instruction that follows into its IX or IY form | `IX;LD HL,(DEFILE)` | | `"` | Puts text into the code | `"HIT ENTER` | | Expressions | Simple arithmetic on labels and numbers | `LD A,(POOP+5.0)` | Give `JR` and `DJNZ` the label of the target and the assembler works out the offset. Typing the `NOT` keyword (SYMBOL SHIFT+S) at the prompt throws away the last entry. **Not sure of the syntax?**Press S (Sear) at the menu and type part of an instruction. The assembler lists every form it accepts that matches, with `e` standing for a number. `LD A,(` gives `LD A,(BC)`, `LD A,(DE)`, `LD A,(e)` and `LD A,(HL)`. Z (Z80s) scrolls through the whole instruction set. **Keep entries short**Type one instruction per entry. In testing, a very long line of junk (forty-odd characters that weren’t an instruction) overwrote part of the assembler’s own lookup routine, and good instructions assembled as nonsense afterwards. If that happens, reload the program. ### Changing code #### Insr: insert instructions Goto the instruction you want to insert in front of and press I. A magenta bar marks the insertion point and the prompt says INSERT MNEMONICS AT CURSOR. Each instruction you type is placed there, and everything from that point to the end of the program moves down to make room. When you press ENTER on an empty line, the assembler goes back over the program and corrects every relative jump (`JR`, `DJNZ`) whose distance has changed. **Check JP and CALL:**Absolute `JP` and `CALL` targets are not changed by an insert. In testing, a `JP 57346` still pointed at 57346 after a NOP was inserted at that address. Correct them by hand, or reassemble those lines. [![Image](http://localhost/wp-content/uploads/2026/10/image-13.png)](http://localhost/wp-content/uploads/2026/10/image-13.png)After inserting a NOP at 57348 and pressing ENTER: the loop’s JR NZ has been corrected from 251 to 250. #### Dele: fill a block D asks for address to delete code, the number of bytes and a code, then fills the block with that value. Use `000` to blank it to NOPs. It doesn’t close up the gap. #### Poke P writes numbers at the current location. Each entry goes into the next address. Press ENTER on an empty line to stop. The help describes it as an 8- or 16-bit poker. #### Xfer: move a block, between banks too [![Image](http://localhost/wp-content/uploads/2026/10/image-14.png)](http://localhost/wp-content/uploads/2026/10/image-14.png)Xfer copies 10 bytes from 57344 to 60000 in home memory (chunks 0 and 0). X asks for SOURCE CHUNKS, DEST. CHUNKS, SOURCE ADDRESS, DEST. ADDRESS and BYTES TO COPY, shows them all, and asks OK (Y/N). The chunk numbers select memory banks in the same way as the 2068’s bank register (port 244). Each bit picks the dock bank for one 8 KB chunk: 1 for 0–8191, 2 for 8192–16383, and so on up to 128 for 57344–65535. Use 0 and 0 for ordinary memory. #### Relocating CALLs and JPs Press SYMBOL SHIFT+R (`<`), a key that isn’t on the menu. The prompt is RELOCATE CALLs & JPs (0=ABORT). Type the address the program will run at. Every `JP` and `CALL` in the program that points into it is changed to match, and the listing then shows the code with its new addresses. The bytes themselves stay where they are, so finish with Xfer to move them. In testing, relocating a program at 57344 to 57345 changed `JP 57346` to `JP 57347`. **0 aborts**Answer `0` to back out. An address that makes no sense (we tried 1) drops you into the file menu. Press ENTER to go back in; your work is still there. #### Enab: choose banks E asks Enable (IN 244,n) TO and sets the 2068’s bank register, port 244, to your number (the help: “enable chunks”). The menu shows the current setting as Enab=. Set it back to 0 for normal memory. ### Labels and variables #### Labl L asks for a name. Then NUMERIC POINTER asks for its value. This is the same as `LET` while assembling. Type a space instead of a name to list all labels in alphabetical order, with the program’s ORG, END and length. The list then asks DELETE A LABEL ?. Type a name to delete it, or press ENTER to leave. **Deleting a label**: The first label that *begins* with what you type is deleted. Typing `L` deleted `LOOP`, not a label named `L`. Type the full name and check the list afterwards. #### Kil K erases every label at once. There is no “are you sure”, so save your labels first. [![Image](http://localhost/wp-content/uploads/2026/10/image-15.png)](http://localhost/wp-content/uploads/2026/10/image-15.png)The label list. Labels can hold addresses (LOOP) or any value (BORDER = 254). #### Vars: a watch window [![Image](http://localhost/wp-content/uploads/2026/10/image-16.png)](http://localhost/wp-content/uploads/2026/10/image-16.png)Vars opens a live list beside the listing. BORDCR has been added at the bottom. V opens a window of memory locations with names and their current values. It starts with 19 system variables (VARS, E LINE, PROG, CHANS and so on). V again closes it. While it is open, A (Assign) adds a variable: give a VARIABLE NAME, its VARIABLE LOCATION, and 1 OR 2 BYTE VAR. D deletes one. ### Looking around | Key | Command | What it does | | --- | --- | --- | | F | Find | Searches memory for a sequence of byte values. Enter one number per prompt (codes to search for), then ENTER on an empty line to start. The listing moves to the first match. It is slow: a two-byte search took about three minutes. | | T | Text | Shows memory as characters from the current location. ENTER continues and Q stops. Good for finding messages in code. | | S | Sear | Searches the assembler’s syntax table for instructions containing what you type. | | Z | Z80s | Scrolls the whole instruction set in two columns. Any key pauses; Q quits. | | N | Numc | Number converter. Type a decimal number, or add `H` for hex or `B` for binary. It shows the value in decimal, hex, binary, and as low and high bytes. ENTER on an empty line returns to the menu. | | H | Help | Five pages: input rules, the menu, and the scrolling keys. | [![Image](http://localhost/wp-content/uploads/2026/10/image-17.png)](http://localhost/wp-content/uploads/2026/10/image-17.png)Sear for `LD A,(`. [![Image](http://localhost/wp-content/uploads/2026/10/image-18.png)](http://localhost/wp-content/uploads/2026/10/image-18.png)Text at 26715: the assembler’s own instruction table. ### Testing code U (UsrC) asks RANDOMIZE USR (0=bort). Type the address to call. When your code returns, the screen says RETURN from USR OK. Press ENTER to carry on. **No safety net:**The help warns “tests code! no error traps!”. A routine that never returns, or one that overwrites the assembler, crashes the machine. Save your code and labels first. SYMBOL SHIFT+U (the `OR` keyword), also missing from the menu, calls address 60000. That’s where Zunk’s ZEBU utilities live. Don’t press it unless something safe to call is there. [![Image](http://localhost/wp-content/uploads/2026/10/image-19.png)](http://localhost/wp-content/uploads/2026/10/image-19.png)The test program ran and came back. ### Saving and loading Q (Quit) leaves the assembler for the file menu at the bottom of the screen. ENTER there goes back into the assembler, with your program, labels and settings as you left them. | Key | Does | | --- | --- | | L | Load a CODE file from tape | | S | Save: opens the save menu | | V | Verify the next CODE file on tape against memory | | Q | Stop the program. GO TO 10 brings the menu back. | | ENTER | Back to the assembler | | R | Not shown on the menu: restarts the assembler as if freshly loaded | [![Image](http://localhost/wp-content/uploads/2026/10/image-20.png)](http://localhost/wp-content/uploads/2026/10/image-20.png)Load, second question: ENTER loads at the address the file was saved from. #### The save menu S shows SAVE Code Labels Prog File:”name”CODE loc,len. Each save shows the SAVE it is about to do and asks OK (Y/N). Tape names are cut to 10 characters. | Key | Saves | | --- | --- | | C Code | Asks CODE LOC, LEN CODE and CODE NAME, then saves that block. The assembler remembers it for *File*. | | F File | Saves the remembered block again under the same name, with no questions. Handy for saving each new version. | | L Labels | Saves the label table, 2,389 bytes from 49209, which also records ORG and END. The first time it asks for a name. After that it offers the same name; answer N to choose another. | | P Prog | Saves the whole assembler as `ASSEMBLER`, set to start itself. Your labels are inside it, so this is a quick way to keep a working copy. | #### Loading 1. At the file menu press L. Type the tape name, or press ENTER alone to load the next CODE file that comes along. 2. The next question gives three choices: type `NOT` to abort, type an address to load there, or press ENTER to load at the address the file was saved from. A label file loads straight back into the label table at 49209. Load your code file and its label file, press ENTER, and you are back where you left off. **Not SPACE:**Answer “Start tape, then press any key” with a letter. SPACE is BREAK and stops the save. ### Key reference | Key | Menu | Does | | --- | --- | --- | | A | Asem | Start a new program at the current location | | C | Cont | Carry on assembling at the end of the program | | D | Dele | Fill a block with a value | | E | Enab | Set the bank register (port 244) | | F | Find | Search memory for byte values | | G | Goto | List from an address | | H | Help | Five help pages | | I | Insr | Insert instructions at the cursor | | J | Jib | Change the displayed address | | K | Kil | Erase all labels | | L | Labl | Add, list or delete labels | | M | Mode | Disassembly or byte listing | | N | Numc | Hex/decimal/binary converter | | O | Orig | List from the program’s ORG | | P | Poke | Write values from the current location | | Q | Quit | To the file menu | | R | Recl | List from the last Goto address | | S | Sear | Search the instruction syntax | | T | Text | Show memory as characters | | U | UsrC | Run code at an address | | V | Vars | Watch window on or off | | X | Xfer | Copy a block, between banks too | | Z | Z80s | Scroll the instruction set | | SYMBOL SHIFT+R | — | Relocate CALLs and JPs | | SYMBOL SHIFT+B | — | Names in the listing on or off | | SYMBOL SHIFT+M | — | JR shown as address or offset | | SYMBOL SHIFT+N | — | 1- or 2-byte values in byte mode | | SYMBOL SHIFT+Z | — | Print the listing on a 2040 | | SYMBOL SHIFT+U | — | Call address 60000 (ZEBU) | ### Tips - Put your first instruction at 57344. Everything from there to 65367 is yours. - Give names to the addresses and values you use with L or `LET` before you start. The disassembly then reads like your source. - Use labels for jump targets rather than numbers. Insert keeps relative jumps right, but numeric `JP` and `CALL` targets need checking after an insert. - Leave a little `RSV` space at the ends of routines so you can add to them later without moving everything. - Save the code with *Code* once, then press F (File) after each change. Save the labels too; together they bring you back to exactly where you were. - Add your program’s own variables to the Vars window and check them after a test run with UsrC. - Forgot how an instruction is written? Sear it before you type it, rather than waiting for a red line.