Before I started using Unix, I did a lot of development and debugging on
MS-DOS/DRDOS. When applications started using more and more of the features of
the 80386 that are available in real mode, such as 32-bit data registers and
extra segment registers, the standard debugger 'debug' became less and less
useful, as it only understands the 8086 instruction set.
So I wrote my own. Other than correctly disassembling the complete 80386
instruction set in both 16- or 32-bit code segments, it also takes advantage of
the 386's hardware breakpoints, which make it possible to single-step through
ROM code and allow you to trap accesses to memory locations.
Other features are remote debugging facilities through the serial port and
support for an NMI key, which can be used to interrupt the program even when
normal interrupts are disabled by the CLI instruction. Both features are
especially useful for debugging graphics routines and in embedded environments.
It's written for Borland's TASM assembler. You need to assemble both
disasm.asm and
monitor4.asm, and then link the
resulting .obj files into
monitor4.exe using Borland
tlink. Earlier versions are also available in the
download directory.
Usage
Invocation:
monitor4 executable[,arguments]
Commands for use at the '-' prompt:
a Set arguments, you get a prompt
b[seg:]ofs Set breakpoint at address seg:ofs, uses CS if no segment given
c Clear all breakpoints and watchpoints
d[[seg:]ofs] Dump 256 bytes of memory at address seg:ofs or last address
g Go, continue program
i Inspect breakpoints
k Keep resident and exit, after debugged program has done same
lexecutable Load a new executable using DOS' exec function
m[seg:]ofs Set a data watchpoint that triggers when read or written
n[seg:]ofs Set a data watchpoint that triggers only when written
p Set breakpoint at instruction below current one and proceed
q Quit
r Display registers
rreg,value Set register reg
rf Set flags, you get a prompt
s[seg:]ofs,s,f Save 's' bytes of memory memory at seg:ofs to file 'f'
t Trace to instruction to be executed next
u[[seg:]ofs] Disassemble code at seg:ofs, assuming a 16-bit code segment
v[[seg:]ofs] Disassemble code at seg:ofs, assuming a 32-bit code segment
w Clear redirection to serial port and use int 10h I/O again
wport Redirect to serial port using UART at base I/O address 'port'