Z80golf
Z80golf is a very simple fantasy Zilog Z80 machine designed for code golf, used on anarchy golf. You can submit bytecode as "z80" there (example submission).
Specification
- Z80golf programs are binary files (
.z8b
). On initialization, the binary is copied to$0000
, and the rest of memory (until$FFFF
) is padded with zeroes. All the registers are zero as well: AF, BC, DE, HL, IX, IY, SP (stack pointer), and PC (programming counter). - Whenever the PC reaches
$8000
, the value inA
is written to standard output, and then aRET
instruction is simulated. (In other words,call $8000
is likeputchar A
.) - Whenever the PC reaches
$8003
, the machine tries to read a single byte from standard input. On EOF, the carry flag is set andA
is left unchanged. Otherwise, the carry flag is cleared andA
is set to the value read. Finally, aRET
isntruction is simulated. (In other words,call $8003
is likegetchar A
.) - The program keeps running until
HALT
is executed.
Examples
Hello world
Ungolfed, at a hefty 27 bytes. The best score is 19 bytes, and a fun puzzle to figure out!
start: ld a, (ix+hello) or a jr nz, okay halt okay: call $8000 ; putchar inc ix jr start hello: db "Hello, world!"
Cat program
A naive cat program:
start: call $8003 ; getchar jr nc, okay halt okay: call $8000 ; putchar jp start
Which is assembled into a 12-byte submission:
cd 03 80 30 01 76 cd 00 80 c3 00 00 (Actually, it's 10 bytes if you leave off the trailing zero bytes!)
But we can do it in 7 bytes.
push de call $8003 jr nc, okay halt okay:
We let the PC run through a sled of NOP
s from $0007
to $8000
; DE is always zero in this program, so push de
will make sure that we return to the start of the program after executing putchar
.
Duplicate characters by kodera
Here is a very clever short submission by kodera. It is like the above program, but it prints every character twice. It reuses almost all of itself as addresses that the stack pointer underflows into.
ld sp,hl ; f9 ld a,h ; 7c jp nc, $8003 ; d2 03 80 xor a ; af halt ; 76
- The first instruction sets SP to 0.
- The second instruction sets A to 0.
- Carry is initially not set, so we jump to
getchar
. - This loads the character into A, then returns to
(SP) = $7cf9
; SP is now 2. - We run into
$8000
, printing A, and return to(SP) = $03d2
; SP is now 4. - We run into
$8000
again, printing A for the second time, and return to(SP) = $af80
; SP is now 6. - The PC overflows into
$0000
and the program starts over.
This prints a spurious \x00\x00
before terminating, but anagol doesn't (didn't?) seem to care.
Tips
- You can use the single-byte
rst 38h
(FF
) instruction as a shorter alternative tocall $8000
(3 bytes) if your program is shorter than 56 bytes. - You can reuse addresses as code. This solution contains
jp nz, $7f76
, which is functionally identical to a jump to$8000
, but the76
byte doubles as ahalt
instruction.
External resources
- mokehehe's Z80golf implementation. (Try
cd src && make
, then./z80golf echo.z8b < input
.) - Lynn's GitHub mirror of the above.
- z80 results on anarchy golf.
- z80asm, to turn your solutions into bytecode.