Z80 asm/disasm in Z80 asm [solution found]

The place for codemasters or beginners to talk about programming any language for the Spectrum.
Post Reply
User avatar
ketmar
Manic Miner
Posts: 612
Joined: Tue Jun 16, 2020 5:25 pm
Location: Ukraine

Z80 asm/disasm in Z80 asm [solution found]

Post by ketmar »

does anybody have standalone Z80 assembler and disassembler modules written in Z80 asm? i don't need advanced things, just a code to disasm one command, and to asm one command. speed is not a concern, but size is -- the smaller the thing, the better. there are alot of sources for various Speccy assemblers and disassemblers, but it is quite hard to extract the relevant code from there. sure, i can write it myself, but maybe somebody already did it, and wiling to share the code?

the idea is to incorporate those into my dsForth system, so ideally asm should take a buffer (and maybe callback to get label value), and produce machine code. and disasm should take a pointer, and produce disassembled string.

p.s.: readable and commented source code would be great. ;-)
dom
Drutt
Posts: 11
Joined: Sun Feb 10, 2019 11:08 am

Re: Z80 asm/disasm in Z80 asm, request

Post by dom »

For a disassembler try this one: https://github.com/z88dk/z88dk/blob/mas ... disz80.asm - it's just over 1k in size so definitely one of the smaller ones. The code was extracted from Utility3 but the history goes back further than that.

Can't help with an assembler unfortunately.
User avatar
ketmar
Manic Miner
Posts: 612
Joined: Tue Jun 16, 2020 5:25 pm
Location: Ukraine

Re: Z80 asm/disasm in Z80 asm, request

Post by ketmar »

thank you alot! i'll take a look at it.
User avatar
Einar Saukas
Bugaboo
Posts: 3070
Joined: Wed Nov 15, 2017 2:48 pm

Re: Z80 asm/disasm in Z80 asm, request

Post by Einar Saukas »

dom wrote: Thu Aug 06, 2020 10:46 pm For a disassembler try this one: https://github.com/z88dk/z88dk/blob/mas ... disz80.asm
This listing says:
The SUBSET editor David Barrow was able to trim only one byte from John Kerr's compact code. I've forgotten where so there's a challenge.
Right at the beginning:

Code: Select all

cp 255
jr nz, dizloop
It can be replaced with:

Code: Select all

inc a
jr nz, dizloop
User avatar
ketmar
Manic Miner
Posts: 612
Joined: Tue Jun 16, 2020 5:25 pm
Location: Ukraine

Re: Z80 asm/disasm in Z80 asm, request

Post by ketmar »

the magic spell "shorten this code" always makes Einar to appear with the solution. ;-)
dom
Drutt
Posts: 11
Joined: Sun Feb 10, 2019 11:08 am

Re: Z80 asm/disasm in Z80 asm, request

Post by dom »

[laughs] I have a feeling that bit of wrapper code isn't part of the "challenge". I think that code is actually trying to disassemble the following instruction, but the push ix gets in the way of that.
User avatar
Einar Saukas
Bugaboo
Posts: 3070
Joined: Wed Nov 15, 2017 2:48 pm

Re: Z80 asm/disasm in Z80 asm, request

Post by Einar Saukas »

Replace this:

Code: Select all

.XTRACT
	or a
	jr z,COPY
.SKIP
	bit 7,(hl)
	inc hl
	jr z,SKIP
	dec a
	jr nz,SKIP
.COPY
With this:

Code: Select all

.SKIP
	bit 7,(hl)
	inc hl
	jr z,SKIP
	dec a
.XTRACT
	or a
	jr nz,SKIP
.COPY
User avatar
ketmar
Manic Miner
Posts: 612
Joined: Tue Jun 16, 2020 5:25 pm
Location: Ukraine

Re: Z80 asm/disasm in Z80 asm, request

Post by ketmar »

wow. recently, R.T. Russell's Z80 BBC Basic became opensourced. and it seems to contan full-featured assembler. i quickly scanned the sources, and they seem to be very well written. so i will look if i'll be able to rip asm module. stay tuned, i will report here if i succeed converting it into something that could be used by providing input buffer implementation.

btw, that Basics seems to be quite cool. it would be fun to port it to Speccy (maybe to +3DOS, with support for disk files). i don't think that i will do that myself, so if you have nothing better to do with your life... ;-)
User avatar
ketmar
Manic Miner
Posts: 612
Joined: Tue Jun 16, 2020 5:25 pm
Location: Ukraine

