First post, by Fizzban
Introduction to the built-in DOSBOX debugger
This guide explains how to activate the DOSBOX debugger and use the various commands it offers. This guide is not for the average DOSBOX user! If you do not
- know how to compile DOSBOX from the sources
- have knowledge about assembler
- have experience in system programming
you should just save you the trouble and not try to use the debugger. It won't help you.
1. Compiling the debug / heavydebug version of DOSBOX
In order to get a debug version, add the switch "--enable-debug" when calling configure:
If you want a heavydebug version, edit config.h after running configure and define C_HEAVY_DEBUG. This can be done by:
The heavy debug version will give you the following extra features:
- Memory breakpoints that activates when the value of a memory location is changed.
- CPU log that outputs the next n commands executed by the CPU to a textfile.
- Heavylog: Dumps the last (currently 20000) executed commands to a textfile when a program crashes or interrupt CD is called
- Unlike the debug version, heavydebug does not use INT 3 to realize breakpoints. This way, they cannot be removed. So if you want to use breakpoints, heavydebug is the better choice.
2. Activating the debugger
To pause the execution and start up the debugger, just press the Alt-Pause-key . DOSBOX has a separate debugger window that should have opened when DOSBOX started. It shows the current value of the CPU registers (those who changed since the last update are colored), a part of the memory content as hex data and assembler code (the command that will be executed next is marked green) and various debug messages.
If you want these debug messages to be saved into a textfile for later analysis, use the logfile entry in the log section of the config file.
3. Debugger keys
The following keys can be used while in debugger mode:
- H displays a reference of all keys and commands offered by the debugger
- F5 continues the execution
- Cursor Down moves the code view one command down
- Cursor Up will move the code view one byte up. Obviously DOSBOX doesn't know where multi-byte opcodes starts so moving up may screw up the disassembler until you find the actual beginning of a command.
- R and F scrolls the data view up and down
- D, E, S, X, B moves the data view to DS:SI, ES:DI, SS:SP, DS:DX or ES:BX respectively
- DOSBOX can display next to commands that deal with memory the current value of the referenced location. Use V to turn the extra info on and off.
- 1, 2, 4, 5 perform 100, 500, 1000, 5000 or 10000 CPU cycles then return to debugger mode.
- T raises the timer IRQ (IRQ0)
- F9 sets or removes a breakpoint at the current code view position (the line will be marked red)
- F10 steps over the next instruction (does not trace into calls)
- F11 traces into the next instruction
- ENTER opens a command line below the code view (a -> appears). See next chapter for details
4. Debugger commands
Commands are executing by hitting ENTER, entering the command in the command line that appears and confirming them by another ENTER.
These commands are always available:
- BP [segment]:[offset] sets a breakpoint at the given position
- BPINT [intNr] [ah] sets a breakpoint that activates when the program calls the given interrupt and AH has the given value. Enter an asterisk (*) for [ah] if DOSBOX should break regardless of the value of AH.
- BPLIST outputs a list of all currently set breakpoints.
- BPDEL [bpNr] / * deletes one breakpoint (use BPLIST to get the number) or all
- C / D [segment]:[offset] jumps the code or data view to the given location
- INT [nr] will execute an interrupt. It will return after the interrupt returns (unless a breakpoint activates before).
- INTT [nr] works like INT but will return into debug mode right away, so you can analyse the interrupt handler.
- SR [reg] [value] sets a register or flag (use af, cf, df,...)
- SM [seg]:[off] [val1] [val2] [val..] Set the memory starting at [seg]:[off] using the listed (byte) values.
- IV [seg]:[off] [name] sets a variable. The disassembler will then replace all references to this memory location by [name].
- SV/LV [fileName] saves and loads variables defined by IV
- MEMDUMP [seg]:[off] [len] dumps the memory content to memdump.txt
- SELINFO CS/DS/ES/FS/GS/SS/[seg] returns information about the descriptor of the segment the given register is currently pointing on. You can also specifiy an arbitrary segment using a hex value.
- GDT/LDT/IDT outputs the global/local/interrupt descriptor table
- INTVEC outputs a list of all real-mode interrupt vectors (located at 000:0000) to a textfile
- INTHAND [intNum] sets the code view to the beginning of the real-mode handler of the given interrupt
The following commands are only available if HEAVY_DEBUG is enabled (see chapter 1):
- LOG [num] performs num CPU cycles and logs the executed commands plus register values into the textfile LOGCPU.txt. Attention: This will slow down DOSBOX tremendously!
- BPM [seg]:[offset] sets a breakpoint that activates whenever the content of the given memory location changes. Attention: The new breakpoint will assume that the given location currently has the value 0x00. So you may get a "memory has changed from 00 to ??" breakpoint message as soon as you continue the execution although the memory actually didn't change.
- BPPM [selector]:[offset] is like BPM but with protected-mode-memory
- BPLM [linear address] like BPM but with a linear address location
- HEAVYLOG enables or disables the heavy logging of CPU activity. DOSBOX will start to store information about the command executed during the last 20000 CPU cycles. It will dump that info into LOGCPU_INT_CD.TXT if either interrupt CD is called (you can do that in the debugger using INT CD) or DOSBOX exits because of a critical error. Very useful to find out why DOSBOX crashes at some point. But similar to LOG, DOSBOX will run significantly slower with HEAVYLOG enabled.