P-Code Debugging Techniques

Debugging p-code is like debugging native machine code. If you are examing your program at the instruction level, you should be familiar with the machine's operation. With p-code, this is the stack machine implemented by the p-code interpreter.

For general information on the interpreter and p-code instructions, see Chapter 3, “Reducing Program Size with P-Code” in Programming Techniques. For information on the p-code instruction set, choose the P-Code Help button from the Microsoft Advisor's top-level contents. Help is available on each p-code instruction.

When you are debugging native code, you normally view two levels of execution: source code and machine code. P-code introduces another level between the two. You can debug at any of these levels by setting the right combination of Source, Mixed, Assembly, and Native display modes.

The next section shows how to choose the different levels and describes what happens when you trace between native and p-code.

The Native Command

The Native command from the Options menu toggles CodeView's display of native machine code and p-code. When Native mode is turned on, a bullet appears to the left of the command on the menu.

Native mode on

With Native mode turned on, CodeView displays native machine instructions in the Source and Mixed display modes. The Register window and the Register command show the native CPU registers.

Native mode off

With Native mode turned off, CodeView displays:

Native machine instructions in those parts of your program that contain native code.

P-code instructions in those parts of your program that contain p-code.

Also, the Register window and the Register command show the native CPU registers when debugging a native routine, and they display the p-code interpreter's registers when debugging a p-code routine.

The distinction between Native mode on and off becomes important when you trace from a native routine into a p-code routine or from a p-code routine to a native routine. Generally, you turn Native mode off to view p-code instructions. Turn Native mode on when you want to see the action of the p-code interpreter.

Tracing From Native Code to P-Code

With Native mode turned off, tracing into a p-code routine causes CodeView to display p-code instructions. You can animate, step, and trace each p-code instruction in your program. You can also set breakpoints at individual p-code instructions. When tracing p-code, the Register window displays the registers and stack of the p-code machine.

With Native mode turned on, tracing into a p-code routine causes CodeView to display the native machine code of the p-code interpreter. Because the p-code interpreter is a library module that does not contain debugging information, CodeView switches to Assembly mode.

Tracing From P-Code to Native Code

With Native mode turned off, tracing from a p-code routine to a native routine causes CodeView to display native machine instructions. The Register window displays native CPU registers.

With Native mode turned on, you don't trace from p-code to native code. You trace out of the p-code interpreter and into your program's native code.

Unassembling P-Code

You can use the View Source and Unassemble commands to display p-code instructions in the Source window. With the View Source command, change to Mixed or Assembly display mode. The Unassemble command automatically displays p-code instructions when Native mode is turned off.

CodeView can display p-code and native code in the Source window at the same time. If you use the View Source or Unassemble commands in an area with both p-code and native code, CodeView displays both types of instructions. This commonly occurs when you view a routine with a native entry point as well as a p-code entry point. The different sections of code are separated by the assembly-language Data directive.

If you try to unassemble p-code with Native mode turned on, CodeView interprets p-code as native code and displays meaningless instructions.