Metropoli BBS
VIEWER: debug.asm MODE: TEXT (CP437)
comment ~ ==================================================================

                    A 32bit protected mode debugger V1.11

               Copyright (c) Adam Seychell,1995.  All rights reserved

                     Last Modified on 1st Oct 1995




 You may use this source code in any way you wish provided that the
 following conditions are met;

 1) Any software what uses any part of this program must be for
    for non-profitable use.

 2)  Send me a copy of improvments you have made to the debugger.


 I have released the source in the hope it will be useful. The debugger
 source code may be used or improved by others who are interested in
 debeloping thier own. This source code is written in MASM 6.1 and by
 no means is it written neatly. If someone wants to write thier
 own debugger then best thing would be to use the instruction decode
 routine ( DEBUG.INC ) since this is a general routine for displaying
 486 instructions as a string. The rest of the debugger could be written
 in 32bit C/C++ and while still using ASM for the exception handlers.





~
OPTION OLDSTRUCTS
.386
.MODEL FLAT
.CODE


EXTERNDEF       Debug             :Near
EXTERNDEF       _Debug            :Near
EXTERNDEF       debug             :Near
EXTERNDEF       _debug            :Near
EXTERNDEF       _Debug_Run        :Near
EXTERNDEF       _debug_run        :Near
EXTERNDEF       _debugrun         :Near
EXTERNDEF       _DebugRun         :Near
EXTERNDEF       Debug_Run         :Near
EXTERNDEF       debug_run         :Near
EXTERNDEF       debugrun          :Near
EXTERNDEF       DebugRun          :Near







include debug.inc   ; This is the instruction decoding routine








ScreenHeight            EQU     50
ScreenWidth             EQU     80
boarder_color   	EQU     3fh
back_color              EQU     3fh
back_color_EA           EQU     03fh
selected_color  	EQU     1fh
selected_brkpt_color    EQU     0dfh
brkpt_color             EQU     4fh
registers_color         EQU     30h
RegistersHiLight_color  EQU     34h
menu_color              EQU     70h
menu_color1             EQU     78h
heading_color   	EQU     3bh
hilight_color           EQU     75h
mesg_box_text_color     EQU     071h
mesg_box_color          EQU     07eh

Number_brkpts           EQU 50


TRUE             EQU     1
FALSE            EQU     0



man_font        LABEL   byte
Include man_font.inc


VIDEO_BUFFERS STRUC
BitPlane1     DB 8192 dup (?)          ; The 8KB of screen memory
BitPlane2     DB 8192 dup (?)          ; The 8KB of video font memory
VIDEO_BUFFERS ENDS

program_reg STRUC
prg_eax          dd ?
prg_ecx          dd ?
prg_edx          dd ?
prg_ebx          dd ?
prg_esp          dd ?
prg_ebp          dd ?
prg_esi          dd ?
prg_edi          dd ?
prg_EIP          dd ?
prg_es           dd ?
prg_cs           dd ?
prg_ss           dd ?
prg_ds           dd ?
prg_fs           dd ?
prg_gs           dd ?
prg_eflags       dd ?

program_reg ENDS


_BSS SEGMENT
VideoBuffers            VIDEO_BUFFERS <>
registers_save          program_reg   <>
origonal_registers      program_reg   <>
Registers_saved_backlog program_reg   48 DUP ({})
_BSS ENDS



.CODE
align 4
;=---------=====------======-----
BreakPoint_EIP           dd   Number_brkpts dup (0)
BreakPoint_saved         db   Number_brkpts dup (0)
MOD_RM_EffectiveAddress  dd 0
MOD_RM_DefaultSegmentReg dd 0
MOD_RM_size              db 0
MOD_RM_SegmentReg        db 0

align 4
Segment_Base            DD  0
_0b8000h                dd 0B8000h  ; 32bit offset
Program_Addr             dd 0        ; 32bit offset
Zero_Addr               dd 0        ; 32bit offset
screen_EIP_value        dd 0
selected_EIP            dd 0
BacklogRegPTR_tail      dd 0
BacklogRegPTR_head      dd 0
screen_ending_EIP   	dd 0
CODE32_sel              dw 0        ; Selector
Zero_sel                dw 0        ; Selector
saved_IRQ1              df 0
saved_int21             df 0
saved_INT32             df 0
prg_videomode           db 0
special_brkpt_EIP       dd 0
special_brkpt_save      db 0
special_brkpt           db False
haveOrigonalRegisters   db False
step_flag       	db False
users_screen            db True
program_is_running      db False
InitDebugOnly           db False
Debug_operating         db False
Testing_EA_TEXT         db False
conditional_jump        db False
DebuggerTerminated      db False
Key_flags               db 0
selected_line           sbyte 0
MOD_RM_flag             db 0
Kbd_Rate                db -1
Kbd_Delay               db -1


;---------- VGA register saved --------------------------
VideoReg_CRTC_index        db 0
VideoReg_SQ_index          db 0
VideoReg_GC_index          db 0
VideoReg_MiscOutp          db 0
VideoReg_CRTC              db 19h dup (0)
VideoReg_SQ                db 5h dup  (0)
VideoReg_GC                db 9h dup  (0)
VideoReg_Attr              db 15h dup (0)
VideoReg_Palette           db 768 dup (0)
VideoReg_PELaddrWrite      db 0
BIOS_cursor                dw 0


string_buffer   db 50 dup (0)

menu_alt_bar_text Label byte
db 0,hilight_color,' Alt: ',0,menu_color,'      '
db 0,hilight_color,'X-',0,menu_color,'Exit     '
db 0,hilight_color,'F4-',0,menu_color,'Back     '
db 0,hilight_color,'F5-',0,menu_color,'User screen     '
db 0,hilight_color,'F9-',0,menu_color,'Goto beginning  '
db '       $'

menu_bar_text Label byte
db 0,menu_color,'     '
db 0,hilight_color,'F2-',0,menu_color,'Brkpt    '
db 0,hilight_color,'F4-',0,menu_color,'Here     '
db 0,hilight_color,'F7-',0,menu_color,'Next     '
db 0,hilight_color,'F8-',0,menu_color,'Step     '
db 0,hilight_color,'F9-',0,menu_color,'Run      '
db '               $'

stk_mesg        db 0,heading_color,'Stack frame$'
stk_ptrmesg     db 0,heading_color,'ss:esp$'
seg_mesg db'  selector   base     limit      selector  base     limit  $'




;===========================================================================
;
;    The routine wich starts the dubugger
;
;    This roitine will just init the debugger and set the Trap flag
;
;
;===========================================================================
align 4
_Debug:
;_debug:
;debug:
Debug    PROC
        push    ds                              ; save DS
        mov     ax,_TEXT
        mov     ds,ax
        pop     registers_save.prg_ds
        pushfd                                  ; Save eflags
        pop     registers_save.prg_eflags
        mov     registers_save.prg_es,es        ; Save ES
        pop     registers_save.prg_EIP          ; Save EIP
        mov     registers_save.prg_esp,esp      ; Save SS:ESP
        sub     registers_save.prg_esp,4
        mov     registers_save.prg_SS,ss
        pushad
        push    ds
        pop     es
        mov     Debug_operating,True
        call    Debugger_init
        ;* start the debugging *


        mov     byte ptr [debug],11001100b        ; put a INT 3
        mov     byte ptr [debug+1],11000011b      ; put a ret
        mov     byte ptr [debug_Run+1],11000011b      ; put a ret


        push    registers_save.prg_es
        push	registers_save.prg_ds

       .if  Debug_operating == False
         pop    ds
         pop    es
         popad
         push    word ptr cs:registers_save.prg_eflags
         popf
         sti
         jmp     cs:registers_save.prg_Eip      ; goto program without debug
       .endif

       .if    InitDebugOnly == False
         or     registers_save.prg_eflags,00100000000b
       .endif

        pop     ds
        pop     es
        popad
        push    cs:registers_save.prg_eflags    ; set eflags with TF set
        popfd
        jmp     cs:registers_save.prg_Eip      ; goto program

Debug    ENDP



;===========================================================================
;
;    The routine initalizes the dubugger but does not set the Trap flag
;  thus continuing normal program execution.
;
;
;===========================================================================
align 4
_Debug_Run:
;_debug_run:
;_debugrun:
;_DebugRun:
;Debug_Run:
;debug_run:
;debugrun:
;DebugRun:
Debug_Run PROC
        push    ds
        mov     ax,_TEXT
        mov     ds,ax
        mov     InitDebugOnly, True
        call    Debug
        pop     ds
        ret
Debug_Run ENDP



;==========================================================================
;
;               initalize the debugger !!!!!!!!!!!!!!!!
;
;  This gets run only once when the debugger is started
;
;
;==========================================================================
debugger_init PROC PRIVATE

        mov     ax,0EE00h                       ; Get selecor values
        int     31h
        mov     Zero_SEL,Bx

        mov     ax,0EE02h                       ; Fixup address information
        int     31h
        mov     Program_Addr,Ebx
        neg     Ebx
        mov     Zero_Addr,Ebx
        add     Ebx,0b8000h
        mov    _0B8000h,Ebx



        ; If the Current Privilege Level (CPL) is above 0 then
        ; we can't run the debugger
        ;

               mov      ax,cs
               lar      eax,eax
               test     ah,01100000b
               jz CPL_0                      ; brach if the CPL = 0

           ;
           ; display the error message
           ;
            .if    InitDebugOnly != True
               call    Debuggers_Video
               mov  edx,offset Mesg_dpmi_is_bad
               call    print_message_box
               mov  edx,offset Mesg_dpmi_is_bad1
               call    print_message_box
               call    restore_video
           .endif
               mov     Debug_Operating ,False
               ret                 ; Return to main program with no debugger
CPL_0:

              mov  ax,cs                      ; Set RPL field to zero
              and  al,11111100b
              push eax
              push offset Load_cs
              retf
