;**************************************************************************
;  EG5.ASM
;
; This program hooks IRQ 0 and loads and executes COMMAND.COM
;
; By Adam Seychell
;**************************************************************************
.386
.model  flat
.stack 400h
.code



align 4

saved_INT8              DF 0
comspec_ptr             dd 0
dummy_cmd_tail  	db 1,' '
meag_v86        	db ' Exiting protected mode ',10,13,36
mesg_pmode      	db 'Got into 32bit protected mode ',10,13
                	db  10,'Press any key to load and execute COMMAND.COM$'



start32:                ; 32 bit code entry point.



      ; *****************  print a message *****************

        mov edx,offset mesg_pmode
        mov ah,9
        int 21h                     ; print string





    ;********** Hook Timer inerrupt ( IRQ 0 ) just for fun ****************

        mov     bl,8                        ;Save IRQ 0 interrupt vector
        mov     ax,204h
        int     31h
        mov     dword ptr saved_INT8 , edx
        mov     word ptr saved_INT8+4 , cx

        mov     bl,8                      ; Set the new IRQ 0 vector
        mov     edx,offset  timer_int     ; See below
        mov     cx,cs                     ; CS:EDX = selector:offset
        mov     ax,205h
        int     31h


        mov     ah,0                    ; wait for key
        int     16h


;************** LOAD AND EXECUTE A PROGRAM ( command.com ) *****************

;
; search for the "COMSPEC=" environemnt varibles
;

        mov     ax,0EE02h            ; Get DOS32 address information
        int     31h                  ; Returns EDI -> environment address
get_str_loop:
        cmp     dword ptr [edi],'SMOC'          ; cmp the string "COMSPEC="
        jne not_string
        cmp     dword ptr [edi+4],'=CEP'
        je got_string                           ; if equal exit loop
not_string:
        mov     al,0                            ; Scan environment for a zero
        mov     ecx,20000                       ; and get next varible
        repne   scasb
        jmp  get_str_loop                       ; loop around again

got_string:
        add     edi,8
        mov     comspec_ptr,edi                 ; save address of the envir


;
; Call the 32bit version of the "load and execute" DOS service
;
        mov     ah,4Bh
        mov     al,0
        mov     edi,00000                       ; DS:EDI -> envrironment
        mov     esi,Offset dummy_cmd_tail       ; DS:ESI -> command tail
        mov     edx,comspec_ptr         	; DS:EDX -> ASCIIZ string
        Int     21h

;******* restore origonal interrupt vector ********************

        mov     edx,dword ptr saved_INT8 
        mov     cx,word ptr saved_INT8+4 
        mov     bl,8                      ; Set the new IRQ 0 vector
        mov     ax,205h
        int     31h



; *****************  print another message *****************
        mov edx,offset meag_v86
        mov ah,9
        int 21h

exit:
        mov   ax,4c00h            ; Terminate program
        int   21h


;
; *****************  IRQ 0  interrupt  handler *****************
;
timer_int:
        push  ds                        ; must save all registers used
        pushad
        mov   ax,_TEXT
        mov   ds,ax                    ; Load DS with data selector
        mov   ax,0EE02h                 ; Get DOS32 Address information
        int   31h
        neg   ebx                       ; EBX = program address
        add   ebx,0b8000h               ; Convert EBX to video memory
        inc word ptr [ebx]              ; increment character on the screen
                                        ; just to show it's doing something
        popad
        pop   ds
        jmp   cs:saved_INT8             ; continue on interrupt chain.
                                        ; must use CS because DS is unknown


END Start32
