MON88
Debug Monitor and Tiny Bios for the 8088/8086 Processor
Last Updated: 29/08/05
MON88 is a combined debug monitor (like the DOS debug.exe program) and some general DOS/BIOS interrupt handlers. The monitor was developed for the CPU86 IP Core processor but can easily be adopted for another embedded x86 system. The MON88 monitor includes an Intel Hex loader, Dissassembler and some INT21/INT10/INT16/INT1A services. The monitor is assembled by A86 assembler and requires about 14Kbyte. The disassembler is based on David Moore's "disasm.c - x86 Disassembler v 0.1".
Download Source File
- MON88 version
0.1 [zipped, 52KByte]
The monitor is located in the bottom 14Kbyte of memory. The first 1Kbyte is reserved for the interrupt vectors thus the (cold) start address is 0000:0400 (CS:IP). The I/O is handled by 2 routines, RXCHAR and TXCHAR which write/read from a UART. To communicate with the Debugger use a dumb terminal like TeraTerm in VT100 mode without local echo.
To assemble the monitor and convert the binary file to an Intel hex file use the following commands:
A86.com +L1 +P0 +W0 +T0 +G2 +S mon88.asm mon88.bin
bin2hex.exe
mon88.bin mon88.hex -o 0000 -e 0400
The bin2hex converter can be downloaded here. The -e argument results in an execute record to be added at the end of the hex file.
Included in the zip file is the C-source and executable (DOS-box) for a simple upload program. I wrote this program since I wanted to automate the upload and execution process something I couldn't do with my terminal program. Also to upload a file you can simple using the Send File (text) option on your terminal, however, this doesn't include any form of checking. The program is pretty basic and defaults to COM1:38400,n,8,1. To upload a file simply issue the command:
upload filename.hex
The extention .hex is optional. If you want to enter a simple terminal program after the upload process add the -t command to the command line:
upload hexfilename -t
or to just enter the terminal program:
upload -t
To quite the upload press F1 (or CTRL-C), to upload a file press F2. The upload command will first write the 'L' character followed by the hexfile.
Available Debug Commands
The following commands are supported:
|
Command |
Function |
Example |
|
DM {from} {to} |
Dump Memory |
DM 0000 0100 |
|
FM {from} {to} {fill_character} |
Fill Memory |
FM 0300 0500 5A |
|
R |
Dump Registers |
R |
|
CR |
Change Register |
CR AX 1234 |
|
U {from} {to} |
Un(dis)assmble range |
U 0100 0120 |
|
WB {address} {byte} |
Write Byte to Memory |
WB 1234 CC |
|
WW {address} {word} |
Write Word to Memory |
WW 1234 5A23 |
|
IB {port} |
Read Byte from I/O port |
IB 03F8 |
|
IW {port} |
Read Word from I/O port |
IW 03F8 |
|
OB {port} {byte} |
Output Byte to I/O port |
OB 03F8 21 |
|
OW {port} {word} |
Output Word to I/O port |
OB 0325 0120 |
|
L |
Load Intel Hex File |
L |
|
BP {number} {address} |
Set Breakpoint |
BP 1 0100 |
|
CB {number} {address} |
Clear Breakpoint |
CB 3 0120 |
|
DB |
Display all Breakpoints |
DB |
|
T |
Trace address |
T 0100 |
|
N |
Next Trace |
N |
|
G {address} |
Execute program |
G 0100 |
|
BS {address} |
Change Base Pointer |
BS 0340 |
|
H or ? |
Display Help |
H |
|
Q |
Quite/Restart Monitor |
Q |
Available Interrupt Handlers
|
Interrupt |
Service |
Action |
|
INT0 |
|
|
|
INT1 |
Breakpoint handler, used by monitor |
Monitor breakpoint function |
|
INT3 |
Trace handler, used by monitor |
Monitor trace (single step) function |
|
|
|
|
|
INT 10 |
AH=0E, AL=char, BH=ignored, BL=ignored |
Teletype Output, character written to UART |
|
|
|
|
|
INT 16 |
AH=00, Return AH=BIOS Scan code, AL=char |
Wait for keypress (kbhit) |
|
|
AH=01, Return AH=BIOS Scan code, AL=char, ZF |
Wait for keypress, ZF=1 no key, ZF=0 key |
|
|
|
|
|
INT 1A |
AH=00, Return CX:DX number of ticks since midnight, AL=0 |
Get System Time, 18.2 ticks/sec |
|
|
AH=01, CX:DX number of ticks since midnight |
Set System Time, 18.2 ticks/sec |
|
|
AH=02, CH=hours, CL=minutes, DH=seconds |
Get RTC Time, all values returned are in BCD |
|
|
AH=03, CH=hour, CL=minutes, DH=seconds |
Set RTC Time |
|
|
AH=04, CH=century, CL=year, DH=month, DL=day |
Get RTC Date, all values returned are in BCD |
|
|
AH=05, CH=century, CL=year, DH=month, DL=day |
Set RTC Date |
|
|
|
|
|
INT 21h |
AH=01, Return char in AL |
Read Character from UART |
|
|
AH=02, AL=char |
Write Character to UART with echo |
|
|
AH=08, AL=char |
Write Character to UART without echo |
|
|
AH=09, DX=Offset to string |
Write NULL (not $) terminated string to UART |
|
|
AH=0B, AL=Status |
Check for char waiting (kbhit), AL!=0 if key pressed |
|
|
AH=25, AL=INT number, DX=offset INT handler |
Set Interrupt Handler |
|
|
AH=2C, Return CH=hours, CL=minutes, DH=seconds DL=0 |
DOS Get System Time, same as INT1A,02 DL=0 |
|
|
AH=30, Return AL=02 |
Get DOS version, fake by returning AL=2 |
|
|
AH=4C |
Terminate, jump back to monitor, AL=Return Code |
|
|
|
|
Examples
The following section shows some examples of using the MON88 Debugger.
-
Load the debugger into memory using a bootstrap loader, JTAG port, or as used in the example below the upload.exe program. The CPU86 processor contains a simple Intel Hex bootstrap loader located in a LUT. After loading type ? or H/h to show the help menu.
d:\hdl_designs\cpu88\mon88\upload mon88
-t
...
UpLoad :1E35E000000000000000000000000000000000000000000000000000000000000000CD
ok
UpLoad :1E35E000000000000000000000000000000000000000000000000000000000000000CD
ok
MON88 8088/8086 Monitor ver 0.1
Copyright WWW.HT-LAB.COM
2005
All rights reserved.
Cmd>?
Commands
DM {from}
{to} : Dump Memory, example D
0000 0100
FM {from} {to} {Byte} : Fill Memory, example FM 0200 020F 5A
R
:
Display Registers
CR {reg} :
Change Registers, example CR SP=1234
L :
Load Intel hexfile
U {from} {to} :
Un(dis)assemble range, example U 0120 0128
G {Address} :
Execute, example G 0100
T {Address} :
Trace from address, example T 0100
N :
Trace Next
BP {bp} {Address} : Set BreakPoint,
bp=0..7, example BP 0 2344
CB {bp} :
Clear Breakpoint, example BS 7 8732
DB :
Display Breakpoints
BS {Word} :
Change Base Segment Address, example BS 0340
WB {Address} {Byte} :
Write Byte to address, example WB 1234 5A
WW {Address} {Word} :
Write Word to address
IB {Port} :
Read Byte from Input port, example IB 03F8
IW {Port} :
Read Word from Input port
OB {Port} {Byte} :
Write Byte to Output port, example OB 03F8 3A
OW {Port} {Word} :
Write Word to Output port, example OB 03F8 3A5A
Q :
Restart Monitor
Cmd>
-
Clear the memory by filling it with e.g. 0xFF characters. Note that all operations like fill memory, dump memory, load etc all operate on the (Base Segment Address<<4 + Offset). The offset is requested by MON88 for each command that requires it, the Base Segment Address defaults to 0380 which is just above the debugger. This means that when you do a fill command from address (offset) 0000-FFFF you will not overwrite the debugger in memory since the effective address is 03800 (0380:0000) to 137FF (0380:FFFF). You can change the Base Segment Address with the BS command.
Cmd>fm 0000-ffff ff
-
Next upload a test program, for example settime.hex (incl in the zip file), If you are using the UpLoad.exe program simply press F2 followed by the filename. If you are using Teraterm or any other terminal program just upload the file (send file) after issuing the L command.
Cmd>
Start upload now, load is terminated
by :00000001FF
>
Enter filename :settime.hex
UpLoad :200100008CC88ED88EC0BAB501B409CD21B402CD1A88E8E85B00B03AE8380088C8E85100D9
ok
UpLoad :20012000B03AE82E008AC6E84700BACC01B409CD21E8500088C5B03AE81800E8460088C128
ok
UpLoad :20014000B03AE80E00E83C008AF0B403CD1AB8004CCD218AD0B402CD21C3B401CD21C39CCE
Retry
UpLoad :20014000B03AE80E00E83C008AF0B403CD1AB8004CCD218AD0B402CD21C3B401CD21C39CCE
ok
UpLoad :2001600050240F3C0A7C0204070430E8E5FF589DC39C50D0E8D0E8D0E8D0E8E8E1FF58E8A1
ok
UpLoad :20018000DDFF9DC35351E81000B10AF6E18AD8E8070000C386C3595BC3E8BEFFE809003C4F
ok
UpLoad :2001A000397E022C072C30C33C617D01C33C7A7E01C32C20C30D0A546865206375727265D6
ok
UpLoad :2001C0006E742074696D652069733A000D0A456E74657220746865206E65772074696D6589
ok
UpLoad :0301E000203A00C2 ok
Load done
Cmd>
-
Check that the program has been loaded using the Dump Memory (DM) command or use the Un/disassembler (U).
Cmd>dm 0100-0200
0380:0100 8C
C8 8E D8 8E C0 BA B5 01 B4 09 CD 21 B4 02 CD ............!...
0380:0110
1A 88 E8 E8 5B 00 B0 3A E8 38 00 88 C8 E8 51 00 ....[..:.8....Q.
0380:0120
B0 3A E8 2E 00 8A C6 E8 47 00 BA CC 01 B4 09 CD .:......G.......
0380:0130
21 E8 50 00 88 C5 B0 3A E8 18 00 E8 46 00 88 C1 !.P....:....F...
0380:0140
B0 3A E8 0E 00 E8 3C 00 8A F0 B4 03 CD 1A B8 00 .:....<.........
0380:0150
4C CD 21 8A D0 B4 02 CD 21 C3 B4 01 CD 21 C3 9C L.!.....!....!..
0380:0160
50 24 0F 3C 0A 7C 02 04 07 04 30 E8 E5 FF 58 9D P$.<.|....0...X.
0380:0170
C3 9C 50 D0 E8 D0 E8 D0 E8 D0 E8 E8 E1 FF 58 E8 ..P...........X.
0380:0180
DD FF 9D C3 53 51 E8 10 00 B1 0A F6 E1 8A D8 E8 ....SQ..........
0380:0190
07 00 00 C3 86 C3 59 5B C3 E8 BE FF E8 09 00 3C ......Y[.......<
0380:01A0
39 7E 02 2C 07 2C 30 C3 3C 61 7D 01 C3 3C 7A 7E 9~.,.,0.<a}..<z~
0380:01B0
01 C3 2C 20 C3 0D 0A 54 68 65 20 63 75 72 72 65 .., ...The
curre
0380:01C0 6E 74 20 74 69 6D 65 20 69 73 3A 00 0D 0A 45 6E
nt time is:...En
0380:01D0 74 65 72 20 74 68 65 20
6E 65 77 20 74 69 6D 65 ter the new time
0380:01E0 20
3A 00 FF :...
Cmd>u
0100-010F
0100 8CC8 MOV
AX, CS
0102 8ED8 MOV
DS, AX
0104 8EC0 MOV
ES, AX
0106 BAB501 MOV
DX, 01B5
0109 B409 MOV
AH, 9
010B CD21 INT
21
010D B402 MOV
AH, 2
-
To execute type G followed by the IP (offset) address. The segment address is set by the BS command and defaults to just above the debugger last used address. The test program displays the RealTime Clock values (INT 1A, AH=01) followed by asking the user to enter a new value (INT1A, AH=03). The program terminates with a terminate interrupt (INT 21, AX=4C00) which results in a cold restart of the debugger. The user memory contents will not changed after a restart.
Cmd>g 0380:0100
The current time
is:11:40:16
Enter the new time :16:46:33
Program Terminated with exit
code 00
MON88 8088/8086 Monitor ver 0.1
Copyright WWW.HT-LAB.COM
2005
All rights reserved.
Cmd>
-
Assume the program is not working correctly and some debugging is required. First set a breakpoint on the address you want to start debugging from. For the example I used address 0131. Mon88 supports 8 breakpoints but this can easily be extended if required. After typing in the set breakpoint command (BP) the monitor will ask for a Breakpoint Number and an Address (offset). You can display all the active breakpoints using the DB command. The set breakpoint command will also show the instruction which will be replaced by the breakpoint INT3 instruction. Next run the program.
Cmd>bp 0 0131
0 0131 E85000 CALL
0184
Cmd>g 0380:0100
The current time is:16:49:59
Enter
the new time :
**** BREAKPOINT 0 ****
AX=0959 BX=0001 CX=1649
DX=01CC SP=0100 BP=0005 SI=0006 DI=0007
DS=0380 ES=0380 SS=0380 CS=0380
IP=0131 ODIT-SZAPC=0000-00100
0380:0131 E85000 CALL
0184
-
After issuing the run (G)o command the breakpoint is hit. After hitting the breakpoint you can dump memory (DM), change registers (CR) memory location (WB) I/O Location (OB/IB) etc or continue using the x86 trace command (N). The x86 Trace command allows you to single step through your code which is quite useful. The (N)ext command single steps to the next instuction, you can also use the (T)race offset command which start tracing at the entered offset address.
Cmd>n
AX=0959 BX=0001 CX=1649 DX=01CC
SP=00FE BP=0005 SI=0006 DI=0007
DS=0380 ES=0380 SS=0380 CS=0380 IP=0184
ODIT-SZAPC=0000-00100
0380:0184 53 PUSH
BX
Cmd>n
AX=0959 BX=0001 CX=1649 DX=01CC SP=00FC BP=0005
SI=0006 DI=0007
DS=0380 ES=0380 SS=0380 CS=0380 IP=0185 ODIT-SZAPC=0000-00100
0380:0185
51 PUSH
CX
Cmd>n
AX=0959 BX=0001 CX=1649 DX=01CC SP=00FA BP=0005
SI=0006 DI=0007
DS=0380 ES=0380 SS=0380 CS=0380 IP=0186 ODIT-SZAPC=0000-00100
0380:0186
E81000 CALL 0199
Cmd>
-
Type Q to restart the monitor.
Some Links
- Eric Isaacson's A86 Assembler
- Teranishi's excellent TeraTerm terminal program for windows.
- University of Denver, 80x86 Programming page
- 8086 instruction set Quick Reference and other one
- Interrupt Jump Table
- Randall Hyde's Webster website
- Paul Hsieh's x86 Assembly Language Page
- Simtel.net MS-DOS Assembly Language Utilities
- google will give you 654000 hits for the 8086, 763000 for the 8088........ happy surfing :-)