Load_cs:

              cli



   .IF InitDebugOnly == True

        mov     Program_is_running, True
  .ELSE

        call    Debuggers_Video

        ;------------ set starting instuction -------------
        mov     eax,registers_save.prg_Eip
        mov     screen_EIP_value,eax
        cld
        mov    edx,offset intro_mesg
        call    print_message_box
  .ENDIF




        ;--------- See if can set/get keyboard typmatic rate -----
        mov     ah,9
        int  	16h
        jc LeaveKbd
        and     al,00001100b
        cmp     al,00001100b
        jne  LeaveKbd


        ;---------------- Save keyboard typmatic rate ----------
        mov     ah,03
        mov     al,06h
        int  	16h
        mov     Kbd_Rate,bl             ; Rate  (0..1fh)
        mov     Kbd_Delay,bh            ; Delay (0..3)

        ;---------------- set fast keyboard typmatic rate ----------
        mov     ah,03
        mov     al,05h
        mov     bl,0            ; Rate  (0..1fh)
        mov     bh,0            ; Delay (0..3)
        int  	16h

LeaveKbd:





        ;---------------- hook INT21 AH=4Ch   ----------------
        mov     bl,21h
        call    GetIntVector
        mov     dword ptr saved_int21,edx
        mov     word ptr saved_int21+4,cx

        mov     edx,offset terminate_Hooker
        mov     cx,cs
        call    SetIntVector


        ;---------------- hook IRQ 1 the keyboard interrupt ----------------
        mov     bl,1
        call    GetIRQvector
        mov     dword ptr saved_IRQ1,edx
        mov     word ptr saved_IRQ1+4,cx

        mov     edx,offset keyboard_ISR
        mov     cx,cs
        call    SetIRQvector


        ;---------------- set debug interrupt hanlder ( INT 1 ) -------------
        mov     bl,1
        mov     edx,offset Debug_Exception
        mov     cx,cs
        call    SetIntVector


        ;-------------- set the page faults handler -----------------

        mov     bl,14
        call    GetIntVector
        mov     dword ptr Old_IntVect14,edx
        mov     word ptr Old_IntVect14+4,cx

        mov     bl,14
        mov     edx,offset PageFalts_Exception
        mov     cx,cs
        call    SetIntVector

        ;-------------- set the break point handler (opcode 0CCh) -----------------
        mov     bl,3
        mov     edx,offset BreakPoint_Exception
        mov     cx,cs
        call    SetIntVector

        ;-------------- the General protection exception vector --------
        mov     bl,13
        call    GetIntVector
        mov     dword ptr Old_IntVect13,edx
        mov     word ptr Old_IntVect13+4,cx

        mov     bl,13
        mov     edx,offset GeneralProtection_Exception
        mov     cx,cs
        call    SetIntVector

        ;-------------- set the Invalid Opcode handler --------
        mov     bl,6
        mov     edx,offset InvalidOpcode_Exception
        mov     cx,cs
        call    SetIntVector


        ;-------------- set the Divide Error handler --------
        mov     bl,0
        mov     edx,offset DivideError_Exception
        mov     cx,cs
        call    SetIntVector

        ret

debugger_init ENDP         ;=========== end of debugger  inialization =

intro_mesg      db '32bit protected mode debugger V1.11  By Adam Seychell$'
mem_mesg db 'Warning:   Insufficient memory.  Video buffering will be disabled $'
Mesg_dpmi_is_bad    db 'Debugger cannot be run above Privlidge Level 0$'
Mesg_dpmi_is_bad1    db 'Press a key to begin normal progam execution$'





;=========================================================================
;
;       Save the *complete* VGA video card state
;
;
;=========================================================================
save_CompleteVideoState PROC PRIVATE
         cld
         cli
;
;               Save some VGA registers
;

        ;--- get and save programs video mode ------------
        mov     ah,0fh
        Int     10h
        mov     prg_videomode,al


        ;------- save the CRT controller registers ------------
        mov     dx,3D4h
        in      al,dx
        mov     VideoReg_CRTC_index,al

        xor     ecx,ecx
@@:     mov     dx,3D4h
        mov     al,cl
        out     dx,al
        mov     dx,3D5h
        in      al,dx
        mov     VideoReg_CRTC[ecx],al
        inc     cl
        cmp     cl,SIZEOF VideoReg_CRTC
        jb @b


        ;------- save the Sequencure controller registers ------------
        mov     dx,3C4h
        in      al,dx
        mov     VideoReg_SQ_index,al

        xor     ecx,ecx
@@:     mov     dx,3C4h
        mov     al,cl
        out     dx,al
        mov     dx,3C5h
        in      al,dx
        mov     VideoReg_SQ[ecx],al
        inc     cl
        cmp     cl,SIZEOF VideoReg_SQ
        jb @b


        ;------- save the Graphic Controller Registers ------------
        mov     dx,3CEh
        in      al,dx
        mov     VideoReg_GC_index,al
        xor     ecx,ecx
@@:     mov     dx,3CEh
        mov     al,cl
        out     dx,al
        mov     dx,3CFh
        in      al,dx
        mov     VideoReg_GC[ecx],al
        inc     cl
        cmp     cl,SIZEOF VideoReg_GC
        jb @b


        ;------- save the Attribute Controller Registers ------------
        mov     dx,3DAh         ; reset flip flop
        in      al,dx
        xor     ecx,ecx
@@:
        mov     dx,3C0h
        mov     al,cl
        out     dx,al
        inc     dl
        in      al,dx
        dec     dl
        out     dx,al
        mov     VideoReg_ATTr[ecx],al
        inc     cl
        cmp     cl,SIZEOF VideoReg_ATTr
        jb @b
        mov     dx,3C0h
        mov     al,20h                  ; Enaple palette
        out     dx,al
        mov     dx,3DAh         	; reset flip flop
        in      al,dx




    ;----- save the video memory that gets wiped on mode switching ------
    ;      set up registers to accsess one Bit plane  only
        mov dx,3C4h 	; sequencer reg group
        mov al,4
        mov ah,0111b
        out dx,ax

        mov dx,3CEh 	; The Graphics Controller reg group
        mov al,5      	; Mode Register
        mov ah,00000000b
        out dx,ax

        mov al,6    	; Miscellaneous Register
        mov ah,1100b
        out dx,ax

        mov al,4        ; set Read Map Mask Register
        mov ah,2    	; to read to bit plane 2
        out dx,ax

      ;--------- save a bit of Bit Plane 2 ( the 8KB of video font memory ) -
        mov     esi,_0b8000h
        mov     edi,Offset VideoBuffers.BitPlane2
        mov     ecx,(sizeof  BitPlane2 )/4
        rep     movsd


  ; set up registers to accsess one Bit plane 0 and 1 chained together
        mov dx,3C4h ; sequencer reg group
        mov al,4
        mov ah,0011b    ; Chain four enabled
        out dx,ax

        mov dx,3CEh 	; The Graphics Controller reg group
        mov al,5      	; Mode Register
        mov ah,00010000b
        out dx,ax

        mov al,6    	; Miscellaneous Register
        mov ah,1110b
        out dx,ax

        mov al,4        ; set Read Map Mask Register
        mov ah,0        ; to read to bit plane 0
        out dx,ax

        ;--------- save a bit of Bit Plane 0 and 1 together ---------
        mov     edi,Offset VideoBuffers.BitPlane1
        mov     ecx,(sizeof BitPlane1 )/4
        mov     esi,_0B8000h
        rep     movsd



        mov dx,3C4h ; sequencer reg group
        mov al,4
        mov ah,VideoReg_SQ[4]
        out dx,ax

        mov dx,3CEh         ; The Graphics Controller reg group
        mov al,4            ; set Read Map Mask Register
        mov ah,VideoReg_GC[4]
        out dx,ax

        mov al,5      ; Mode Register
        mov ah,VideoReg_GC[5]
        out dx,ax

        mov al,6    ; Misellaneous Register
        mov ah,VideoReg_GC[6]
        out dx,ax

        ;--------- save the general or external VGA registers ----------
        mov     dx,3CCh
        in      al,dx
        mov	VideoReg_MiscOutp,al



;--------- save the palette----------------------------
        mov     dx,3C8h
        in      al,dx
        mov     VideoReg_PELaddrWrite,al
        mov     dx,3C7h

        mov     al,0
        out     dx,al
        mov     dx,3C9h
        xor     ecx,ecx
@@:     in      al,dx
        mov     VideoReg_Palette[ecx],al
        in      al,dx
        mov     VideoReg_Palette[ecx+1],al
        in      al,dx
        mov     VideoReg_Palette[ecx+2],al
        add     ecx,3
        cmp     ecx,SIZEOF VideoReg_Palette
        jb @b


        ;------ save cursor position ------------------
        mov     ah,3
        mov     bh,0
        int  10h
        mov     BIOS_cursor,dx
        ret

;========== finished saveing the video state =====================
save_CompleteVideoState ENDP




;===================================================================
;
;
;   load the VGA video state from what was saved in the
;  "save_CompleteVideoState" procedure above
;
;
;===================================================================
restore_video PROC PRIVATE
         cld
        .IF   users_screen
                ret
        .Endif
        pushad

          ;---- first  retrun video mode -------------------
          xor   eax,eax
          mov   al,prg_videomode
          cmp   al,3h
;          je _Vmode3
          cmp   al,83h
;          je _Vmode3
          or    al,80h
          int 10h
