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 in A is written to standard output, and then a RET instruction is simulated. (In other words, call $8000 is like putchar A.)
* Whenever the PC reaches $8003, the machine tries to read a single byte from standard input. On EOF, the carry flag is set and A is left unchanged. Otherwise, the carry flag is cleared and A is set to the value read. Finally, a RET isntruction is simulated. (In other words, call $8003 is like getchar 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 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 $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 to call $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 the 76 byte doubles as a halt 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.
Category:Languages
Category:Golfing language
Category:2018