Basic Tips‎ > ‎

z80

This page describes the specification of z80 in golf.shinh.org briefly and a simple example. Please check wikipedia for the basic information of z80. Also, please search web sites for more detailed information. For example, this site seems to contain detailed information including instruction set.

The z80 is an 8-bit CISC CPU with 16 bits address space. There are eight 16-bit registers: AF, BC, DE, HL, IX, IY, SP (stack pointer), and PC (programming counter). You can use the first 6 registers as general purpose registers. You can also use the half of 16-bit registers as 8-bit registers. Their names are A, F, B, C, D, E, H, and L. If you modify the values of A or F, the value of AF is changed. Also, if you modify the value of AF, the values of A or F are changed. One of the important key of z80 golf is the A register. Since the A register is defined as the accumulator (and the z80 is CISC), there are many instructions which processes the A register. The table of z80 instructions will help you to find short instructions.

The basic specification of the environment of golf.shinh.org is given by mokehehe. You can download the source code of the emulator from here (no English doc inside this package). This emulator is based on fMSX by Marat Fayzullin.

We'll see the minimal code for echo challenge as an example code to understand the specification. The minimal submission of echo challenge is 7 bytes. The code is

0000: D5             PUSH  DE
0001: CD 03 80  CALL  $8003
0004: 30 01        JR    NC,$0007
0006: 76             HALT

(thanks for yaneurao!). You may be surprised since there are no call for putchar (0x8000). This code runs as follows:

1. (0000) Push DE into the stack. The DE is always 0 in this program. This means push 0 (but this expression is shorter). So, the stack is [TOP - 0 - BOTTOM] after this operation.
2. (0001) Calls getchar. Recall that the emulator calls getchar if the value of programming counter becomes 0x8003. After this operation, the stack is [TOP - 4 - 0 - BOTTOM] since call pushes the return address.
3. (8003) The emulator executes getchar. If it returns positive or zero, the return value will be stored in A register. Otherwise (EOF is detected), the emulator sets 1 to the carry bit. Then, the program returns from getchar using the address stored in stack top, which is 4. After this operation, the stack is [TOP -  0 - BOTTOM], and A register may be set (otherwise carry bit must be set).
4. (0004) JR NC means "if carry bit is not set, jump to the operand address". If the input was EOF, the programming counter will become 0x0006 (step7) after this. Otherwise, we jump to 0x0007 (step5).
5. (0007) There are no operations defined by your code. Since 00 means NOP in z80 and the memroy is cleared by zero, the programming counter advances without no operations. Finally the value of programming counter becomes 0x8000.
6. (8000) The emulator executes putchar using A register. Since A register was filled by getchar, we will put the input charactor without modifications. Like other functions, putchar also returns to the address of stack top. Please recall the step 1. We pushed 0 on the top of the stack. So, we will return to step 1. In this way, we could create a loop!
7. (0006) If EOF is detected in step3, the next step of step4 is here. HALT stops the program. Please note that you always need to use this instruction to stop your code.

Sorry for this not-well-organized and short descriptions. Please feel free to reorganize this doc, add more info, or fix English mistakes.

Tips

* Use RST 38H instead of CALL 8000 if the size of your code is less than 56B.

There 8 instructions which call fixed address, RST 0H, 8H, 10H, 18H, 20H, 28H, 30H, and 38H. Since they consume just 1 byte, we can save 2 bytes by changing CALL to RST. So, if the size of your code < 56B (0x38), CALL 38H is as almost same as CALL 8000H since all instruction between 38H to 8000H is NOP. One difference is speed. RST 38H is slower than CALL 8000H since we need to process >30k NOPs.

* HALT == 76H

In this golf site, all z80 program must stop by HALT. You may be surprised since the following one-instruction code outputs two '\x00' and then stops.

 0000: 36 76    LD (HL),76H

The trick is the magic number 76H. This number is the instruction code of HALT. The LD removes itself and writes HALT and NOP.

TODO: write why there are two outputs.

Comments