Z80golf

From Esolang
Jump to navigation Jump to search

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