_Vmode3:

         ;------ restore cursor position ------------------
         mov     ah,2
         mov     bh,0
         mov     dx,BIOS_cursor
         int  10h



 ;----- restore the video memory that gets wiped on mode switching ------

    ;      set up registers to accsess one Bit plane  only
    ; set for sequentual memory addressing
        mov dx,3C4h ; sequencer reg group
        mov al,4
        mov ah,0111b
        out dx,ax

        mov dx,3CEh ; The Graphics Controller reg group
        mov al,5      ; Mode Register
        mov ah,00000000b
        out dx,ax

        mov dx,3ceh ; The Graphics Controller reg group
    	mov al,6    ; Misellaneous Register
        mov ah,1100b
        out dx,ax

      ; set Map Mask Register
        mov dx,3c4h ; sequencer reg group
    	mov al,2
        mov ah,0100b    ;to write to bit plane 2
        out dx,ax

     ; can now fill up the video font memory
        mov     edi,_0b8000h
        mov     esi,Offset VideoBuffers.BitPlane2
        mov     ecx,(sizeof  BitPlane2 )/4
        rep     movsd



  ;      set up registers to accsess one Bit plane 0 and 1 chained together
        mov dx,3C4h ; sequencer reg group
        mov al,4
        mov ah,00011b            ; Chain four enabled
        out dx,ax

        mov dx,3CEh ; The Graphics Controller reg group
        mov al,5      ; Mode Register
        mov ah,00010000b
        out dx,ax

        mov al,6    ; Miscellaneous Register
        mov ah,1110b
        out dx,ax

     ; set Map Mask Register
        mov dx,3c4h ; sequencer reg group
    	mov al,2
        mov ah,0011b    ;to write to bit plane 0 and 1
        out dx,ax

        ;--------- restore the first 4KB of bit plane 0 and 1 ---------

        mov     esi,Offset VideoBuffers.BitPlane1
        mov     ecx,(sizeof BitPlane1 )/4
        mov     edi,_0B8000h
        rep     movsd


        ;--------- Resotre the general or external VGA registers ----------
        mov     dx,3C2h
        mov     al,VideoReg_MiscOutp
        out     dx,al


        ;------- restore the CRT controller registers ------------

        mov     al,VideoReg_CRTC[ecx]   ; Turn off protection
        mov     dx,3D4h
        mov     ah,VideoReg_CRTC[11h]
        and     ah,01111111b
        mov     al,11h
        out     dx,ax

        xor     ecx,ecx
@@:     mov     dx,3D4h
        mov     al,cl
        out     dx,al
        mov     dx,3D5h
        mov     al,VideoReg_CRTC[ecx]
        out     dx,al
        inc     cl
        cmp     cl,SIZEOF VideoReg_CRTC
        jb @b
        mov     dx,3D4h
        mov     al,VideoReg_CRTC_index
        out     dx,al


        ;------- restore the Graphic Controller Registers ------------

        xor     ecx,ecx
@@:     mov     dx,3CEh
        mov     al,cl
        out     dx,al
        mov     dx,3CFh
        mov     al,VideoReg_GC[ecx]
        out     dx,al
        inc     cl
        cmp     cl,SIZEOF VideoReg_GC
        jb @b
        mov     dx,3CEh
        mov     al,VideoReg_GC_index
        out     dx,al


        ;------- Restore the Sequencure controller registers ------------
        xor     ecx,ecx
@@:     mov     dx,3C4h
        mov     al,cl
        out     dx,al
        mov     dx,3C5h
        mov     al,VideoReg_SQ[ecx]
        out     dx,al
        inc     cl
        cmp     cl,SIZEOF VideoReg_SQ
        jb @b
        mov     dx,3C4h
        out     dx,al
        mov     al,VideoReg_SQ_index


        ;------- Restore the Attribute Controller Registers ------------
        mov     dx,3DAh         ; reset flip flop
        in      al,dx
        xor     ecx,ecx
@@:
        mov     dx,3C0h
        mov     al,cl
        out     dx,al
        mov     al,VideoReg_ATTr[ecx]
        out     dx,al
        inc     cl
        cmp     cl,SIZEOF VideoReg_ATTr
        jb @b
        mov     dx,3C0h
        mov     al,20h                  ; Enaple palette
        out     dx,al
        mov     dx,3DAh         ; reset flip flop
        in      al,dx




;--------- Retore the palette----------------------------

        mov     dx,3C8h
        mov     al,0
        out     dx,al
        mov     dx,3C9h
        xor     ecx,ecx
@@:     mov     al,VideoReg_Palette[ecx]
        out     dx,al
        mov     al,VideoReg_Palette[ecx+1]
        out     dx,al
        mov     al,VideoReg_Palette[ecx+2]
        out     dx,al
        add     ecx,3
        cmp     ecx,SIZEOF VideoReg_Palette
        jb @b
        mov     dx,3C8h
        mov     al,VideoReg_PELaddrWrite
        out     dx,al

        mov     users_screen,True
        popad
        ret
restore_video ENDP



;========================================================================
;  This procedure will test the address in ECX to see if it's a valid
; location, i.e will not cause a page fault.
;
;
;  Return       If location is Ok then
;                   testing_EA_TEXT = True
;               else
;                   testing_EA_TEXT = False
;
;========================================================================
Test_location PROC PRIVATE USES ES
                mov     es,Zero_SEL
                jmp  $+2
                mov     testing_EA_TEXT,True
tea_ins:
                mov     ebx,es:[ecx]
                mov     ecx,es:[ecx+4]
tea_ins_size EQU $ - tea_ins
                nop
                nop
                nop
                nop
                nop
                nop
                ret
Test_location ENDP



;===========================================================================
;
;        Look at current instrucion and see if a VGA register was modified
;
;
;  Expects      "registers_save.prg_EIP" pointing to instruction
;
;  Returns:    restores video state if instruction was using a VGA port
;
;===========================================================================
CheckVGAport    PROC PRIVATE

        pushad
        mov     eax,registers_save.prg_EIP
        mov     eax,[eax]
        mov     cl,2
Loopeer:
         .IF     al == 66h               ; igonre operand size prefix
           shr eax,8
         .ELSEIF  al == 11110010b        ; igonre any stupid REP prefix
           shr eax,8
         .ENDIF
       dec cl
       jnz Loopeer

        and     al,01111100b
        cmp    AL ,01101100b            ;see if IN,OUT, INS or OUTS
        je getPortIn
        jmp exit


getPortIn:
        mov     eax,registers_save.prg_edx
        mov     edi,offset allVGAports
        cld
        mov     ecx,19
        repne   scasw
        jne  exit

         call    Restore_Video

exit:   popad
        ret

allVGAports     dw      3D4h,3D5h,3C4h,3C5h,3CEh,3CFh,3CCh,3CAh,3C2h,3DAh
                dw      3c0h,3c8h,3c9h,3c7h,3d6h,3c3h,3cdh,3d4h,3d5h
CheckVGAport    ENDP








draw_char MACRO  char
        mov  al,char
        call    _draw_char
ENDM
draw_2char MACRO  char
        mov     bx,char
        call    _draw_2char
ENDM
draw_vert MACRO  char,count
        mov  al,char
        mov  cl, count
        call    _draw_vert
ENDM
draw_horz MACRO  char,count
        mov  al,char
        mov  cl, count
        call    _draw_horz
ENDM


;================================================================
;
;
;       Displays a repeated character on the screen Verticaly
;
;      Expects   edi = character offset in the screen memory.
;                al  = character
;                cl  = repeat
;                ah  = color
;
;================================================================
_draw_vert PROC PRIVATE
        mov     edx,_0B8000h
@@:     mov     word ptr [edi*2+edx],ax
        add     edi,80
        dec    cl
        jnz @b
        ret
_draw_vert ENDP


;================================================================
;
;
;       Displays a repeated character on the screen horizonataly
;
;      Expects   edi = character offset in the screen memory.
;                al  = character
;                cl  = repeat
;                ah  = color
;
;================================================================
_draw_horz PROC PRIVATE
        mov     edx,_0B8000h
@@:     mov     word ptr [edi*2+edx],ax
        inc     edi
        dec    cl
        jnz @b
        ret
_draw_horz ENDP



;================================================================
;
;
;       Displays a single character on the screen
;
;      Expects   edi = character offset in the screen memory.
;                al  = character
;                ah  = color
;
;================================================================
_draw_char PROC PRIVATE
        mov     edx,_0B8000h
        mov     word ptr [edi*2+edx],ax
        inc     edi
        ret
_draw_char ENDP


;================================================================
;
;
;       Displays two characters on the screen
;
;      Expects   edi = character offset in the screen memory.
;                bh  = character 1
;                bl  = character 2
;                ah  = color
;
;================================================================
_draw_2char PROC PRIVATE
        mov     al,bh
        mov     edx,_0B8000h
        mov     word ptr [edi*2+edx],ax
        inc     edi
        mov     al,bl
        mov     word ptr [edi*2+edx],ax
        inc     edi
        ret
_draw_2char ENDP

;================================================================
;
;
;       Display a string on the screen
;
;      Expects   edi = character offset in the screen memory.
;                edx = points to the string that terminates with a '$'
;                ah  = color
;
;================================================================
plot_string PROC PRIVATE USES EBX
        mov     ebx,_0B8000h
leer:   mov     al,[edx]
        cmp     al,'$'
        je exit
        cmp     al,0
        jne @f
         mov ax,[edx+1]
         add   edx,2
         xchg  al,ah
   @@:  mov     word ptr [edi*2+ebx],ax
        inc     edi
        inc     edx
        jmp leer
exit:   ret
plot_string ENDP



;================================================================
;
;
;       Display a hexidecimal number on the screen
;
;      Expects   edi = character offset in the screen memory.
;                ebx = The number to display
;                cl = The number of nibbles to display
;
;================================================================
print_hex PROC PRIVATE USES EBX EBP EDX ECX
        mov     edx,_0B8000h
he_plotloop:
        rol     ebx,4
        movzx   ebp,bl
        and     ebp,0fh
        mov     al,ds:hex_chars[ebp]
        mov     word ptr [edi*2+edx],ax
        inc     edi
        dec     cl
        jnz he_plotloop
        ret
hex_chars       db '0123456789abcdef'
print_hex ENDP



