Using the Microsoft Visual Studio 6 Debugger

 

Updated: 03/08/2003

This tutorial shows how to begin using the Microsoft Visual Studio 6 Debugger to debug 32-bit assembly language programs running in Protected mode.

This debugger lets you do the following:

  • Step through your program, viewing the source code
  • Set breakpoints in your code
  • View CPU registers and flags
  • View a disassembly of your program
  • Watch the values of program variables
  • View the runtime stack
  • Display blocks of memory
  • Perform remote debugging across a network

This will be a hands-on tutorial, so you can learn the most if you follow each step.

Load the Source Program

Open AddSub2.asm from MASM's \Examples\ch03 directory. Here's a listing of the essential code:

.data
val1     DWORD  10000h
val2     DWORD  40000h
val3     DWORD  20000h
finalVal DWORD  ?

.code
main PROC
	mov  eax,val1		; start with 10000h
	add  eax,val2		; add 40000h
	sub  eax,val3		; subtract 20000h
	mov  finalVal,eax	; store the result (30000h)
	call DumpRegs		; display the registers
	exit
main ENDP
END main

Assemble and link the program using the Build 32-bit MASM Tool command. If you have not yet installed MASM commands in the tools menu, click here.

Start the Debugger

Select the Debug 32-bit MASM from the Tools menu. A second copy of Visual Studio will load into memory, and the window will appear to be blank.

Press the F10 function key to display the program's source code. Other windows may also appear:

Don't worry if some of the windows on the bottom do not appear. We can open and close them at will. First however, let's take a tour:

Source Window

The Source window displays the program's source file. Note that the first MOV statement has a yellow arrow next to it. The arrow always indicates the next statement that's about to be executed.

Tip: You can remove any debugger window by right-clicking inside and selecting the Close option. You can open any window by selecting Debug Windows from the View menu.

Watch Window

The Watch window is like an electronic spreadsheet that displays the names and values of selected variables. As you step through a program, you can see variables in this window change value. Currently the window is empty, but you can drag any program variable into the window with your mouse.

Drag the val1, val2, and finalVal variables into the Watch window and note their current values. The values are displayed in decimal, so let's select the hexadecimal format by right-clicking on the watch window and selecting Hexadecimal Display from the popup menu.

Memory Window

The memory window displays a raw dump of memory in either hexadecimal or decimal. It is particularly useful when working with array variables. Since we don't have any arrays in the program, let's display the value of val3.

Next to the Address label, type: val3

(The name is case-sensitive.)

The Memory window displays a series of individual memory bytes, beginning at the address of val3. Actually, val3's value appears on the second line of the window's display. Because val3 is a doubleword, let's change the display format. Right-click on the window, and select Long Hex Format. Along the left side of the window is shown the address of the first value in each line:

In our sample, val3 is located at address 00404008, although your addresses might be different.

You can also type a hexadecmal constant into the Address field. Use the C format, where the digits are preceded by "0x". For example: 0x0040400C

(Note that the Memory window resets its address back to a default when you restart the debugger.)

Register Window

The Register window, on the right side of your screen, displays the current values of all the CPU registers. You might have to stretch it a bit to see the values of the CPU flags on the bottom:

The register names starting with "MM" are the floating-point CPU registers. Following are the flag abbreviations:

Flag Name Abbreviation
Overflow OV
Direction UP
Interrupt EI
Sign PL
Zero ZR
Aux Carry AC
Parity PE
Carry CY

Disassembly Window

The Disassembly window displays a raw listing of the program's code. It will often show code that has been generated by your own macros, or by some of the high-level MASM directives (such as .IF, in Chapter 6).

To make the Disassembly window visible, select View / Debug Windows / Disassembly from the debugger menu. Here is a sample:

Note that the offset of each variable apears next to its name. Note also that the exit statement in the AddSub2 source file has been translated into a call to the ExitProcess function. This is explained more fully at the bottom of page 75 in the book.

For now, right-click on this window and select Close.

Step Through the Program (F10)

Let's step through the program using the F10 function key. As you press F10, watch the yellow arrow in the Source window move from statement to statement.

Things to notice as you step through the program:

  • Individual register names (in the Register window) turn red, indicating that they have been modified. The AddSub2 program modifies the EAX and EIP registers quite a bit, as you can see.
  • Variables in the Watch window turn red when they are modified.
  • Memory locations in the Memory window turn red when they are modified.

As soon as you step past the call DumpRegs statement, click on the black MS-DOS icon on the Taskbar at the bottom of the screen. You should see the program's output, which is a register display.

When you reach the exit statement and press F10, the debugger halts.

Trace (F11)

Another way to step through a program is to use the Trace (F11) command. It steps down into each procedure call.

In contrast, the F10 key just executes procedure calls without tracing into the procedure code.

Stopping and Restarting

It's easy to either stop or restart your program inside the debugger while you're in the process of stepping through a program:

  • To restart the program, select Restart from the Debug menu. The program is reloaded into memory, so any changes previously made to variables in the Watch window are undone. Also, you have to retype the name of your variable in the Memory window, because it resets itself to a default address.
  • To stop debugging in the middle of a program, select Stop Debugging from the Debug menu.

Tips

Be sure to stop the debugger before trying to modify and re-assemble your program's source code. Otherwise, the linker will refuse to assemble your EXE file, indicating that it's currently in use:

After debugging my program, I like to leave the debugger window open and switch to my first Visual Studio editor icon on the Taskbar. In that window, I can make changes to your program, build it again, and then switch back to the debugger icon. The debugger will recognize that the EXE file has changed, and prompt you to load the new EXE file:

Of course, you click on the Yes button, and start debugging.

 

The End (for now)