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 . On initialization, the binary is copied to, and the rest of memory (until  ) 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, the value in   is written to standard output, and then a   instruction is simulated. (In other words,   is like  .)
 * Whenever the PC reaches, the machine tries to read a single byte from standard input. On EOF, the carry flag is set and   is left unchanged. Otherwise, the carry flag is cleared and   is set to the value read. Finally, a   isntruction is simulated. (In other words,   is like  .)
 * The program keeps running until  is executed.

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 s from   to  ; DE is always zero in this program, so   will make sure that we return to the start of the program after executing.

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.
 * This loads the character into A, then returns to ; SP is now 2.
 * We run into, printing A, and return to  ; SP is now 4.
 * We run into  again, printing A for the second time, and return to  ; SP is now 6.
 * The PC overflows into  and the program starts over.

This prints a spurious  before terminating, but anagol doesn't (didn't?) seem to care.

Tips

 * You can use the single-byte   instruction as a shorter alternative to   (3 bytes) if your program is shorter than 56 bytes.
 * You can reuse addresses as code. This solution contains, which is functionally identical to a jump to  , but the   byte doubles as a   instruction.

External resources

 * mokehehe's Z80golf implementation. (Try, then  .)
 * Lynn's GitHub mirror of the above.
 * z80 results on anarchy golf.
 * z80asm, to turn your solutions into bytecode.