;================================================================
;
;
;       This will display all the segment register values and
;       the base addresses and limit.
;
;
;  Expects Nothing
;
;================================================================
Display_SegReg_info     PROC  PRIVATE
                   mov     edi,(1 + ScreenWidth*(ScreenHeight-5) )
                   mov     ah,heading_color
                   mov     edx,offset seg_mesg
                   call    plot_string

                   mov     edi,(2 + ScreenWidth*(ScreenHeight-4) )
                   mov     ah,registers_color
                   xor     ebp,ebp
           plot_segloop:
                   mov     edx,offset ES_symb
                   add     edx,ebp
                   call    plot_string
                   draw_char '='
                   mov     ebx,ds:registers_save.prg_es[ebp]
                   mov     cl,4
                   ror     ebx,16
                   call    print_hex
                   movzx     ecx,word ptr ds:registers_save.prg_es[ebp]
                   lsl     ebx,ecx
                   jz @f
                     mov  edx,offset nul_sel_measg
                     call  plot_string
                     jmp invsel
                   nul_sel_measg   db '··Invalid selector··$'
           @@:
                  draw_2char '  '

                   mov     ebx,Program_Addr
                  .if  cx  == Zero_Sel
	            xor     ebx,ebx
	          .endif
                   mov     cl,8
                   call    print_hex
                   draw_2char '  '
                   lsl     ebx,ds:registers_save.prg_es[ebp]
                   mov     cl,8
                   call    print_hex
           invsel: add     edi,ScreenWidth-27
                   add     ebp,4
                   cmp     edi,( ScreenWidth*(ScreenHeight-1) )
                   jb  plot_segloop
                   cmp     edi,(2+ ScreenWidth*(ScreenHeight-1) )
                   ja exit
                   mov     edi,(33+ ScreenWidth*(ScreenHeight-4) )
                   jmp  plot_segloop
exit:              ret
Display_SegReg_info ENDP


;================================================================
;
;
;       This will display all the debug register values and
;       the the R,W and LEN fields of each
;
;   Expects :  Nothing
;================================================================
Display_DRx_info PROC  PRIVATE
                mov     edi,(1 + ScreenWidth*(ScreenHeight-5) )
	        mov     ah,heading_color
                mov     edx,offset HardwareBrkpts_mesg
                call    plot_string

                ;---- display the break point regieters -----------
                mov     edi,(2 + ScreenWidth*(ScreenHeight-4) )
                mov     ah,registers_color
                draw_2char 'DR'
                draw_2char '0='
                mov     ebx,DR0
                mov     cl,0
                call    Plot_DR

                mov     edi,(2 + ScreenWidth*(ScreenHeight-3) )
                draw_2char 'DR'
                draw_2char '1='
                mov     ebx,DR1
                mov     cl,2
                call    Plot_DR


                mov     edi,(33 + ScreenWidth*(ScreenHeight-4) )
                draw_2char 'DR'
                draw_2char '2='
                mov     ebx,DR2
                mov     cl,4
                call    Plot_DR

                mov     edi,(33 + ScreenWidth*(ScreenHeight-3) )
                draw_2char 'DR'
                draw_2char '3='
                mov     ebx,DR3
                mov     cl,6
                call    Plot_DR

                mov     edi,(2 + ScreenWidth*(ScreenHeight-2) )
                draw_horz  ' ',58

                                ret

Plot_DR PROC PRIVATE    ;------------ sub proc for plotiing one DR reg ---
                mov     ebp,DR7
                shr     ebp,cl
                push    ecx
                mov     cl,8
                call    print_hex
                pop     ecx
                test    ebp,00000003h   ; look at  Gi and Li bits
                jnz  @f
                     mov  edx,offset nul_DRx_measg
                     call  plot_string
                     ret
          @@:   shr     ebp,cl
                draw_char  ' '
                draw_2char 'W='
                mov  bx,'0 '
                test    ebp,00010000h
                jz  @f
                 mov  bh,'1'
           @@:  call  _draw_2char
                draw_2char 'R='
                mov  bx,'0 '
                test    ebp,00020000h
                jz  @f
                 mov  bh,'1'
           @@:  call  _draw_2char
                draw_2char 'LE'
                draw_2char 'N='
                mov     ebx,ebp
                and     ebx,000C0000h
                rol     ebx,10
                mov     cl,1
                call    Print_hex
                draw_char  ' '
                ret
Plot_DR ENDP
nul_DRx_measg   db ' ···disabled·· $'

HardwareBrkpts_mesg     db  '      80386  Linear Address Breakpoint Registers         $'

Display_DRx_info ENDP





;========================================================================
;
;     This will update the registers log storage.
;
;   Expects :  Nothing
;
;========================================================================
Update_register_LOG PROC  PRIVATE
           ;------ copy all regs into back log --------------
        mov        edi,BacklogRegPTR_head
        add        edi,offset registers_saved_backlog
        mov        esi,offset registers_save
        mov        ecx,(SIZEOF program_reg ) /4
        rep        movsd

        mov        eax,BacklogRegPTR_head
        add        eax, SIZEOF program_reg
       .if       eax >= SIZEOF registers_saved_backlog
             xor   eax,eax
       .endif
        mov        BacklogRegPTR_head,eax

        .if     BacklogRegPTR_tail  == EAX
                mov     eax,BacklogRegPTR_tail
                add     eax, SIZEOF program_reg
               .if      eax >= SIZEOF registers_saved_backlog
	             xor   eax,eax
	       .endif
                mov        BacklogRegPTR_tail,eax
        .endif
        ret
Update_register_LOG     ENDP




;================================================================
;
;
;       This will display all the register values, flags and all the
; intructions on the screen  ( except segment and debug registers )
;
;
;================================================================
refresh_screen PROC PRIVATE

local   old_esi         :dword
local   count1          :dword
local   line_count      :byte
local   current_instruc :byte
local   brkpt_flag      :byte
local   InstCursor_flag :byte


        ;----- print the nine registers on the screen ----------------
        mov     edi,(ScreenWidth*1+66)
        xor     esi,esi
RegPrint_LOOP:
        mov     cl,8
        mov     ebx,registers_save.prg_eax[esi*4]
        mov     ah,registers_color
        mov     edx,BacklogRegPTR_head
       .if     BacklogRegPTR_tail  != EDX
                sub     edx, SIZEOF program_reg
                jge @f
                mov edx,SIZEOF registers_saved_backlog - SIZEOF program_reg
            @@:
                .if ( EBX != Dword PTR registers_saved_backlog[edx+esi*4] ) \
                     &&  ( ESI != 8 )
                  mov     ah,RegistersHiLight_color
                .endif
        .endif
        call    print_hex
        inc     esi
        add     edi,80-8
        cmp     esi,9
        jb RegPrint_LOOP

        ;----- print the eight flags ----------------
        mov     ah,registers_color
        mov     edi,(ScreenWidth*1+78)
        mov   al,'0'
        test  registers_save.prg_eflags,0000000000001b
        jz @f
        mov   al,'1'
@@:     call    _draw_char
        mov     edi,(ScreenWidth*2+78)
        mov   al,'0'
        test  registers_save.prg_eflags,0000001000000b
        jz @f
        mov   al,'1'
@@:     call    _draw_char
        mov     edi,(ScreenWidth*3+78)
        mov   al,'0'
        test  registers_save.prg_eflags,0000010000000b
        jz @f
        mov   al,'1'
@@:     call    _draw_char
        mov     edi,(ScreenWidth*4+78)
        mov   al,'0'
        test  registers_save.prg_eflags,0100000000000b
        jz @f
        mov   al,'1'
@@:     call    _draw_char
        mov     edi,(ScreenWidth*5+78)
        mov   al,'0'
        test  registers_save.prg_eflags,0000000000100b
        jz @f
        mov   al,'1'
@@:     call    _draw_char
        mov     edi,(ScreenWidth*6+78)
        mov   al,'0'
        test  registers_save.prg_eflags,0000000010000b
        jz @f
        mov   al,'1'
@@:     call    _draw_char
        mov     edi,(ScreenWidth*7+78)
        mov   al,'0'
        test  registers_save.prg_eflags,0001000000000b
        jz @f
        mov   al,'1'
@@:     call    _draw_char
        mov     edi,(ScreenWidth*8+78)
        mov   al,'0'
        test  registers_save.prg_eflags,0010000000000b
        jz @f
        mov   al,'1'
@@:     call    _draw_char


        ;========== plot the stack frame =======================

                mov     edi,(ScreenWidth*(ScreenHeight-2)+67)
                mov     esi,registers_save.prg_esp
                push    es
                mov     bx,word ptr registers_save.prg_ss
                mov     es,bx
               .IF    BX == _TEXT
                  mov  ebx,Program_addr
                  mov Segment_Base,ebx
               .ElseIF BX == Zero_SEL
                  mov Segment_Base,0
               .else
                  mov Segment_Base,0
               .endif

stlplol:
                mov     ecx,esi
                add     ecx,Segment_Base
                Call  Test_location           ; Test location DS:[ECX]
               .If Testing_EA_TEXT == True
                  mov     ebx,es:[esi]
                  mov     cl,8
                  call    print_hex
                  mov Testing_EA_TEXT,False
                .Else
                  mov      edx,Offset Bad_stack_mesg
                  call     Plot_String
                .Endif
                sub     edi,80+8
                add     esi,4
                cmp     edi,(ScreenWidth*12+67)
                jae stlplol
                pop     es

;=========== plot the intructions ========================================
;=========== plot the intructions ========================================
;=========== plot the intructions ========================================
;=========== plot the intructions ========================================
;=========== plot the intructions ========================================

Plot_The_Instructions:

        mov     count1,0
        mov     esi,screen_EIP_value
        mov     line_count,0
        mov     InstCursor_flag,FALSE

        mov     eax,ESI
        mov     ecx,Number_brkpts
        mov     edi,offset BreakPoint_EIP
        repne scasd
        mov    brkpt_flag,False
        jne no_brkpt_
           sub  edi,offset BreakPoint_EIP+4
           shr  edi,2
           mov   brkpt_flag,True
           mov   al,BreakPoint_saved[edi]                ; temperarly put
           mov   [esi],al                                ; in old intruction
           mov   old_esi,esi
no_brkpt_:

back_more:

        .if selected_line > (ScreenHeight-8)
                   mov  selected_line,(ScreenHeight-8)
                   mov     edi,offset string_buffer
                   call    decode_instruction
                   mov     screen_EIP_value,esi

        .elseif selected_line < 0
                     inc     selected_line
                     mov     edi,offset string_buffer
                     mov      old_esi,esi
	             mov cl,8
            tryagn:  dec   cl
	             jz stptry
	             dec     screen_EIP_value
	             mov     esi,screen_EIP_value
                     mov     edi,offset string_buffer
                     call    decode_instruction
                     cmp     esi,old_esi
                     jne tryagn
            stptry:  mov     esi,screen_EIP_value
                     jmp  back_more
        .endif

    ;------- Put back break point if is here-------
        .if   brkpt_flag  == True
                mov     eax,old_esi
                mov     byte ptr [eax],0CCh
        .endif



       .if step_flag == 1
	        mov     eax,registers_save.prg_EIP
                .if   eax < esi
                        mov  screen_EIP_value,eax
                        mov  esi,eax
                .endif
                .if   eax > screen_ending_EIP
                        mov  screen_EIP_value,eax
                        mov  esi,eax
                .endif
                mov    Selected_EIP,eax
       .endif

