JMON-monitor for banked BIOS Vers 1.00 88Jan22 by Julian Loke This is a simple Z80 breakpoint debugger which I use to trace through my CP/M banked BIOS. During the bootstrap procedure, as many as five bank swaps are made. This means that I can't use a standard debugger or even my ROM monitor since there is no fixed stack segment. This self-modifying debugger code lives in common memory (in my system COLOUR RAM at 0F800h). The ZASM source code is supplied, and overlays for a MicroBee 56 are included. These include keyboard scan code and code for a hardware scroll VDU driver using the 6545. As is, the code can be shoehorned into just under 4k. Introduction After I piggy-backed the second 56k bank of RAM on my Z80 MicroBee computer, I felt it was rather a waste to use it all as a RAM disk. I had a terrible sinking feeling in the pit of my stomach when I realized I would write a banked memory BIOS. I didn't feel any better when I had to debug the beast. This is one of the more useful tools I developed to help me trace through my XBIOS, which sits in a different bank from the TPA. The design criteria were simple: Z80 breakpoint debugger with multiple breakpoints Memory monitor Port monitor Keyboard and VDU routines independent of ROM MUST fit in common memory (2k) Transparent to XBIOS (i.e. no shared memory) The Monitor Those of you familiar with DDT will feel right at home. Single letter commands are typed on a short command line. Parameters follow, and are separated by commas. There is NO help facility. Being only a tiny monitor, JMON does not allow disassembly. You will need to manually trace through your code, armed with a list of Z80 opcodes and mnemonics, and with a printed listing of your .PRN file. I found this quite adequate for my purposes. Of course, if you insist on being able to disassemble and trace, I'd be very grateful if you could add the code to do this. Assembling JMON This program is NOT an example of elegant assembly language programming. As is, it is intended for use with ZASM and LOAD via a .HEX file. It produces a file for use with a MicroBee. The keyboard and VDU I/O routines (see below) for the MicroBee are rather large. Consequently, there was not much left for a decent monitor unless I used self-modifying code. A major stumbling block (which still remains) is the lack of a PHASE directive in ZASM. Being an ASM user from way back, I used offsets at EVERY ABSOLUTE address. So, instead of: ld sp,stk ;new stack ld a,(lbl5) ;absolute address jr nz,lbl1 ;relative address I have to put ld sp,stk+poff ;new stack + offset ld a,(lbl5+poff) ;absolute address + offset jr nz,lbl1 ;relative address where poff is defined earlier in the program. Look through the source code for more examples. If your assembler has a PHASE directive, put that into the file, and EQUate poff to zero. poff equ 0 ;offset for patch I/O interfacing To assemble JMON for a non-MicroBee system, you MUST to provide TWO include files: file entry point function JVDU.Z80 wr$a write ASCII char in register A to VDU. Preserves all other registers. JKBDST.Z80 kbdst Keyboard status/input routine. Return ASCII key in register A, and NZ flag. If no keys are pressed, return A=0, Z status. Beware! See the section above on producing PHASE code with an assembler without a PHASE directive. You MUST get this correct, or you will wind up in terrible trouble! Using JMON There is a small loader supplied with JMON.Z80 for loading the program into the correct address. I put a couple of options for my system, but this may or may not be suitable for you. A>JMON load and install JMON in the COLOUR RAM at 0F800h. Return to CP/M, ready for JUMP 0F800 from ZCPR, or following DDT. A>JMON X load, install, then run JMON A>JMON X.1 as above, but stores JMON in the PCG RAM instead of the colour RAM. Command Short Description B display all breakpoints Bxxxx toggle breakpoint at xxxx C clear all breakpoints D dump 128 bytes from current pointer Dxxxx dump 128 bytes from xxxx Dxxxx,yyyy dump from xxxx to yyyy D,yyyy dump from last addr to yyyy Fxxxx,yyyy fill from xxxx to yyyy with 00 Fxxxx,yyyy,nn fill from xxxx to yyyy with nn G go to PC Gxxxx go to xxxx Gxxxx,yyyy go to PC, temporary breakpoint at yyyy Hxxxx,yyyy display sum and difference (hexadecimal) Inn input from port nn Inn,oo input from port nn, put oo on A8..A15 Mxxxx,yyyy,zzzz move memory from xxxx..yyyy to zzzz Onn,oo output value oo to port nn Q quit to ROM monitor Qxxxx quit to address xxxx R display registers Rrxxxx set register r to xxxxx, r in [ABDHXYSPZ] RFfff set flag(s) in flag register, f in [SZHPNC] S substitute memory contents from last address Sxxxx substitute memory contents at xxxx Z display current PAGE register Zxxxx set PAGE register to xxxx Notes on commands field description example notes nn hex number I0 input from port 00h xxxx hex number G,0DF3 go with temp brkpt at 0DF3h or PC spec D. dump from PC onwards or PC relative B.r brkpt assuming PC at JR or PC absolute B.a brkpt e.g. with PC at CALL rr register name RA38 set A to 38h RH1234 set HL to 1234h ffff flag name RFZPS set FLAGS Z P and S The S command allows you to put several bytes in sequence (separated by commas) on the same line. If you start with a comma, the rest of the line is stored as an ASCII string verbatim. How I use JMON Let's say I am debugging the SELECT DISK XBIOS CODE. This lives in a bank separate from the TPA, which can only be accessed when the stack has been set to common memory. I have a printed listing of the region of code under test, and select a suitable location for a breakpoint. Using JMON, I can change banks using the Z command, and examine memory with the D dump command. I usually change some memory with the S command, then issue a GO command with temporary breakpoint. The registers are displayed, and may be redisplayed and modified with the R command. In this way I can successfully trace through my XBIOS. Many a bug, hidden stealthily in obscure source code has been revealed to me by this method. Sample JMON run with comments A>JMON X invoke jmon JMON v1.00 by J.Loke 88Jan22 $z1 select XBIOS bank $dc84e dump memory in bank 1,C84E 01:C84E 7A 2E... 01:C85E 5F 73... ... $bc84e set a permanent breakpoint $b display all breakpoints $z2 select TPA bank $g0 start, breakpoints active A>dir b: invoke test function ... XBIOS breakpoint reached registers are displayed c clear all breakpoints $d. dump at PC $g,c854 go with temporary brkpnt ... breakpoint reached registers are displayed $rfz set ZERO flag $ra0 set accumulator zero $h.,5 display PC+5,PC-5 $g,.r trace past relative jump $d. dump instruction LD HL,LBL $d.a dump LBL EUREKA I found the error! $z2 select TPA bank $q0 quit with a warm boot Any more? JMON is not a fully featured monitor. It is not even the debugger I use within CP/M. I only use JMON because there is nothing else that could handle the banked memory in my computer. Think of it as a kludge, and you won't be disappointed. You might even be pleasantly surprised how useful JMON can be. For more extensive documentation, or to return comments or criticisms, please get in contact with me on EASTWOOD R/ZSYS (03) 870 4623, or after your International access code, 61-3-870-4623. V22 or Bell 212 Copyright Released to the public domain to be freely distributed. May not be sold or included in a package which is sold. Julian Loke Melbourne, Australia. 1988 Jan 22