The project is gradually approaching a more-or-less complete form. Not everything works yet. The assembler itself was originally taken from a CL library, but in the process, it had to be rewritten from scratch. The previous version was good but overly convoluted: several levels of macros generated a large set of methods, each for one specific case (operation signature).
Quick Start
You need to add a standard initialization at the beginning of the source file. This can be done once per build session.
;; Load the assembler file (load "common/xiff/soot/asm.sot") ;; Switch the type system to Z80 (init-types 'z80)
Now Z80 data types are available, for example, uint16 or pointer (2 bytes in size).
Next, declare a module that will combine all segments into one logical block. This could be the entire program or a part of it. A module can consist of one or several segments, and segments can be written to one or more files.
(defmodule test-module)
Writing a Simple Program
Now you can write a simple program.
(zasm
(org #x0000)
$zero
(org #x8000)
$start
(jp 'label3)
(db 22)
(db (list 22 33 44))
(dw 64)
(ds 8)
(dw 'start)
(dw '(1 2 3))
(ascii "Hello World\n")
(align 16)
$label1
(jmp 'label1)
(jmp 'label2)
(ld @a @b)
$label2
(jmp 'label1)
(jmp 'label3)
(ld @c (+ 1 3))
(subroutine label3
(jmp 'label3)
(jmp 'label2)
(jmp 'label1)
(ld @a @c)
(jmp 0)
(jmp 'zero)
(ld @a [+ ix 5]) ; Should be: DD 7E 05
(ld [- iy 10] #xAA) ; Should be: FD 36 F6 AA
)
)
The org directive here is only for testing; in a real project, it might not be needed since each segment can have its own base address.
Finally, add the build directive:
(build test-module)
Running the Build
After launching:
> xiff Loaded asm-z80 ────────────────────────────────────────── BUILD SUCCESSFUL: test-module ────────────────────────────────────────── Segment: MAIN | Base: #0000 | Size: 32847 bytes ──────────────────────────────────────────
Generating a Listing
The following command saves a listing (with :print-listing #t, it also prints it to the screen):
(generate-module-listing test-module :print-listing #t)
The resulting listing:
--- Segment: MAIN | Base: #0000 --- 0000 | -------- | org 00h 0000 | zero: | 8000 | -------- | org 8000h 8000 | start: | 8000 | C3 3B 80 | jp label3 8003 | 16 | db 16h 8004 | 16 21 2C | db (22 33 44) 8007 | 40 00 | dw 40h 8009 | 00 00 00 00 00 00 00 00 | ds 08h 8011 | 00 80 | dw start 8013 | 01 00 02 00 03 00 | dw (1 2 3) 8019 | 48 65 6C 6C 6F 20 57 6F 72 6C 64 0A | ascii Hello World 8025 | -------- | align 10h 8030 | label1: | 8030 | 18 FE | jr label1 8032 | 18 01 | jr label2 8034 | 78 | ld a, b 8035 | label2: | 8035 | 18 F9 | jr label1 8037 | 18 02 | jr label3 8039 | 0E 04 | ld c, 04h 803B | label3: | 803B | 18 FE | jr label3 803D | 18 F6 | jr label2 803F | 18 EF | jr label1 8041 | 79 | ld a, c 8042 | C3 00 00 | jp 00h 8045 | C3 00 00 | jp zero 8048 | DD 7E 05 | ld a, (ix+5) 804B | FD 36 F6 AA | ld (iy-10), AAh
Exporting the Result
You can save all or selected segments to a file:
(save-module-hex test-module)
This creates two files.
1. Intel HEX format file:
:10800000C33B801616212C40000000000000000039 :1080100000008001000200030048656C6C6F20576F :108020006F726C640A000000000000000000000095 :1080300018FE18017818F918020E0418FE18F61820 :0F804000EF79C30000C30000DD7E05FD36F6AA10 :00000001FF
2. Symbol table file:
("test-module"
(:export label3 label2 label1 start zero)
(:symbols
(:public 32827 0 "label3" :label "MAIN" :meta ())
(:public 32821 0 "label2" :label "MAIN" :meta ())
(:public 32816 0 "label1" :label "MAIN" :meta ())
(:public 32768 0 "start" :label "MAIN" :meta ())
(:public 0 0 "zero" :label "MAIN" :meta ())
)
)
What's Next?
The data structures can already be saved to a buffer, but they cannot yet be used directly in the assembler. I hope this functionality will be working within a week.
To be continued...
h2w
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.