Common searches

Guide to the DOSBox debugger

Topic actions

First post, by Fizzban

User metadata
Rank Newbie

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:

./configure --enable-debug

If you want a heavydebug version, edit config.h after running configure and define C_HEAVY_DEBUG. This can be done by:

./configure --enable-debug=heavy

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.
Last edited by Fizzban on 2004-01-22, 17:46. Edited 3 times in total.

Reply 1 of 33, by jal

User metadata
Rank Oldbie

It seems this guide is a bit out of date (not surprising after almost 12 years 😀). Is there a more recent guide somewhere?

EDIT: Just found the debugger topic in the developers section. Here's 0.74 help:

Debugger commands (enter all values in hex or as register):
F3/F6 - Previous command in history.
F4/F7 - Next command in history.
F5 - Run.
F9 - Set/Remove breakpoint.
F10/F11 - Step over / trace into instruction.
ALT + D/E/S/X/B - Set data view to DS:SI/ES:DI/SS:SP/DS:DX/ES:BX.
Escape - Clear input line.
Up/Down - Move code view cursor.
Page Up/Down - Scroll data view.
Home/End - Scroll log messages.
BP [segment]:[offset] - Set breakpoint.
BPINT [intNr] * - Set interrupt breakpoint.
BPINT [intNr] [ah] * - Set interrupt breakpoint with ah.
BPINT [intNr] [ah] [al] - Set interrupt breakpoint with ah and al.
BPM [segment]:[offset] - Set memory breakpoint (memory change).
BPPM [selector]:[offset]- Set pmode-memory breakpoint (memory change).
BPLM [linear address] - Set linear memory breakpoint (memory change).
BPLIST - List breakpoints.
BPDEL [bpNr] / * - Delete breakpoint nr / all.
C / D [segment]:[offset] - Set code / data view address.
DOS MCBS - Show Memory Control Block chain.
INT [nr] / INTT [nr] - Execute / Trace into interrupt.
LOG [num] - Write cpu log file.
LOGS/LOGL [num] - Write short/long cpu log file.
HEAVYLOG - Enable/Disable automatic cpu log when dosbox exits.
ZEROPROTECT - Enable/Disable zero code execution detection.
SR [reg] [value] - Set register value.
SM [seg]:[off] [val] [.]..- Set memory with following values.
IV [seg]:[off] [name] - Create var name for memory address.
SV [filename] - Save var list in file.
LV [filename] - Load var list from file.
ADDLOG [message] - Add message to the log file.
MEMDUMP [seg]:[off] [len] - Write memory to file memdump.txt.
MEMDUMPBIN :[o] [len] - Write memory to file memdump.bin.
SELINFO [segName] - Show selector info.
INTVEC [filename] - Writes interrupt vector table to file.
INTHAND [intNum] - Set code view to interrupt handler.
CPU - Display CPU status information.
GDT - Lists descriptors of the GDT.
LDT - Lists descriptors of the LDT.
IDT - Lists descriptors of the IDT.
PAGING [page] - Display content of page table.
EXTEND - Toggle additional info.
TIMERIRQ - Run the system timer.
HELP - Help

Reply 2 of 33, by videogamer555

User metadata
Rank Member

Is there a way to set the current execution pointer EIP with a command in DOSBox debugger? Like highlight the opcode you want to be the next opcode that gets executed (with up/down arrows) and then type a command to set next execution to that point. I need a way to skip over a jump (JMP) command that's running in a loop.

Last edited by videogamer555 on 2020-01-17, 18:27. Edited 1 time in total.

Reply 4 of 33, by videogamer555

User metadata
Rank Member
Qbix wrote on 2020-01-17, 18:26:

SR (HELP in the debugger lists that well)

Sorry, didn't see that until now. I meant an easier way like highlight the next instruction you want executed, and then press a hotkey like F12 to set the EIP/IP code pointer to that instruction. I don't see that in the HELP command, but I think I remember doing something like that before. One thing I know is F12 doesn't do it. I just tried. Is there some undocumented hotkey that does this?

Reply 6 of 33, by videogamer555

User metadata
Rank Member
Qbix wrote on 2020-01-17, 18:36:

you mean setting a breakpoint ?

No. I don't mean setting a breakpoint. I mean a way to set the next-executed instruction. For example, when a program is paused in the debugger, if I press F10, it executes the next instruction. What if I want to skip that instruction without using SR to manually set the IP register, by manually selecting the next instruction to be executed. I thought there was a way to highlight the next instruction you wanted executed with the up/down arrow keys, and then press a hotkey to set the IP to that instruction, such that the next time you pressed F10 it would execute the instruction you had selected, rather than the one it would otherwise have executed next. However, when I type HELP in the debugger, I see no such feature. I haven't used DOSBox Debugger for a while, so it may be I'm remembering wrong, but thought it used to have such a feature. Was this maybe some kind of undocumented feature someone told me about a while ago, but I forgot how to do it now? Or am I just remembering wrong, and there never was such a feature?

Reply 7 of 33, by pantercat

User metadata
Rank Newbie

Just NOP the opcodes you don't want.

For example, if you have this instructions:

267E:6CE3 8BD7 mov dx,di
267E:6CE5 8BDE mov bx,si
267E:6CE7 1E push ds

To skip "mov dx,di" -> SM 267E:6CE3 90 90
To skip "push ds" -> SM 267E:6CE7 90

Reply 8 of 33, by jal

User metadata
Rank Oldbie

EDIT: removed post about not checking the date while I didn't check it correctly myself 😀

Last edited by jal on 2020-03-31, 16:36. Edited 1 time in total.

Reply 13 of 33, by betlit

User metadata
Rank Newbie


Forgive me to post a rather general question here.... I am familiar with assembler (but truth to be told NOT x86 assembly, just simpler stuff like PIC microchips, 'n stuff).

I try to go through the code of an old DOS game (some simulation game that i own on a physical optical storage medium (remember those?) trying to figure out some calculation the game does) and i am currently at a loss.
i'm sure its something obvious, but i can't figure out what i am missing here.

i am stepping happily through the code from some breakpoint i set a bit before and i am at this location:

File size
25.27 KiB
File license
Public domain

The instruction pointer shows 0x4994, which is the line highlighted in green. ok... so a NOP (which i learned is equal to xchg eax, eax) the AX register is set to 0x0.

i push F11.... and this is what i get next:

File size
24.62 KiB
File license
Public domain

the instruction pointer is now at 0x49AD (i.... expected 4995....) and AX register contains now the value 0xA5.....

Does F11 not just execute a single instruction?

the host system here is Windows 10 (dosbox 74-3 binary downloaded from this very forum) if that matters 😀 i get the same behaviour on linux (dosbox built myself)with heavy-debug).

What am i not seeing here?
Thanks a lot


Reply 16 of 33, by mills26

User metadata
Rank Newbie

Sorry if this question does not belong here.

I want to dump memory to a file using this debug, I read I just have to write a command in the debug window.
The problem is, I can't write anything in that window. "ENTER" is supposed to enable a command line, but nothing happens, keyboard does nothing in debugger window, and there is no command line to write to 🙁.


Reply 18 of 33, by mills26

User metadata
Rank Newbie
Qbix wrote on 2021-02-11, 13:05:

did you press alt-break in the normal dosbox window first ?

Thanks!. And sorry for the dumb question, I was pressing alt+break in the debugger window, not in the normal one.