MONITOR
by Jon Ellis
from ZX Computing November 1986

If you're writing your own machine code programs you'll need a good
monitor to help debug them - so here it is.


[NOTE: I made a small correction to the text in the program, replacing the]
[incorrectly spelled phrase "Number base togle now" with the phrase       ]
["Number base toggle is".                                             JimG]


Over the course of writing many machine code routines I realised that
I had no good program for debugging them. So, If you haven't got a
program - write it yourself. Here is that program, a monitor which
should provide all the functions you would normally need in the course
of debugging a machine code program.

Numbers can be entered In either hex or decimal, regardless of the
state of the number base toggle. Decimal numbers must all be five
digits long, being bulked out with leading zeros if necessary. To
enter a number in hex, type '&' as the first character, and then the
number in four hex digits, again using leading zeros if necessary. If
only one byte is required then the low byte is taken, ie. if you enter
a number greater than 255 when the Monitor is expecting a number in
the range 0 to 255, then your input will be taken as modulo 256.

After most functions have been executed the Monitor will pause for you
to examine the results of the function, if any. To terminate this
pause press either 'X' or BREAK and you will then be returned to the
menu.

The Monitor is written so that you can treat the Spectrum as a Z80
processor only as far as possible. This means that, although the
Spectrum operating system requires the IY register to have the value
23610 at all times, unless your routine is going to use the operating
system, you may ignore this requirement. A similar situation occurs
with the HL pair. The registers that are used when your routine is run
are not those used by the Monitor or the Spectrum ROM.

To abort a function you should press BREAK which will return you to
the menu.


Monitor Functions

The monitor offers a menu of 18 functions:

1) Alter Memory. This function will prompt for a start address (see
note on the input of numbers), and the program will then print the
address and its contents. The Monitor will then wait for you to input
the new value before moving on to the next byte. When you have filled
up a screen, press 'X' for another page. At any time you may press
BREAK to escape.

2) Breakpoint. This function enables you to place an instruction in
the middle of the code that is being debugged, which causes execution
to be stopped and control returned to the Monitor so that you can
alter/inspect the registers etc. The breakpoint instruction is three
bytes long, and thus two breakpoints should not be inserted less than
four bytes apart otherwise a crash might occur on execution. The code
that occupied the three bytes overwritten by the breakpoint
instruction is stored, and will be replaced when the breakpoint is
deleted. When you select this function from the menu it will prompt
for the address at which the breakpoint is to be inserted. A total of
nine breakpoints may be used at once. If all nine are in use then
nothing will happen when the function is selected.

3) Convert Number. This function will prompt for the input of a number
and then print the number in decimal, hex, and binary.

4) Delete Breakpoint. When selected, this command will display all
nine of the breakpoints, and then ask for the number of the breakpoint
to be deleted. (Note that you should enter the number of the
breakpoint (1-9), not its address). The three bytes that were
overwritten will then be replaced.

5) Examine Stack. The Monitor provides 40 bytes of stack space solely
for use by the object program. On entering the Monitor or resetting
the registers, the stack is reduced to one word in length, this word
being a return address inside the Monitor, which should prevent a
crash in the event of a RET instruction being executed at the end of
the object program. On selection, this function displays all the words
currently on the user stack.

6) Fill Memory Block. This command allows you to fill a block of
memory with a specified value. It prompts for a start address, the
length of the block to be filled, and the byte to be used.

7) Jump to Routine. The function will prompt for the address to be
jumped to, and execution will continue from this address using the
values of the user registers (see later). This function is to allow
for the object code to be tested. Ideally a breakpoint should be used
at the end of the code to return to the Monitor, in which case the
report "BREAK at (address)" will be displayed. However, a RET
instruction should also work providing that the routine has used the
stack correctly.

8) Look at Breakpoints. This function displays the addresses of each
of the nine breakpoints, an address of 0 indicating that the
breakpoint is unused.

9) Move Memory Block. This command allows you to copy blocks of memory
to other areas. It prompts for the start address of the block, the
start of the destination area, and the length of the block to be
copied.

10) Number Base Toggle. This toggle determines the base in which all
numeric output from the monitor will be displayed. It toggles between
hex, decimal and binary. Only some output can be displayed in binary
due to the length of a binary word (16 characters), other output being
displayed in hex. The toggle defaults to decimal.

11) One-Step Routine. This is probably one of the most useful
functions. It enables you to step through the object code one
instruction at a time, whilst keeping track of the user register
values. The Monitor will prompt for a start address, and will commence
stepping from that address, updating the register display after each
instruction and then pausing for you to inspect the registers, To move
to the next instruction, press 'X'. To escape, press BREAK.

12) Printers Toggle. When toggled to ON, this causes output from the
View Memory function to be dumped to the ZX Printer. The toggle
defaults to OFF.

13) Quit. Returns control to BASIC.

14) Register Display. This function displays the values of the user
registers, both the normal and the alternate set. The current values
of the interrupt vector register, I, and the memory refresh register
R, are also displayed. The value given for the program counter, PC,
refers to the last instruction executed. The value of the stack
pointer, SP, that is displayed refers to the user stack. The flags
register of the normal AF pair is shown expanded into bit format, with
each of the six flags labelled. The value of the maskable interrupt
flip-flop is also shown, the interrupts being enabled or disabled as
appropriate when the user code is executed.

15) Specify Entry Values. This function allows you to change the
values of the user registers, perhaps to test a subroutine whose
parameters are passed to it in the registers. You can also specify the
value of the zero flag and the carry flag. You should select the
register to be altered by pressing the appropriate letter. To escape
press BREAK.

16) Use Other Program. This function allows you to use another program
and to call it from the Monitor. The function is not designed for the
execution of the object program, but for the calling of some other
utility such as a disassembler. When you quit the other program,
control will return to the Monitor. The use of this function to call
an assembler forms a very powerful development tool.

17) View Memory. This displays the contents of memory from the
specified start location, dumping also to the printer if the printer
toggle is on. The routine displays 110 bytes per page, 20 bytes per
page if using binary. When the page is full the computer will wait for
you to press 'X' before proceeding to the next page. To escape, press
BREAK.

18) Zero Registers. This function restores the user registers to their
original values that they held when the Monitor was first entered. In
most cases this is 0, but the IY register defaults to 23610 and the HL
pair defaults to 10072 as required by the Spectrum operating system.
The user stack is also reset and preloaded with the return address
mentioned earlier in the Examine Stack function.


Instructions

The Monitor is written entirely in machine code and occupies the
memory from 28350 to 32767, and is thus 4418 bytes long. This means
that it will fit on a 16K Spectrum, but it is unlikely that the
expansion opportunities offered by the User program feature will be
utilised fully.

Type in listing 1 and save it - this is the hex loader. Run the
program and you will be prompted for the string of hex digits and then
for the check digit. Although the check digit might not look right it
is actually more effective than a normal checksum, spotting the vast
majority of transposition errors. When you have finished the program
will save the finished code and then verify it.

Reset the machine and then type CLEAR 28349: LOAD "MONITOR" CODE as a
direct command. After the code has loaded you should enter the Monitor
with RANDOMIZE USR 28350. A menu of the 18 functions should be
displayed. You should test each of the functions carefully. If you
discover any errors then listing 3 should help - it displays the code
you have entered in the same format as listing 2.


--
Another Fine Product transcribed by:
Jim Grimwood, Weardale, England (http://www.users.globalnet.co.uk/~jimg/)
--
