;***************************************************************************
; EG6.ASM
;              This does lots of simple things with the extender.
;
;***************************************************************************

.386
.model flat
.stack 200h
.code



memory_pointer  dd 0
File_handle     dw 0
message1        db      ' Reading the file "EXAMPLE1.EXE" into some allocated memory.',10,13
                db      ' Also hooking IRQ 0 ( the timer ) and altering the VGA color 0',10,13
                db      'register.     Press any key to stop',10,13,36

message2        db      10,10,'Everything was successful $'
message3        db      10,10,'Something went wrong $'
Old_IRQ0_vector df 0



start_Example1:                               ; Start of the program


;********************************************************************
;               DISPLAY A MESSAGE

        mov     edx,offset message1
        mov     ah,9                       ; Print string DS:EDX -> string
        int     21h                        ; call a DOS type service




;********************************************************************
;               ALLOCATE  SOME MEMORY

        mov     edx,4000h               ; allocate a 16K memory
        mov     ax,0EE42h
        int     31h                     ; returns EDX = offset of block
        jc   exit_unsucsessfuly         ; jump if error
     	mov   memory_pointer,edx        ; save the block pointer




;********************************************************************
;               LOAD THIS FILE INTO MEMORY

        mov     ax,0EE02h               ; Get DOS32 Address info
        int     31h                     ; ECX -> .EXE file name/path

        mov     edx,ecx                 ; let DS:EDX points to file name
        mov     ah,3Dh                  ; Open the file
        mov     al,00h                  ; opening flags.  0 = read only
        int     21h
        jc exit_unsucsessfuly           ; exit if error
        mov     File_handle,ax          ; save the file handle


        mov     ecx,4000h               ; try to read 16Kb of file
        mov     edx,memory_pointer      ; DS:EDX -> receive buffer
        mov     bx,File_handle          ; BX = handle
        mov  	ah,3Fh
        int     21h                     ; Read file


        mov  	bx,file_handle           ; Close the file
        mov  	ah,3Eh
        int  	21h



;********************************************************************
;               HOOK  IRQ 0  ( TIMER INTERRUPT )

       ;------ save origonal interrupt vector ------------
       mov      bl,8                            ; BL = int number.
       mov      ax,0204h
       int      31h                             ; Call the service.
       mov      Dword Ptr Old_IRQ0_vector,edx   ; Save vector as a 48 bit far
       mov      Word Ptr Old_IRQ0_vector+4,cx   ;  pointer.



       ;------ set the new interrupt vector --------------
       mov      BL,8                            ; BL = int number
       mov      EDX,offset Timer_Interrupt      ; EDX = offset of int vector
       mov      cx,cs                           ; CX = selector value
       mov      ax,0205h
       int      31h                             ; Call the service.

         ;( see below for the hadrware interrupt handler )




;********************************************************************
;               WAIT FOR A KEY TO BE PRESSED

                mov     ah,0                    ; use the BIOS services
                int     16h




;********************************************************************
;               DISPLAY A SUCCESSFUL MESSAGE

        mov     edx,offset message2
        mov     ah,9
        int     21h



;********************************************************************
;               RESTORE ORIGONAL IRQ 0  ( TIMER INTERRUPT )

       mov      BL,8                            ; BL = int number
       mov      edx,dword ptr Old_IRQ0_vector   ; Get vector as a 48 bit far
       mov      cx,word ptr Old_IRQ0_vector+4   
       mov      ax,0205h
       int      31h                             ; Call the service.




;********************************************************************
;                      RESTORE THE VGA COLOR 0 REGISTER TO BLACK

                mov     dx,3c8h
                mov     al,0
                out     dx,al
                inc     dl
                out     dx,al
                out     dx,al
                out     dx,al


;********************************************************************
;                      TERMINATE THIS WONDERFUL PROGRAM
exit_program:

	        mov   ah,4ch
                int   21h





;********************************************************************
;               DISPLAY A UNSUCCESSFUL MESSAGE AND EXIT
exit_unsucsessfuly:

        mov     edx,offset message3
        mov     ah,9
        int     21h
        jmp exit_program





;********************************************************************
;               OUR  HARDWARE INTERRUPT HANDLER

Timer_Interrupt:
        push    ds                           ; Save segemnt registers
        push    edx                          ; must save all registers used.
        push    eax

        mov     ax,_TEXT                 ; load ax with program data selector
        mov     ds,ax                    ; and put it in DS.



     ;lets do something so we know this interrupt handler is working.

        mov     dx,3C8h                 ; Set color register number 0
        mov     al,0
        out     dx,al
        inc     dl
        mov     al,color0_red
        out     dx,al
        mov     al,color0_green
        out     dx,al
        mov     al,color0_blue
        out     dx,al

        inc     color0_blue               ; Update blue
        add     color0_red,2                ; Update red
        add     color0_green,3              ; Update green
        and     color0_blue,1fh
        and     color0_green,1fh
        and     color0_red,1fh


        pop     eax                       ; restore ALL saved registers
        pop     edx
        pop     ds
        jmp     cs:Old_IRQ0_vector        ; Note we must use CS:
                                          ; because DS can equal
                                          ; anything.

color0_green    db 0
color0_blue     db 0
color0_red      db 0




END  start_Example1