mainloop:       ;============= MAIN  LOOP ========================

       mov      screen_ending_EIP,esi


       mov     ah,registers_color
      .if step_flag == 1
	        .if     registers_save.prg_EIP == esi
	           mov  al,line_count
	           mov  selected_line,al
                   mov  ah,selected_color
                   mov  step_flag,False
	        .endif
       .else
                 mov    al,selected_line
                .if     line_count == al
                 mov     ah,selected_color
                 mov    selected_EIP,esi
                .endif
       .endif



        push    eax
        mov     eax,ESI
        and     eax,eax
        jz  no_brkpt
        mov     ecx,Number_brkpts
        mov     edi,offset BreakPoint_EIP
        repne scasd
        pop     eax
        mov    brkpt_flag,False
        jne no_brkpt
           sub  edi,offset BreakPoint_EIP+4
           shr  edi,2
           mov   brkpt_flag,True
           mov  al,BreakPoint_saved[edi]                ; temperarly put
           mov  [esi],al                                ; in old intruction
          .if ah == selected_color
               mov   ah,selected_brkpt_color
          .else
               mov   ah,brkpt_color
          .endif


no_brkpt:



        mov     edi,(ScreenWidth*1 +1 )
        add     edi,count1
        add     count1,ScreenWidth
        draw_2char  'cs'
        draw_char  ':'
        mov     ebx,esi
        mov     cl,8
        call    print_hex

                  ;-- copy string buffer to screen ----
                .if     registers_save.prg_EIP == esi
                    mov    bl,4
                    mov  al,213
               @@:  call  _draw_char
                    inc   al
                    dec   bl
                    jnz @b
                .else
                    draw_horz ' ',4
                .endif

                ;======= plot the instuction ============
                push    edi
                mov     edi,offset string_buffer
                mov     ecx,edi
                call    decode_instruction
                sub     ecx,edi
                neg     ecx
                pop     edi


                  xor   ebx,ebx
             @@:  mov   al,string_buffer[ebx]
                  inc    ebx
                  call  _draw_char
                  dec    ecx
                  jnz @b
                  mov   ecx,43

;                .if  current_instruc > ' '
;                  .if conditional_jump == True
;                      draw_char ''
;                  .endif
;                  mov   ecx,42
;                .endif

                  mov   al,' '
             @@:  cmp   ebx,ecx
                  jae er4
                  call  _draw_char
                  inc    ebx
                  jmp @b
        er4:

                ;------- plot the effective address of the mod r/m field ----
       .IF (AH == selected_brkpt_color) || (AH == selected_color)

                 or InstCursor_flag,True
                 pushad
                 mov     edi,27
                .if MOD_RM_flag == True
                  mov   ah,back_color
                  draw_horz '═',33
                  mov     edi,27
                  mov     ah,back_color_EA
                  draw_char    ' '
                  mov   edx,op_seg_overide
                  .if edx == NULL
                    mov   edx,MOD_RM_DefaultSegmentReg
                  .endif
                  sub   edx,offset ES_symb
                  mov   ebx,ds:registers_save.prg_es[edx]
                  mov   cx,cs
                  .if   BX == CX
                     mov   ecx,Program_Addr
                  .elseif  BX == _TEXT
                     mov   ecx,Program_Addr
                  .elseif  BX == ZERO_SEL
                     xor        ecx,ecx
                  .else
                    add   edx,offset ES_symb
                    call  Plot_string
                    mov edx,offset inv_sel_mesg
                    jmp inval_addre             ; invalid sel if
                  .endif
                  mov   Segment_Base,ecx
                  add   edx,offset ES_symb
                  call  Plot_string

                  draw_2char    ':['
                  mov     ebx,MOD_RM_EffectiveAddress
                  mov   cl,8
                  call    print_hex
                  push ebx
                  draw_2char   '] '
                  draw_2char '= '
                  pop   ecx
                  add   ecx,Segment_Base
                  Call  Test_location           ; Test linear addr ECX

                    .if  testing_EA_TEXT == True
                           push     ebx
                           draw_char '0'
                          .if  MOD_RM_size == 3
                             mov    ebx,ecx
                             mov    cl,4
                             rol    ebx,16
                            call    print_hex
                            draw_char ':'
                          .endif
                           pop     ebx
                          .if  MOD_RM_size >= 2
	                     mov   cl,8
                          .elseif MOD_RM_size == 1
	                     mov   cl,4
                             rol    ebx,16
                          .else
                             mov   cl,2
                             rol    ebx,24
                          .endif
                            mov     testing_EA_TEXT,False
                            call    print_hex
                    .else
                       mov     edx,offset inv_adr_mesg
inval_addre:           call    Plot_String
                    .endif
                   draw_char ' '
                .else
                   mov   ah,back_color
                   draw_horz '═',33
                .endif
                 popad

        .ENDIF


         ;------- Put back break point if is here-------
        .if   brkpt_flag  == True
                mov     eax,screen_ending_EIP
                mov     byte ptr [eax],0CCh
        .endif

        inc	line_count
        cmp     line_count,(ScreenHeight-7)
        jb mainloop

     ; If the selected instruction was not displayed then
     ; replaot the screen with the selected instruction at the top.
     ;
        .If     InstCursor_flag == FALSE
           mov     selected_line,0
           mov     eax,registers_save.prg_EIP
           mov     Selected_EIP,eax
           mov     Screen_EIP_value,eax
           jmp  Plot_The_Instructions
        .Endif
        ret

inv_adr_mesg      db  'illegal address$'
inv_sel_mesg      db  ':   illegal selector$'
Bad_stack_mesg    db  '≡≡≡≡≡≡≡≡$'


refresh_screen ENDP











;========================================================================
;      ISR for terminate hooking  INT21h AH=4Ch
;
;  Used to trap any INT21h AH=4Ch. so can notify the user that the program
; has terminated
;
;=========================================================================
terminate_Hooker PROC PRIVATE
                 cli
        .IF ( ah == 4Ch ) && ( cs:InitDebugOnly == False ) && (cs:DebuggerTerminated == False)

                pushad
                push   es
                push   ds
                xor     eax,eax             ;disable debug registers
                mov     DR7,eax
                mov     ax,_TEXT
                mov     ds,ax
                mov     es,ax
                mov     users_screen,False
               .If Program_is_running
                 mov     users_screen,True
               .Endif
                call    debuggers_video
                mov     edx,offset exit_code
                call    print_message_box
                pop     ds
                pop     es
                popad
                sub     dword ptr [esp],2
                jmp     Handle_Debug_Exception
       .ENDIF
        jmp     cs:saved_int21
exit_code       db  ' Program terminated with exit code INT 21h AH=4Ch $'
terminate_Hooker ENDP





;===================================================================
;
;
;       PRINTS A MESSAGE IN THE SCREEN IN A BOX and waits for a key.
;Expects:
;              EDX = points to a string that ends with a '$'
;
;===================================================================
print_message_box       PROC PRIVATE
local height :byte
local lenth :byte
                mov     height,6
                mov     al,'$'
                mov     edi,edx
                push    edx
                cld
@@:             scasb
                jne @b
                sub     edi,edx
                add     edi,4
                mov     eax,edi
                mov     lenth,al
                shr     edi,1
                neg     edi
                add     edi,39+ScreenWidth* (ScreenHeight/2 - 3)
                push    edi
                mov     ah,mesg_box_color
                push    edi
                add     edi,ScreenWidth
                draw_vert '║',height
                pop     edi
                push    edi
                draw_char '╔'
                draw_horz '═',lenth
                draw_char '╗'
                add     edi,ScreenWidth-1
                draw_vert '║',height
                pop     edi
                add     edi,ScreenWidth+1
                mov     ch,height
@@:             push    edi
                draw_horz ' ',lenth
                pop     edi
                add     edi,ScreenWidth
                dec     ch
                jnz @b
                dec     edi
                draw_char '╚'
                draw_horz '═',lenth
                draw_char '╝'
                pop     edi
                mov     eax,ScreenWidth
                mul     height
                shr     eax,1
                add     edi,eax
                add     edi,3
                pop     edx
                mov     ah,mesg_box_text_color
                call    plot_string
                add     edi,ScreenWidth*3
                movzx   eax,lenth
                shr     eax,1
                sub     edi,eax
                mov     ah,(mesg_box_color and 0f0h) or 8
                mov     edx,offset mesg_OK_
                call    plot_string
                sub     edi,ScreenWidth+5
                mov     ah,0A1h
                mov     edx,offset mesg_OK
                call    plot_string
                mov     ah,(mesg_box_color and 0f0h) or 8
                draw_char '▄'

                mov     eax,Zero_addr   ; clear the keyboard buffer
                mov     dx,[eax+41ch]
                mov     [eax+41ah],dx
@@:
                in al,64h             ; Read key only when 8242 is ready
                test al,1
                jz @b
                in      al,60h          ; wait for enter key
                test    al,80h          ; see if was a release code
                jz  go_make
                INT 9                   ; Must send code to BIOS
                jmp @b
go_make:        sub     al,3Bh          ; loop if key was an Function key
                cmp     al,10
                jbe @b
                call    debuggers_video
                ret
mesg_OK db ' OK $'
mesg_OK_ db '▀▀▀▀$'
print_message_box       ENDP





