Chapter 26 - Using machine code

This chapter is written for those that understand Z80 machine code, the set of instructions that the Z80 processor chip uses. If you do not, but you would like to, there are books about it; two introductory ones are 'Programming the Z80' by Rodnay Zaks, published by Sybex at about £10 and 'Z80 and 8080 Assembly language programming' by Rathe Spracklen, published by Hayden at £5.25.

    The ultimate authority is the 'Z80 Assembly Language Programming Manual' together with the 'Z80-CPU, Z80A-CPU Technical Manual', published by Zilog at about £6 for the pair, but these could hardly be recommended for beginners.

    Machine code routines can be executed from within a BASIC program using the function USR. The argument of USR is the starting address of the routine, and its result is a two byte unsigned integer, the contents of the bc register pair on return. The return address to the BASIC is tacked in the usual way, so return is by a Z80 ret instruction.

    There are certain restrictions on USR routines:

    (i) On return, the iy & i registers must have the values 4000h & 1 Eh.

    (ii) The display routine uses the a', f', ix, iy & r registers, so a USR routine should not use these if compute & display is operating. (It is not even sade to read the af' pair.)

    The control, data & address busses are all exposed at the back of the ZX81, so you can do almost anything with a ZX81 that you can with a Z80. The ZX81 hardware might sometimes get in the way, though, especially in compute and display. Here is a diagram of the exposed connections at the back.

    A piece of machine code in the middle of memory runs the risk of being overwritten by the BASIC system. Some safer places are

    (i) In a REM statement: type in a REM statement with enough characters to hold your machine code, which you then poke in. Make this the first line in the program, or it might move about. Avoid halt instructions, since these will be recognized as the end of the REM statement.

    (ii) In a string: set up a long enough string, and then assign a machine code byte to each character. Strings are always liable to move about in the memory.

    In appendix A, the character set, you will find the characters and Z80 instructions written down side by side in order, & you may well find this useful when entering code.

    (iii) At the top of the memory. When the ZX81 is switched on, it tests to see how much memory there is and puts the machine stack right at the top so that there is no space for USR routines there. It stores the address of the first non-existent byte (e.g. 17K, or 17408, if you have 1K of memory) in a system variable known as RAMTOP, in the two bytes with addresses 16388 & 16389. NEW on the other hand, does not do a full memory test, but only checks up as far as just before the address in RAMTOP. Thus if you poke the address of an existing byte into RAMTOP, for NEW all the memory from that byte on is outside the BASIC system and left alone. For instance, suppose you have 1K of memory and you have just switched on the computer.

       PRINT PEEK 16388+256*PEEK 16389

tells you the address (17408) of the first non-existent byte.

    Now suppose you have a USR routine 20 bytes long. You want to change RAMTOP to 17388 = 236 + 256*67 (how would you work this out on the computer?), so type

       POKE 16388,236

       POKE 16389,67

and then NEW. The twenty bytes of memory from address 17388 to 17407 are now yours to do what you like with. If you then type NEW again it will not affect these twenty bytes.

    The top of memory is a good place for USR routunes, safe (even from NEW) and immobile. Its main disadvantage is that it is not saved by SAVE.


    Functions: USR

    Statements: NEW


1. Make RAMTOP equal to 16700 and then execute NEW. You will get an idea of what happens when the memory gets full.

Previous: Chapter 25    Next: Chapter 27