Question

I'm trying to override the default interruption when a key is pressed. Here is my code : I don't understand why it doesn't work, it works with others INT numbers (43h for example)

mov al,9h
mov ah,25h
mov bx,seg int9h
mov ds,bx
mov dx,offset int9h
int 21h

(Where int9h is a label in my code) Does anyone know how to hook the interruption when a key is pressed ? Thanks !

EDIT:

mov     ax,2509h
mov     dx,offset int9h
int     21h            

int9h PROC
    ;do some stuff
    IRET 
int9h ENDP
Was it helpful?

Solution

I'll try and answer this again - in a somewhat long-winded fashion.

Before Windows became prevalent, DOS ruled the computer. In order to extend its functionality, people used to write TSR (terminate and stay resident) programs; these programs would hook various interrupt functions (such as the clock and the keyboard), terminate and then stay resident in memory. As a result, when the given interrupt occurred, the resident code of these utilities would handle the interrupt, possibly calling the original interrupt handler.

Such programs would have a structure composed of two sections: the transient part and the resident part. The transient part would be the code which would run when the program was invoked from the command line; this would check whether the resident part had already been installed. If the resident part had been installed, the program would simply exit, but if this was the first invocation, the program would first save the address of the current interrupt handler, then install its own code as the new interrupt handler and then make a special DOS call which would leave the handler code in memory.

The code which you have shown is part of the transient program where the new interrupt handler is installed into the interrupt table. This code should only ever run once and is certainly not part of the new interrupt handler itself.

TSR programs became obsolete when the use of Windows became widespread. In a sense, every program run under Windows is a TSR program, and what was the keyboard interrupt handler code now becomes a keyboard event which is handled (in Delphi, for example) in an 'OnKeyPress' function.

The following code changes the interrupt table

mov ax, 2509h
mov dx, offset kb_handler
int 21h

The code which begins at the address *kb_handler* is the actual interrupt handler.

What you are doing is repeatedly setting the address of the interrupt handler as opposed to handling the interrupt. Your above code should be run only once when the program itself is installed; the interrupt handler code will be called many times.

I hope that this makes things clearer.

What you haven't written is why you are doing this.

OTHER TIPS

I dug the following code out of my archive (it's dated 24/06/1995); this is the keyboard handler for a program which I wrote which blanks the screen if both shift keys are pressed.

kb_int      proc    far
            pushf                           ;Save FLAGS
            push    ax                      ;Save AX
            in      al,60h                  ;Read the scan code
            mov     cs:[scancode],al        ;Save it
            pop     ax                      ;Restore AX
            popf                            ;Restore FLAGS
            pushf                           ;Push FLAGS
            call    cs:[int09h]             ;Call previous handler
            sti                             ;Enable interrupts

            test    cs:[scancode],80h       ;Exit if high bit of scan
            jnz     kb_exit                 ;  code is set

            push    ax                      ;Save AX and ES
            push    es
            mov     ax,40h                  ;Point ES to the BIOS
            mov     es,ax                   ;  Data Area
            mov     al,es:[17h]             ;Get keyboard flags
            and     al,03h                  ;Zero the upper 6 bits
            cmp     al,03h                  ;Are the Shift keys pressed?
            pop     es                      ;Restore AX and ES
            pop     ax
            jne     kb2                     ;Branch if they're not
            call    disable_video           ;Blank the screen
            iret                            ;Return from interrupt
kb2:        push    cs:[time]               ;Reset countdown timer
            pop     cs:[count]
            cmp     cs:[blanked],0          ;Is the screen blanked?
            je      kb_exit                 ;If not, then exit
            call    enable_video            ;Unblank the screen
kb_exit:    iret                            ;Return from interrupt
kb_int      endp

And here is the code to hook the interrupt - this runs at the beginning of the program

            mov     ax,3509h                ;Hook interrupt 09H
            int     21h
            mov     word ptr int09h,bx
            mov     word ptr int09h[2],es
            mov     ax,2509h
            mov     dx,offset kb_int
            int     21h

The entire program is too long to post here - 33KB. But then, you only want to see an example of what to do....

Here's another example which checks for various alt/ctrl/key functions

even
New_09     proc   far
           sti
           pushf
           push   ax
           mov    ah, 2                 ; get shift key status
           int    16h
           and    al, 0Fh
           cmp    al, 12                ; alt/ctrl?
           jne    @@0                   ; no
           in     al, 60h
           cmp    al, 19                ; 'R'?
           je     @@1                   ; yes
           cmp    al, 31                ; 'S'
           je     @@1                   ; yes
           cmp    al, 16                ; 'Q'
           je     @@1                   ; yes
@@0:       pop    ax                    ; exit if not my hotkey
           popf
           jmp    cs:old_09

@@1:       push   bp
           mov    bp, ax                ; save scan code
           in     al, 61h               ; reset keyboard
           mov    ah, al
           or     al, 80h
           out    61h, al
           mov    al, ah
           out    61h, al
           cli
           mov    al, 20h
           out    20h, al
           sti

           mov    ax, bp                ; restore scan code
           cmp    al, 16                ; was it Q?
           jne    @@GetMode

I don't remember now why all the ins and outs were needed (this code is from 14/05/1992 - twenty years ago!!!!).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top