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 inAis written to standard output, and then aRETinstruction is simulated. (In other words,call $8000is 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 andAis left unchanged. Otherwise, the carry flag is cleared andAis set to the value read. Finally, aRETisntruction is simulated. (In other words,call $8003is likegetchar A.) - The program keeps running until
HALTis 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 NOPs 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
$8000again, printing A for the second time, and return to(SP) = $af80; SP is now 6. - The PC overflows into
$0000and 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 the76byte doubles as ahaltinstruction.
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.