debugging jbwyatt.com

.. debugging

Debugging refers to the removal of errors in your program. Admiral Grace Hopper (an early computing pioneer) liked to tell a story in which a technician solved a glitch in the Harvard Mark II machine by pulling an actual insect out from between the contacts of one of its relays.

The debugger allows you to single step through code, stop execution at critical points
and examine registers and memory - WHILE your program is running!

  • Step through code (step into, step over)
  • Examine registers (right click for flags)
  • Examine memory (&Var1 or address)
  • Watch (Right click on Var1, add watch)
  • View disassembly (right click options) of HOL


.. emu8086 debugger

Running and Debugging

Emulator:
- View: memory stack variables flags - Debug: single step set breakpoint



Extended Debug For The Emulator
- - Use these commands in the debug log
- - - - View log and debug.exe emulation

  • c - compare several bytes (arrays). For example:
    
    org 100h
    jmp a
    v1 db  1,4,3,4,5,6,7
    v2 db  1,5,3,0,5,6,7
    a:
    mov ax, v1
    mov al, v2
    mov dx, v1
    mov dl, v2
    ret
    
    To compare v1 and v2 type the following:

    c v1 L 7 v2

    L denotes the size of the array. If L parameter is not specified this command compares 8 bytes by default. For example to compare 8 bytes at offsets CS:100 and CS:233 type the following:

    c 100 233

    It is also possible to use registers as parameters, for example:

    c SI L 20h DI

    The command outputs only those addresses with values that are different.
    Equal bytes are not printed out.

  • i - input and display byte from a specified port. For example:

    i 123

    To input a word value use iw command.

  • o - output byte to a specified port. For example:

    o 123 55

    To output a word value use ow command. For example:

    ow 123 5512

  • d - dump 128 bytes at specified address. For example:

    d ds:3
    d ds:[bx]
    d ds:[bx+si]
    d bx + 5
    d 10

    If no segment is specified CS is used by default. Square brackets are optional. Subsequent use of d command without parameters shows next block of the memory.

    L parameter can be used to specify the number of bytes to dump. For example: There must be spaces around L to distingush from variable offset, for example:

    d lion L 10

    The above command dumps 16 bytes at offset of a variable called lion.

    If requred to denote variable L, declared as L db 5, brackets must be used. For example:

    d [L]
    d [L] L 1

  • t - single step.

  • p - step over (procedure or interrupt).

  • r - show all registers and current instruction at CS:IP.

    • rf - view/set flags.
    • r [register name] - view/set register value.




Code Examples to Look at in Debug



.. Code with bugs...

; Wyatt, 11/11/2011
;
;    Demonstrate 'bugs'
;
;    Supposed to loop thru the array, adding 
;    each element.
;        setup a pointer
;        setup loop counter
;        loop
;            add each element in the array
;            bump pointer to next element
;        end loop
;        multiply answer by 2   
; 
; goto part2 where it does ?
    
; FILE WITH MACROS & PROCS
include emu8086.inc       

; ADDRESS WHERE CODE WILL BE LOCATED
org 100h             

; CODE
    lea si, array
    mov cx, 3
    mov ax, 0
    L1:
       add ax, [si]
       add si, 1         
    loop L1 
    shl ax,1
    call PRINT_NUM 
    jmp part2   
ret

; DATA   
array dw 1,2,3   
sum dw 0
    
; PROCEDURES (call)
DEFINE_PRINT_NUM      ; prints AX signed
DEFINE_PRINT_NUM_UNS  ; prints AX unsigned - required for print_num.

PART2:
; CODE
    mov cx, 256
    mov ah, 2
    mov dl, 65
    L2:           
       int 21h
       inc dl         
    loop L2    
    ret
    
; stop assembling here    
END

.. Hello one character at a time: pointer and interrupt emu8086

; "hello, world!" step-by-step char-by-char way... 
; this is very similar to what int 21h/9h does

name "hello"
org     100h   ; compiler directive to make tiny com file. 

; execution starts here, jump over the data string: 
jmp     start

; data string: 
msg db 'Hello, world!', 0

start:
   ; set the index register: 
   mov     si, 0

next_char:
   ; get current character: 
   mov     al, msg[si]
   ; is it zero?  if so stop printing: 
   cmp     al, 0
   je      stop

   ; print character in teletype mode: 
   mov     ah, 0eh
   int     10h

   ; update index register by 1: 
   inc     si

   ; go back to print another char: 
   jmp     next_char

stop: 
   mov ah, 0  ; wait for any key press. 
   int 16h

   ; exit here and return control to operating system... 
   ret
end  

.. Sum an Array: Multi-segment (exe) emu8086

 - show memory before
 - show memory after
 - explain

; multi-segment executable file template. include emu8086.inc data segment x DW 100b, 100d, 100h, 100o ; CAREFUL! len = $-x y DW 0 ends stack segment dw 128 dup(0) ends code segment start: ; set segment registers: mov ax, data mov ds, ax mov es, ax ; set up pointer to x ; ----------------- lea di, x ;mov di, OFFSET x ; set up loop counter ; ----------------- mov cx, len shr cx, 1 ; init ax to 0 ;----------------- mov ax, 0 ; xor ax, ax ; sum array items one at a time... L1: add ax, [di] ; add what di points to to AX add di, 2 ; bump pointer loop L1 ; repeat until CX = 0 call print_num ret define_print_num define_print_num_uns end


Other Debuggers



.. visual studio debugger


.. debug an exe w/o source & debug utility