Z80-MON

# Z80-MON - the Z80 monitor/disassembler

## 0. Content

- 0. Content
- 1. Introduction
- 2. How it works
- 3. Disassembling
- 4. Compiling
- 5. Console
- 6. Functions
- 7. Data

## 1. Introduction

This file describes essenial parts of the Z80 monitor/disassembler. Things in this document not described can be found in sources or man pages.

## 2. How it works

Debugger controls 64KB of memory as the Z80 CPU. All registers are stored in variables including SP, PC (program counter). There are special "registers" like IM and MEMP. IM is only for user's information. MEMP is starting address of memory dump. Registers and flags are displayed on screen together with the status of the IFF1-flipflop, the CPU-halt pin and the clock counter T. An important thing is disassembling.

## 3. Disassembling

In file simul.c machine code is interpreted. Sequentially bytes are read from memory (generally IO-address) and looked up into disassembling tables until the entire instruction has been decoded. Tables are in decode-table.c file, headers are in decode-table.h file.

First one or two bytes select disassembling table. There are several tables, each for different prefix. For no prefix, for CB prefix, and ED prefix. Instructions with FD prefix use IY register, instructions with DD prefix use IX register modifying HL-access interpretation.

When table is given, one byte is read for instruction body. This byte is line in the table. Line contains pointer to disassembling function and four arguments passed to this function. Arguments are type and value of first and second instruction operand. Then appropriate number of bytes is read from memory. Function and arguments are stored in current_instr structure, which is of type instruction_type.

All this is done in the decode function.

Disassembling functions are in execute.c file, headers are in execute.h file. These functions names start with f_ prefix. There are several auxiliary functions as set_flag, is_flag or reg_str in the z80-mon.c file.

Disassembling functions can be called in two modes: print and exec mode. Modes are switched with global variable cpu_wait.

In print mode disassembling functions return only the disassembled instruction. Next decode() calls the global function print, which prints string to appropriate position on screen. This position is stored in global variable row.

In exec mode instructions are interpreted. This means modifying registers and memory. Block instructions as djnz or ldir are executed step by step. In case of djnz register B is decreated and if B is non-zero PC is changed according to djnz offset. ldir is similar, it decreases BC and on non-zero it subtracts length of ldir instruction from PC.

Disassembling is realized forward only because it's impossible to disassemble code backward unambiguously. This is due to we don't know length of disassembled instruction. So if you wanna list backward in code you must enter exact value to PC register.

## 4. Compiling

z80-mon enables putting instructions to memory. Instruction is read from input to a text buffer. Then function compile from Z80 compiler library is called. Output is written to memory. If an error occurs an error function error is called . This function writes an error message and waits for a key.

The same principle is used in executing instructions. If you press the "x" key you're asked for an instruction. Instruction is compiled by the compile function, output is written to temporary memory tmp_memory. Then function decode is called on compiled instruction. Instruction is executed. Moreover compile needs at least the functions take_line for its input and write_to_memory for its output.

## 5. Console interface

I will not describe which functions print what on the screen and how they do it, I'll neither describe functions for user interface. I'll describe low-level interface which maintains writing to console, moving cursor, setting colors, cleaning screen, clearing block of screen, reading keys, etc. All these functions start with c_ prefix.

Low level interface is in file console.c, headers are in console.h file. The interface is the only operating system dependent part. In DO$ functions from conio.h are simply called. Under UNIX console is controlled with ANSI escape sequencies.

Console must be initialized before use and shut down after use. For this purposes there are functions c_init and c_shutdown.

Function c_getkey returns pressed key, if it's a special key as ENTER, ESCAPE, BACKSPACE, etc. it returns value K_ENTER, K_ESCAPE, .... These values are declared in console.h file.

## 6. Functions

Not all functions are mentioned here. Only the ones mentioned above or the important ones. Other functions aren't worth mentioning. You can see them in sources.

- void error(int n,char *line,char* message) - prints error messsage to the bottom of the screen and waits for a key.
- void print(char *str)

## 7. Data

Here are important data structures and variables. Other can be found and explained in sources.

- struct instruction_type
  - void (*func)(unsigned short a1,unsigned char t1,unsigned short a2,unsigned char - disassembling function for the instruction
  - unsigned char arg1,type1,arg2,type2; - value and type of instruction argument 1 and argument 2
- _uchar tmp_memory[64] - temporary memory

updated: 2004-Feb-13