;===================================================================
;
;
;      SETS UP THE VIDEO SCREEN FOR THE DEBUGGER
;
;
;===================================================================
debuggers_video PROC PRIVATE
        pushad


    .IF  Users_Screen

        call    save_CompleteVideoState

        mov   ax,83h            ; Goto VGA Text Mode 80x25
        int 	10h

        mov     bl,00h                 ;  Text Mode 80x50
        mov     ah,11h
        mov     al,12h
        int 10h

    .ENDIF





        ;------------------ put in my man -----------------------
    ;      set up registers to accsess Bit plane 2 only
    ; set for sequentual memory addressing
        mov dx,3C4h ; sequencer reg group
        mov al,4
        mov ah,0111b
        out dx,ax

        mov dx,3ceh ; The Graphics Controller reg group
    	mov al,6    ; Misellaneous Register
        mov ah,1100b
        out dx,ax

      ; set Map Mask Register
        mov dx,3c4h ; sequencer reg group
    	mov al,2
        mov ah,0100b    ;to write to bit plane 2
        out dx,ax

       ; can now fill up the video font memory
        cld
        mov     esi,offset man_font
        mov     edi,_0b8000h
        add     edi,20h*213                     ; put man at chars 213..216
        mov     ecx,20h*4
        rep     movsb



    ; set for sequentual memory addressing
        mov dx,3C4h ; sequencer reg group
        mov al,4
        mov ah,0011b
        out dx,ax

        mov dx,3ceh ; The Graphics Controller reg group
    	mov al,6    ; Misellaneous Register
        mov ah,1110b
        out dx,ax

      ; set Map Mask Register
        mov dx,3c4h ; sequencer reg group
    	mov al,2
        mov ah,0011b    ;to write to bit plane 1+0
        out dx,ax

        ;----- disable character blinking-------------------------
        mov     dx,3DAh
        in      al,dx
        mov     dl,0C0h
        mov     al,10h or 20h
        out     dx,al
        inc     dl
        in      al,dx
        and      al,NOT 8
        dec     dl
        out     dx,al

        ;----- turn off cursor -------------------------
        mov     dx,3D4h
        mov     ax,200Ah
        out     dx,ax



        ;---------------- draw the screen -----------------------
        mov     edi,_0B8000h
        mov     ax,back_color*256
        mov     ecx, ScreenWidth * ScreenHeight
        cld
        rep     stosw

        mov     ah,boarder_color
        mov     edi,(0+ 80*1 )
        draw_vert  '║',18+25
        draw_char  '╟'
        draw_horz  '─',59
        draw_char  '┤'
        mov     edi,(0+ 80*0 )
        draw_char  '╔'
        draw_horz  '═',59
        draw_char  '╤'
        draw_horz  '═',13
        draw_char  '╤'
        draw_horz  '═',4
        draw_char  '╗'
        mov     edi,(0+ 80*45 )
        draw_vert  '║',4
        mov     edi,(60+ 80*45 )
        draw_vert  '│',4
        mov     edi,(60+ 80*11 )
        draw_vert  '│',33
        mov     edi,(60+ 80* 1 )
        draw_vert  '│',9
        draw_char  '├'
        draw_horz  '─',13
        draw_char  '┴'
        draw_horz  '─',4
        draw_char  '╢'
        mov     edi,(79+ 80*1  )
        draw_vert  '║',9
        mov     edi,(79+ 80*11 )
        draw_vert  '║',38
        mov     edi,(74+ 80*1  )
        draw_vert  '│',9
        mov     edi,(64+ 80*11 )
        mov     edx,offset stk_mesg
        call    plot_string
        mov     edi,(61+ 80*(ScreenHeight-2) )
        mov     edx,offset stk_ptrmesg
        call    plot_string
        mov     edi,(80*1+62)
        mov     edx,offset EAX_symb
        mov     ah,registers_color
@@:     call    plot_string
        add     edi,80-3
        add     edx,1
        cmp     edx,offset EAX_symb+9*4
        jb  @b
        mov     edi,(80*1+76)
        draw_2char  'c='          ;-------- DRAW CARRY FLAG STATE ----------
        mov     edi,(80*2+76)
        draw_2char  'z='          ;-------- DRAW ZERO  FLAG STATE ----------
        mov     edi,(80*3+76)
        draw_2char  's='          ;-------- DRAW SIGN  FLAG STATE ----------
        mov     edi,(80*3+76)
        draw_2char  's='          ;-------- DRAW SIGN  FLAG STATE ----------
        mov     edi,(80*4+76)
        draw_2char  'o='          ;-------- DRAW OVERFLAW FLAG STATE ----------
        mov     edi,(80*5+76)
        draw_2char  'p='          ;-------- DRAW PARITY FLAG STATE ----------
        mov     edi,(80*6+76)
        draw_2char  'a='          ;-------- DRAW AUX FLAG STATE ----------
        mov     edi,(80*7+76)
        draw_2char  'i='          ;-------- DRAW INTERRUPT FLAG STATE ----------
        mov     edi,(80*8+76)
        draw_2char  'd='          ;-------- DRAW DIRECTION FLAG STATE ----------

        mov  Users_Screen , False
        popad
        ret
debuggers_video ENDP






;===================================================================
;
;
;     THIS PROC TRAPS ANY VIDEO MODE CHANGING  BY THE PROGRAM
;    So we can keep track of the video state at all times
;
;===================================================================
Video_mode_trap PROC PRIVATE
        pushfd
        push    ds
        push    es
        push    eax
        mov     ax,_TEXT
        mov     ds,ax
        mov     es,ax
        pop     eax
                cmp     byte ptr [esp+4*5],10h
                jne no_video_change
                cmp     ah,0
                jne no_video_change
                cmp     program_is_running, True
                jne no_video_change
                 push 10h
                 pushfd
                 push cs
                 push offset JO99
                 jmp saved_INT32
        JO99:
                  call    save_CompleteVideoState

no_video_change:
        pop     es
        pop     ds
        popfd
        jmp cs:saved_INT32
Video_mode_trap ENDP





;=========================================================================
;
;  The debugger's low level keyboard handler ( for traping CTRL-BREAK )
;
;=========================================================================
keyboard_ISR PROC PRIVATE
        test    byte ptr [esp+4*2+2],10b    ; don't trap if was in V86 mode
        jnz    noPM
        push    ds
        push    es
        pushad
        mov     ax,_TEXT
        mov     ds,ax
        mov     es,ax

        in al,60h       ;get scan code from perifial port A

     .if program_is_running == True

        .if scan_coden == 0
            cmp  al,0e0h
            jne no_break
        .elseif  scan_coden == 1
            cmp  al,046h
            jne no_break
        .elseif  scan_coden == 2
            cmp  al,0e0h
            jne no_break
        .elseif  scan_coden == 3
            cmp  al,0c6h
            jne no_break
                ;-------- set the ctrl-breaker -----------
                mov     al,20h               ; Send EOI cmd to 8259
                out     20h,al
                mov program_is_running , False
                call    debuggers_video
                mov     edx,offset user_ctrl_breaked
                call    print_message_box
                popad
                pop     es
                pop     ds
                or      byte ptr [esp+4*2+1],1   ; set TF
                jmp    Handle_Debug_Exception
        .ENDIF
         inc    scan_coden

   .ENDIF


noTrap:
        popad
        pop     es
        pop     ds
noPM:   jmp cs:saved_IRQ1

no_break:
        mov    scan_coden,0
        jmp noTrap

scan_coden      db 0
user_ctrl_breaked   db ' Program Stoped with CTRL-BREAK  $'

keyboard_ISR ENDP




;===========================================================================
;
;    This is the INT 3 breakpoint exception handler.
;
;
;
;===========================================================================
BreakPoint_Exception                                    PROC PRIVATE
        push    ds
        pushad
        mov     ax,_TEXT
        mov     ds,ax

        mov     eax,Zero_addr   ; clear the keyboard buffer
        mov     dx,[eax+41ch]
        mov     [eax+41ah],dx

         cmp    special_brkpt,True
         je     special_CCh
nospecial_CCh:
        mov     eax,[esp+4*9]           ; get EIP from stack
        push    es
        push    ds
        pop     es
        dec     eax
        mov     ecx,Number_brkpts
        mov     edi,offset BreakPoint_EIP
        cld
        repne scasd
        pop     es
        jne  not_a_brkpt

                ;---------- put back origonal intruction --------------
                dec    dword ptr [esp+4*9]        ; decreament  EIP on stack
                sub     edi,offset BreakPoint_EIP+4
                shr     edi,2
                mov     dl,BreakPoint_saved[edi]
                mov     [eax],dl        ; restore byte in the instruction

        .if  program_is_running == True
           popad
           pop     ds
           or      byte ptr [esp+4*2+1],1   ; set Trap Flag on stack
           jmp   Handle_Debug_Exception
        .else
           popad
           pop     ds
           iretd                          ; set to debugging mode (again)
        .endif



not_a_brkpt:    ;-------------------------------------------------
        cmp     byte ptr [eax],0CCh
        je     normal_CCh
        dec     eax
        cmp     word ptr [eax],03cdh
        je      normal_INT_3
        popad
        pop     ds
        iretd



normal_CCh:
        .if  program_is_running == True
           sub   dword ptr [esp+4*9],1       ; decreament  EIP on stack
           jmp exit
        .endif
        jmp exit


normal_INT_3:
        .if  program_is_running == True
           sub   dword ptr [esp+4*9],2       ; decreament  EIP on stack
           jmp exit
        .endif
         popad
         pop     ds
         iretd

special_CCh:
         mov     ebx,dword ptr [esp+4*9]      ; look to see if on a special
         dec    ebx
         mov     eax,special_brkpt_EIP
         cmp    ebx,eax
         jne   nospecial_CCh
         mov    special_brkpt,False
         dec     dword ptr [esp+4*9]
         mov     dl,special_brkpt_save
         mov     [eax],dl                ; delete the 0CCh

exit:
           popad
           pop     ds
           or      byte ptr [esp+4*2+1],1   ; set Trap Flag on stack
           jmp   Handle_Debug_Exception


BreakPoint_Exception    ENDP






;===========================================================================
;
;    The General Protection handler  ( Interrupt 13 )
;
;
;===========================================================================
GeneralProtection_Exception               PROC PRIVATE


   ; Read the ISR (Interrupt Service Register) to see if a IRQ is waiting
   ; to be serviced.
   ;
        push   eax
        mov     al,00001011b    ; OCW3 to read ISR on next read
        out     20h,al          ; write to base I/O address of 8259A
        in      al,20h          ; read ISR
        and     al,al
        pop     eax
        jz    non_V86_exec        ; Brach if a IRQs is not awaiting
        jmp  cs:old_IntVect13

