DOCUMENT:Q80379 26-JUN-2001 [utilities] TITLE :Stepping Through Self-Modifying Code in CodeView PRODUCT :Microsoft Programming Utilities PROD/VER::2.2,3.0,3.11,3.14,4.0,4.01,4.02,4.05,4.1 OPER/SYS: KEYWORDS:kb16bitonly ====================================================================== ------------------------------------------------------------------------------- The information in this article applies to: - Microsoft CodeView for MS-DOS, versions 2.2, 3.0, 3.11, 3.14, 4.0, 4.01, 4.02, 4.05, 4.1 ------------------------------------------------------------------------------- SUMMARY ======= Code that is written to modify its 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 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 query words: kbinf 2.20 3.00 4.00 4.10 ====================================================================== Keywords : kb16bitonly Technology : kbAudDeveloper kbCodeView kbZNotKeyword3 kbCodeView220DOS kbCodeView300DOS kbCodeView311DOS kbCodeView314DOS kbCodeView400DOS kbCodeView401DOS kbCodeView402DOS kbCodeView405DOS kbCodeView410DOS Version : :2.2,3.0,3.11,3.14,4.0,4.01,4.02,4.05,4.1 ============================================================================= THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY. Copyright Microsoft Corporation 2001.