Re: Z80 asm/disasm in Z80 asm, request

Post by ketmar »

yay, it is really great! by adding several i/o routines and very dumb expression parser (because it is using the same expression parser as the rest of the system) it correctly parsed "ld a,42", and even printed the generated machine code!

of course, it is far from being usable yet, but it looks really promising. also, it is less than 2kb of machine code. seems like a perfect hit.
+3code

Re: Z80 asm/disasm in Z80 asm, request

Post by +3code »

ketmar wrote: Thu Aug 13, 2020 5:35 am btw, that Basics seems to be quite cool. it would be fun to port it to Speccy (maybe to +3DOS, with support for disk files).
Look here:
http://mdfs.net/Software/Spectrum/BBCBasic/

But only tape support.
User avatar
ketmar
Manic Miner
Posts: 612
Joined: Tue Jun 16, 2020 5:25 pm
Location: Ukraine

Re: Z80 asm/disasm in Z80 asm, request

Post by ketmar »

intermediate results:

Image

assembler size: 752
assembler tables size: 443

sizes are without expression parser and label manager. i'm expecting the whole thing to fit into 2kb (math expression parsing can be quite big). even 2.5/3 kb is still ok -- it is not a big price to pay to have full-featured assembler in dsForth.

i may include expression parser into assembler module, leaving only label manager as external dependence, so people may avoid writing it again and again. it is still nicely isolated from the other asm code, so it would be possible to replace it with your own.

ah, the license. BBC Basic (Z80) is zlib-licensed, so the asm will use the same license too.


p.s.: contrary to my other projects, i'm avoiding self-modifying code here, so the whole thing could be used in ROMs.
User avatar
ketmar
Manic Miner
Posts: 612
Joined: Tue Jun 16, 2020 5:25 pm
Location: Ukraine

Re: Z80 asm/disasm in Z80 asm, request

Post by ketmar »

here is the soruce code repository, so you can watch my progress if you want to. ;-) please, note that it is heavy WIP yet.
User avatar
ketmar
Manic Miner
Posts: 612
Joined: Tue Jun 16, 2020 5:25 pm
Location: Ukraine

Re: Z80 asm/disasm in Z80 asm, request

Post by ketmar »

as usual, i was slightly overoptimistic. ;-) with expression parser (and without label manager) assembler size is ~2300 bytes. still acceptable, considering that expression parser is quite powerful (it supports operator precedence, parentheses, 16-bit mul/div/mod/shl/shr/and/or/xor/bitneg), and numeric parser supports wide range of prefixes and suffixes ("&"/"#"/"$"/"%"/"0x"/"0b"/"0o" as prefixes, "O"/"B"/"H" as suffixes). this number parser is more than 300 bytes by itself! ;-)

i am sure that Einar will be able to make it at least 50% smaller, but it is already good for me. ;-) my actual budget is ~3KB, and even with label manager it should still fit in 2500-2700 bytes.

i tried to comment the code, and make it easily reusable (including some comments in the original asm source), so feel free to look at it if you'll need built-in assembler for your z80 project. except for several runtime variables, the code is fully ROMable. it never calls any input/output routines too. IY register is used for input buffer pointer, tho, and IX register is used for output buffer pointer.

i will prolly make some more small changes to the code (like moving expression parser to the main asm module, and adding callback for getting label value into it), but there should be no big changes.

here's a k00l screenshot of the testing app, because people love screenshots!
Spoiler
Image
User avatar
ketmar
Manic Miner
Posts: 612
Joined: Tue Jun 16, 2020 5:25 pm
Location: Ukraine

Re: Z80 asm/disasm in Z80 asm, request

Post by ketmar »

i moved everything asm-related into one source file (assembler and expression parser), added missing code to expression parser so it now understands labels (i.e. calls label manager callback for that), and added simple label manager to show how it could be written.

i also dropped disasm module to the repository.

in case you missed it, here's the repo with the sources.
User avatar
ketmar
Manic Miner
Posts: 612
Joined: Tue Jun 16, 2020 5:25 pm
Location: Ukraine

Re: Z80 asm/disasm in Z80 asm [solution found]

Post by ketmar »

managed to strip out 30 bytes from assembler, and add "division by zero" check. less is more! ;-)
Post Reply