non_V86_exec:
        add     esp,4
        push    edx
        mov     edx,offset GP_mesg
        jmp   Close_the_fatal_falt

align 4

old_IntVect13   df 0
GP_mesg 	db  'Instruction Caused a General Protection Exception $'

GeneralProtection_Exception  endp

;===========================================================================
;
;    The Invalid Opcode handler  ( Interrupt 6 )
;
;
;===========================================================================
InvalidOpcode_Exception                                     PROC PRIVATE
        push    edx
        mov     edx,offset badI_mesg
        jmp   Close_the_fatal_falt

badI_mesg db  'Program executed an Invalid Opcode $'

InvalidOpcode_Exception    ENDP

;===========================================================================
;
;    The Divide by Zero handler  ( Interrupt 0 )
;
;
;===========================================================================
DivideError_Exception                                     PROC PRIVATE
        push    edx
        mov     edx,offset divide0_mesg
        jmp   Close_the_fatal_falt

divide0_mesg db  '  Division By Zero Error$'


DivideError_Exception    ENDP

;===========================================================================
;
;    The Page Fault handler  ( Interrupt 14 )
;
;
;===========================================================================
PageFalts_Exception                                     PROC PRIVATE


   ; Read the ISR (Interrupt Service Register) to see if a IRQ is waiting
   ; to be serviced for VCPI server.
   ;
        push   eax
        mov     al,00001011b    ; OCW3 to read ISR on next read
        out     20h,al          ; write to base I/O address of 8259A
        in      al,20h          ; read ISR
        and     al,al
        pop     eax
        jz    skip_8259pf        ; Brach if a IRQs is not awaiting
        jmp  cs:old_IntVect14

skip_8259pf:

        add     esp,4
         .IF  cs:Testing_EA_TEXT == True
            push  ds
            push  dword ptr _TEXT
            pop   ds
            mov   Testing_EA_TEXT,False
            pop   ds
            add   dword ptr [esp],tea_ins_size ; skip intruction that caused
            iretd
         .ENDIF
        push    edx
        mov     edx,offset PF_mesg
        jmp   Close_the_fatal_falt

PF_mesg 	db  'Instruction caused a Page Falt $'
old_IntVect14   df 0

PageFalts_Exception    ENDP


;===========================================================================
;

; This rotine displays the  exception error message and stuff
; Used by the above CPU exception routines

;===========================================================================
Close_the_fatal_falt PROC PRIVATE
        push    ds
        push    es
        pushad
        mov     ax,_TEXT
        mov     ds,ax
        mov     es,ax

        xor     eax,eax                         ;disable debug registers
        mov     DR7,eax
        mov     eax,[esp+4*11]          ; get EIP from stack
        mov     Step_flag,True
        mov     Selected_EIP,eax
        mov     screen_EIP_value,eax
        mov     registers_save.prg_EIP,eax
        mov     registers_save.prg_CS,cs
        cld
        push    edx
        call    debuggers_video
        call    refresh_screen
        pop     edx
        call    print_message_box
        popad
        pop     es
        pop     ds
        pop     edx
        or      byte ptr [esp+4*2+1],1          ; set Trap Flag on stack
        jmp   Handle_Debug_Exception          ; set to debugging mode (again)
Close_the_fatal_falt ENDP



hardwareInstruc_mesg   db ' Instruction Fault on Breakpoint Register '
DRx_mesg1        db '    $'
hardwareData_mesg   db '  Data Trap on Breakpoint Register '
DRx_mesg2        db '    $'






;===========================================================================
;
;     THE MAIN  DEBUG EXCEPTION HANDLER     ( INTERRUPT ONE )
;
;
;===========================================================================
Debug_Exception PROC PRIVATE
        pushad
        push    ds
        push    es
        mov     ax,_TEXT
        mov     ds,ax
        mov     es,ax
         .IF  cs:Testing_EA_TEXT == True
            mov   Testing_EA_TEXT,False
            pop     es
            pop     ds
            popad
            iretd               ; return  to intruction on in EA test mode
         .ENDIF

        ;=================  GET DEBUG EXCEPTION STATUS from DR6 ========
                mov     eax,DR6
                mov     ebx,DR7
                mov     DRx_mesg1,'0'
                mov     DRx_mesg2,'0'
                test    al,1
                jz brkpt1
                 test  bl,3
                 jz brkpt1
                 shr    ebx,16
                 jmp found_brkptReg

brkpt1:         mov     DRx_mesg1,'1'
                mov     DRx_mesg2,'1'
                test    al,2
                jz brkpt2
                 test  bl,0ch
                 jz brkpt2
                 shr    ebx,20
                 jmp found_brkptReg

brkpt2:         mov     DRx_mesg1,'2'
                mov     DRx_mesg2,'2'
                test    al,4
                jz brkpt3
                  test  bl,030h
                 jz brkpt3
                 shr    ebx,24
                 jmp found_brkptReg

brkpt3:         mov     DRx_mesg1,'3'
                mov     DRx_mesg2,'3'
                test    al,8
                jz no_brkpt
                  test  bl,0c0h
                  jz no_brkpt
                  shr    ebx,28
found_brkptReg:
                test     bl,03
                jz  RW0
                push     offset hardwareData_mesg
                jmp RW1
       RW0:     push    offset hardwareInstruc_mesg
       RW1:     call    Debuggers_video
                mov     eax,[esp+4*11]          	; get EIP form stack
                mov     Selected_EIP,eax
                mov     step_flag,True
	        mov     registers_save.prg_EIP,eax
                call    refresh_screen
                pop     edx
                call    print_message_box
                or      dword ptr [esp+4*12],010100h    ; Set the TF and RF
                jmp Step_debug


no_brkpt:
        test    eax,4000h
        jz   normal_INT1


Step_debug:
                xor     eax,eax
                mov     DR6,eax         ; must clear the DR6 bits
normal_INT1:    pop     es
	        pop     ds
                popad
                jmp handle_Debug_Exception

Debug_Exception ENDP






;===========================================================================
;
;     THE GENARAL DEBUG EXCEPTION HANDLER for exceptions from  breakpoints
; , TF or  any breakpoint registers.
;
;   This is the main routine of the whole debugger.
;
;===========================================================================
Handle_Debug_Exception PROC PRIVATE
        push    ds
        push    dword ptr _TEXT
        pop     ds
        pop     registers_save.prg_ds
        pop     registers_save.prg_EIP
        pop     registers_save.prg_cs
        pop     registers_save.prg_eflags

        mov     registers_save.prg_Eax, eax
        mov     registers_save.prg_Ebx, ebx
        mov     registers_save.prg_Ecx, ecx
        mov     registers_save.prg_Edx, edx
        mov     registers_save.prg_Edi, edi
        mov     registers_save.prg_Esi, esi
        mov     registers_save.prg_Ebp, ebp
        mov     registers_save.prg_Esp, esp
        mov     registers_save.prg_ss , ss
        mov     registers_save.prg_es , es
        mov     registers_save.prg_fs , fs
        mov     registers_save.prg_gs , gs
        pushad
        push    fs
        push    es
        push    ds                         ; Load ES with data selector
        pop     es
        cld
;-------------------------------------------------------------------

        mov     program_is_running,False

        .if haveOrigonalRegisters == False
                mov     edi,offset origonal_registers
                mov     esi,offset registers_save
                mov     ecx,(SIZEOF registers_save)/4
                rep     movsd
                mov     haveOrigonalRegisters,True
        .endif

        mov     eax,registers_save.prg_EIP
        mov     Selected_EIP,eax
        mov step_flag,True


        .if  Users_Screen  == True
           call    Debuggers_Video
        .endif


       .if InitDebugOnly == True
         mov    edx,offset intro_mesg
         call   print_message_box
         mov    InitDebugOnly,False
      .endif


main_loop:


        call    refresh_screen

key_waitloop:

                test    Key_flags,010b       ; look at CTL flag
                jz no_ctrl
                call   Display_DRx_info
                mov     edi,(0 + 80*49 )
                mov     ah,menu_color
                draw_horz ' ',80
                jmp  skip_disp
no_ctrl:
                test    Key_flags,1       ; look at ALT flag
                jnz disp_nalt
                 call         Display_SegReg_info
                 mov     edx,offset menu_bar_text
                 jmp disp_alt
disp_nalt:
               mov     edx,offset menu_alt_bar_text

disp_alt:       mov     edi,(0 + 80*49 )
	        mov     ah,menu_color
                call    plot_string
skip_disp:



;=======================================================


        in      al,64h
        test    al,1
        jz key_waitloop
        in      al,60h



        .if     al == 38h                       ; set for 'Alt'
                or  Key_flags,1
        .elseif al == 38h or 80h
                and Key_flags,Not 1             ; clear 'Alt'

        .elseif al == 1Dh                        ; set for 'Ctrl'
                or Key_flags,2
                INT 9
        .elseif al == 1Dh or 80h
                and Key_flags,Not 2             ; clear 'Ctrl'
                INT 9
        .endif

               push   eax
               in al,61h                ; (pulse PPI port B bit 1
               or al,80h       ;set bit 7   ; to acknoledge the keyboard)
               out 61,al
               and al,7fh      ;clear bit 7
               out 61h,al
               pop   eax

        test    al,80h
        jnz key_waitloop
        mov     ah,al

        mov     al,Key_flags



        .if    ah == 50h
           inc  selected_line
        .elseif ah == 48h
           dec  selected_line
        .endif
        cmp ax , 3F01h            ;alt+F5
        je user_screen
        cmp  ax, 4300h            ;F9
        je run_program
        cmp  ax, 4301h            ;alt+F9
        je goto_start
        cmp  ax, 3E00h            ;F4
        je  here
        cmp  ax, 3C00h            ;F2
        je  set_brkpt
        cmp ax , 4200h            ;F8
        je  large_steping
        cmp  ax, 4100h            ;F7
        je step_intruc
        cmp  ax, 3E01h            ;alt+F4
        je  back_step
        cmp  ax, 2D01h            ;alt+X
        je exit_program
        cmp  ah, 51h              ; pgDown
        je  page_Down
        cmp  ah, 49h              ; pgUP
        je  page_Up
        jmp main_loop





