INF: Stepping Through Self-Modifying Code in CodeView

ID Number: Q80379

2.x 3.00 3.10 3.11 3.14

MS-DOS

Summary:

Code that is written to modify it's own contents may run differently

when run one line at a time in the Microsoft CodeView Debugger (CV).

This occurs because of the the way the 80x86 processors fetch

instructions. Because this is a limitation of how CodeView works, care

should be used when debugging self-modifying code.

The code may run one way outside of CodeView, and another way from

within CodeView. Also, running the program by using the go (F5)

command instead of the step (F10) or trace (F8) command may affect the

program's execution. Different processors can also affect this

behavior.

More Information:

The 80x86 processor will try to pre-fetch the next instruction from

memory while processing the current instruction. If the code being

modified is already waiting in the instruction queue, then the

processor will run the unmodified code. However, a jump instruction

will invalidate the queue, causing the next instruction to be fetched

before execution. In self-modifying code, this will cause the modified

instruction to be run. When stepping through a program in CodeView,

the instruction queue is always marked invalid, so all modified

instructions are run. The code below demonstrates this behavior.

If you step through the sample code in CodeView it will output "Num =

1". If you run straight though the code, allowing the processor to

pre-fetch instructions, it will output "Num = 0".

Sample Code

-----------

/* Compile options needed: /Zi

*/

#include<stdio.h>

void main(void)

{

unsigned int Num;

_asm {

mov ax, cs

push ds

mov ds, ax

inc byte ptr [cnt + 1] /* Adding a "jmp cnt" between the */

cnt: mov ax, 0 /* INC and the MOV will cause the */

mov Num, ax /* modified code to be run */

pop ds

}

printf("Num = %d",Num);

}

Additional reference words: 3.00 3.10 2.20