MACHINE CODE TESTER
by T.E. Watts
from ZX COmputing, May 1986

If you're tired of crashing code, here's a routine that allows you to
check the effects of your m/c programs before you run them.


Everyone who has attempted to program in machine code will be aware of
(if not very familiar with) the routine: enter code ... save code ...
test ... CRASH! ... unplug ... plug in ... reload ... print addresses
and trace ... amend ... save ... test ... CRASH!! ... (expletive
deleted) and so on.

This program saves all the frustration and a great deal of time by
tracing your machine code routines step by step, showing the contents
of the registers before and after each instruction and printing the
contents of any address. The registers can be preset to any desired
value as can the stack pointer. A separate stack from that used by the
Basic system is set up which avoids problems of stack balancing and
makes it very easy to check that your routine does balance the stack.
The address of the instruction to be executed can, of course, be
changed and a facility is included to put an address on the stack or
to change the address to the last entry on the stack. The alternate
register set is not printed, but is preserved and can be used.

Unfortunately, owing to the screen usage of the program and (if they
are used) the complexity of the ROM routines, screen printing routines
will produce little or no visible results. However, the state of all
registers and all stores is known at all stages so that in practice
there is no real difficulty in testing such routines.

The heart of the program is the machine code routine at address 6D5E
(decimal 27998) which is accessed via line 710. As the alternate
register pair H'L' is used by the USR routine, provision has been made
to preserve and restore its contents by the routines at addresses
6D7F-6D83 and 6D90-6D97. The rest of the code is quite straightforward
and should present no difficulty.

The Basic program sets up initial values for the registers and stack
pointer and prints these values. It also keeps track of the address of
the next instruction and copies the appropriate number of bytes to
addresses 6D88-6D8B. The construction of the program is outlined in
Table 1, functions are listed in Table 2 and variables in Table 3.
[None of these tables were printed in the magazine. JimG]


Entering the program

You should first enter the Basic program and after checking the
listing for errors save it with the command SAVE "mctp" LINE 1.

The machine code routine (Listing 2) can then be entered. Carefully
check your loaded code (which shouldn't take too long since the
routine is so short) and save it immediately after the Basic program
when prompted.


In use

When saved as above, the command LOAD "mctp" will load and autostart
the program. The machine code routine is loaded if necessary and the
program stops with the question "Do you want instructions?". You are
then asked if you wish to load a named machine code routine; this will
normally be the routine you want to test and it should be saved on
tape so that the command LOAD "name" CODE will load it to the correct
location. The location of your code must be above 6DA4 (decimal 28068).

Apart from the name of a routine to be loaded and one other option
which we will come to shortly, all input to the program is either a
number or a single letter, "y" or "n". All numbers may be in either
decimal or hexadecimal; hex numbers must be either 2 or 4 digits long
and followed by "h" (eg. 4 can be input as "4" or "04" or "04h" or
"0004h"). Letters, whether as part of a hex number or a reply to a
question, may be either upper or lower case. But remember that there
is no syntax check on numbers and an entry such as "04D1" (i.e. "h"
missing from a hex number) will produce the report "440.1 : Nonsense
in Basic" or a similar error halt. If this happens then restart the
program by typing "GO TO 600".

The program now needs to be told the address that it starts testing
from and initial values for all registers; a location in an unused
part of RAM must be selected for use as the stack.

The program then enters the main loop. The current location is printed
in both decimal and hexadecimal and the contents of this and the next
three locations are displayed in hex code. You now enter the number of
bytes in the instruction or a code value to get to the required
facility. The result of entering the different possible values is as
follows:


Number from 1 to 4:

The number of bytes specified is executed and the state of the
registers after execution is displayed.


Zero entered:

The program asks "Skip/go to?". Entering 0 to 4 causes the current
address to be increased by the number. Entering a number higher than
four changes the current address to the number entered and will ask if
you wish to put a number on the stack (use this facility if the
instruction is CALL), entering "s" changes the current address to the
last entry on the stack and increments the stack pointer (use this
facility if the instruction is RET). All these options are followed by
the opportunity to change the contents of the registers and stack
pointer. A number less than zero can be entered and this will stop the
program.


Number greater than 4:

This is the same as entering more than four in response to the
'skip/go to' question above. The current address is changed and you
can put a number on the stack. The register contents can be changed.

The program stops if you try to enter any number less than zero. All
the above options (except those which stop the program) are followed
by the question "Print locations?". Entering "y" produces the response
"Start at?" followed by "How many/End at?" and the appropriate
locations are printed in decimal and hex (if the second number is
greater than the first then the program assumes it to be an end
location). After printing, the program returns to the question "Print
locations?" and further locations can be printed. Entering anything
other than "y" takes the program back to the start of the main loop.

If you have stopped the program and you wish to restart at the same
location and with the same data then use the command GO TO 600.
RUNning the program will require you to reinitialise the registers and
stack pointer; however any data above location 6D5D (27997) will be
unaffected and the test in line 5 will avoid the necessity of
reloading the program's machine code routine. You can, of course, RUN
the program in order to load and test a different machine code routine.


Testing routines which change address

When testing a routine which includes instructions such as CALL, RST,
JP JR, RET you should not execute the jump instruction but should
change the next address to the appropriate value, and for CALL
instructions put the return address (usually current address + 3) on
the stack. If you have done this for a CALL then the corresponding RET
is followed by executing zero bytes and entering "s" in response to
the "Skip/go to" question.

This action is necessary because executing an instruction which
transfers control to another address will take the program counter
outside the limits of the test control routine with no guarantee that
control will ever be properly returned. Of course a tested routine can
be called but you should be certain that it is fully tested and always
returns satisfactorily.