continue_debugging:

        pop     es
        pop     fs
        popad
        mov     ds,registers_save.prg_ds
        push    cs:registers_save.prg_eflags
        push    cs:registers_save.prg_cs
        push    cs:registers_save.prg_EIP
        iretd


page_Up:
         sub    selected_line,(ScreenHeight-10)
         jmp main_loop

page_Down:
        mov     eax,screen_ending_EIP
        mov     screen_EIP_value,eax
        jmp main_loop



large_steping:
        mov     eax,registers_save.prg_EIP
        mov     ecx,Number_brkpts
        mov     edi,offset BreakPoint_EIP
        repne scasd
        jne @f
         sub    edi,offset BreakPoint_EIP+4
         shr    edi,2
         mov    dl,BreakPoint_saved[edi]
         mov    [eax],dl
@@:
        mov     esi,eax
        mov     edi,offset string_buffer
        call    Decode_instruction
        cmp     dword ptr string_buffer,06c6c6163h       ; look for "call"
        je  skipcall
        cmp     dword ptr string_buffer,0706f6f6ch       ; look for "loop"
        je  skipcall
        and     dword ptr string_buffer,0ffffffh
        cmp     dword ptr string_buffer,00706572h       ; look for "rep"
        jne  step_intruc

 skipcall:
                  call    CheckVGAport
                  mov     special_brkpt_EIP,esi
                  mov     dl,[esi]
	          mov     special_brkpt_save,dl
                  mov     byte ptr [esi],0CCh          ; insert the CC
                  mov     special_brkpt,True
                  mov     program_is_running,True
                  call    restore_video            ; goto users screen
                  and      registers_save.prg_eflags,not 00100000000b
                  mov        BacklogRegPTR_head,0         ; clear backlog
                  mov        BacklogRegPTR_tail,0
                  jmp continue_debugging




step_intruc:
        call    Update_register_LOG
        mov     eax,registers_save.prg_EIP
        mov     ecx,Number_brkpts
        mov     edi,offset BreakPoint_EIP
        repne scasd
        jne @f
         sub    edi,offset BreakPoint_EIP+4
         shr    edi,2
         mov    dl,BreakPoint_saved[edi]
         mov    [eax],dl
@@:
        call  CheckVGAport
        .if   byte ptr  [eax] == 0CDh      ;see if a INT n instruction
          .if  byte ptr  [eax+1]  == 21h     ; must not stop INt 21h ah=4ch
           cmp byte ptr  registers_save.prg_eax+1,04Ch
           je continue_debugging
          .endif
          add     eax,2
          mov     special_brkpt_EIP,eax
          mov     dl,[eax]
          mov     special_brkpt_save,dl
          mov     byte ptr [eax],0CCh              ; insert the CC
          mov     special_brkpt,True
          mov        BacklogRegPTR_head,0         ; clear backlog
          mov        BacklogRegPTR_tail,0
          mov     program_is_running,True
          call    restore_video            ; goto users screen
          and      registers_save.prg_eflags,not 00100000000b
          jmp continue_debugging
        .endif
        jne continue_debugging


run_program:
        mov        BacklogRegPTR_head,0         ; clear backlog
        mov        BacklogRegPTR_tail,0
        call    restore_video
        mov     eax,registers_save.prg_eip
        mov     ecx,Number_brkpts
        mov     edi,offset BreakPoint_EIP
        repne scasd
        je continue_debugging   ; don't run a debugger break point
        .if    byte ptr [eax] == 0CCh       ; don't run a users break point
            inc  registers_save.prg_eip
        .elseif word ptr [eax] == 03CDh
            add  registers_save.prg_eip,2
        .endif
        mov     program_is_running,True
        and      registers_save.prg_eflags,not 00100000000b
        jmp continue_debugging

exit_program:
        xor     eax,eax             ;disable debug registers
        mov     DR7,eax
;        mov     ax,003h            ; Goto normal text mode on exit
;        int     10h
;       cmp  prg_VideoMode, 3
;       je  Jd3
;       cmp  prg_VideoMode, 83h
;       jne  Jl2
;Jd3:
        call  Restore_Video      ; Goto normal users mode on exit
Jl2:
        mov     ah,03              ;- Restore keyboard typmatic rate
        mov     al,05h
        mov     bl,Kbd_Rate             ; Rate  (0..1fh)
        mov     bh,Kbd_Delay            ; Delay (0..3)
        cmp     bl,-1
        je @f
        int  	16h
@@:     mov     DebuggerTerminated,True
        mov     ax,4C00h
        int     21h                  ; Terminate to Operating system

user_screen:
        call    Restore_video

@@:
                in al,64h             ; Read key only when 8242 is ready
                test al,1
                jz @b
                in      al,60h          ; wait for enter key
               .if     al == 38h                       ; set for 'Alt'
                  or  Key_flags,1
               .elseif al == 38h or 80h
                  and Key_flags,Not 1             ; clear 'Alt'
               .endif
                test    al,80h          ; loop if release code
                jnz  @b
        call    Debuggers_Video
        jmp main_loop


here:
        mov     eax,Selected_EIP
        mov      registers_save.prg_EIP,eax
        jmp main_loop

goto_start:
        call    debuggers_video
        mov        BacklogRegPTR_head,0
        mov        BacklogRegPTR_tail,0
        mov        Step_flag,True
       .if haveOrigonalRegisters == True
                mov     esi,offset origonal_registers
                mov     edi,offset registers_save
                mov     ecx,(SIZEOF registers_save)/4
                rep     movsd
        .endif
        call    refresh_screen
        jmp    load_all_regs




;============================ The Break Point mangaging routine ===========
set_brkpt:
        mov     eax,Selected_EIP
        mov     ecx,Number_brkpts
        mov     edi,offset BreakPoint_EIP
        repne scasd
        je  Deleate_brkpt
        xor     eax,eax
        mov     ecx,Number_brkpts
        mov     edi,offset BreakPoint_EIP
        repne scasd
        je insert_a_brkpt

            ;------ show that no more break points can be used---------
                mov     edx,offset brkpts_are_full_mesg
        	call    print_message_box
                jmp main_loop
	brkpts_are_full_mesg label byte
        db 'No more than 50 Breakpoints can be assigned $'



Deleate_brkpt:
        sub     edi,offset BreakPoint_EIP+4

                ;---------- take away the break point --------------
                mov     BreakPoint_EIP[edi],0
                shr     edi,2
                mov     dl,BreakPoint_saved[edi]
                mov     eax,Selected_EIP
                mov     [eax],dl        ; restore byte in the instruction
                jmp main_loop




insert_a_brkpt:
        sub     edi,offset BreakPoint_EIP+4
        mov     eax,Selected_EIP
        mov     dx,[eax]                ; save byte in the instruction
        cmp     dl,0cch    ; not allowed to put brk pts on top of brk pts
        je stupid_person
        cmp     dx,03CDh
        je stupid_person
        mov     BreakPoint_EIP[edi],eax
        shr     edi,2
        mov     BreakPoint_saved[edi],dl
        mov     byte ptr [eax],0CCH            ; but in a INT 3

        jmp main_loop

stupid_person:
        mov     edx,offset mesg_1234
        call    print_message_box
        jmp main_loop
mesg_1234       db 'Are you stupid?  You can''t put a Breakpoint on a Breakpoint ¡$'






back_step:
        mov     eax,BacklogRegPTR_head
        .if     BacklogRegPTR_tail  != EAX
                sub     eax, SIZEOF program_reg
                jge @f
                 mov eax,SIZEOF registers_saved_backlog - SIZEOF program_reg
            @@: mov        BacklogRegPTR_head,eax

                ;------ copy all regs into back log --------------
                mov        esi,BacklogRegPTR_head
                mov        BacklogRegPTR_head,eax
                add        esi,offset registers_saved_backlog
                mov        edi,offset registers_save
	        mov        ecx,(SIZEOF program_reg ) /4
	        rep        movsd
        .else
                jmp main_loop
        .endif


        pop     es
        pop     fs
        popad


load_all_regs PROC PRIVATE
        mov     eax,registers_save.prg_Eax
        mov     ebx,registers_save.prg_Ebx
        mov     ecx,registers_save.prg_Ecx
        mov     edx,registers_save.prg_Edx
        mov     edi,registers_save.prg_Edi
        mov     esi,registers_save.prg_Esi
        mov     ebp,registers_save.prg_Ebp
        mov     esp,registers_save.prg_Esp
        mov     ss,registers_save.prg_ss
        mov     es,registers_save.prg_es
        mov     fs,registers_save.prg_fs
        mov     gs,registers_save.prg_gs

        mov     ds,registers_save.prg_ds
        push    cs:registers_save.prg_eflags
        push    cs:registers_save.prg_cs
        push    cs:registers_save.prg_EIP
        jmp     Handle_Debug_Exception

load_all_regs ENDP



Handle_Debug_Exception ENDP




;----------------------------------------------------------------------
;
; The following routines are used to make calling DOS32 services easier.
;----------------------------------------------------------------------


SetIntVector    PROC PRIVATE Uses Eax
        mov     ax,0205h
        int     31h
        ret
SetIntVector    ENDP

GetIntVector    PROC PRIVATE Uses Eax
        mov     ax,0204h
        int     31h
        ret
GetIntVector    ENDP

GetIrqVector    PROC PRIVATE Uses Eax Ebx
        cmp     bl,8h
        jb @@j1
        add     bl,60h
@@j1:   add     bl,8
        mov     ax,0204h
        int     31h
        ret
GetIrqVector    ENDP

SetIrqVector    PROC PRIVATE  Uses Eax Ebx
        cmp     bl,8h
        jb @@j1
        add     bl,60h
@@j1:   add     bl,8
        mov     ax,0205h
        int     31h
        ret
SetIrqVector    ENDP






debugger_ending     EQU  $       ; Define the debuggers ending address

END



















\\\\\\\
[ RETURN TO DIRECTORY ]