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 exa
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!!!!).
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.