From: sayanna@studaff.und.ac.za (Mr Alvin Sayanna) Newsgroups: comp.os.msdos.programmer Subject: INFO: How to detect Key Press/Releases Date: Tue, 9 Aug 1994 07:47:09 GMT Hi all, Seems that many people want advice on Keyboard Interrupts. I also did a short time ago and with the help I got then I figured out how to do a few nifty things with interrupts. I have written up a short document (below) that will hopefully help others start on the very interesting road to interrupt programming. Just one note. I AM A BEGINNER ! The information that is found below is what I have gained from tinkering around and asking questions. If there are any points that are incorrect I will be grateful you would correct me. (oh yes...the program included works too !) Ok...Here it is... --------------------------------------------------------------------------- HOW THE HECK TO MESS UP MY KEYBOARD ;^) by Me... (Alvin Sayanna) --------------------------------------------------------------------------- What happens when a key is pressed ? ------------------------------------ Interrupt 9 (IRQ1) is generated when data is received from the keyboard. This data is normally a scan code that is produced from a key press or release. If the BIOS supports an enhanced keyboard it calls INT 15h (service 4Fh) before further processing of the key. Interrupt 15h service 4Fh makes allowance for keyboard translation. When called AL will contain the scan code with the Carry Flag set to 1. On return INT 15h returns the scan code in AL with the Carry Flag set. If the Carry flag is clear on return from INT 15h then INT 9 ignores the keystroke. So what does this all mean ? ---------------------------- To intercept a key press or to detect a key release we can insert our very own procedure into INT 15h to catch the scan code. Once we have intercepted this scan code we can do anything with it eg: We can cause INT 9 to ignore it, we can change the code to some other code, we can detect if this was a key release, etc. So how do we actually do that ? ------------------------------- Ok...decide what we want to do with the key...for example we want to detect when a key is released. We then write out our little procedure in PASCAL (*grin* that's about the easiest for me). But wait...how do we know when a key was released anyway ? Well when a key is released bit 7 of the scan code in AL is set. So all we have to do is check bit 7 of every scan code we intercept and here is a small program to demonstrate just that... ----------our program--------- {$M $400,0,0} <---set up a 1k stack Uses Crt, Dos; <---we all know what this is :) Var KbdIntVec : Procedure; {$F+} <---note the Far Call Procedure Catch_Int_15(Flags, CS, IP, AX, BX, CX, DX, SI, DI, DS, ES, BP : Word); Interrupt; Begin If Hi(AX) = $4f then <---pass all other INT15 services to the orig handler. We are only interested in service 4Fh. If (Lo(AX) and 128) = 128 then <---check if bit 7 is set Begin Sound(1000); <---It is, so let's make a beep Delay(1); NoSound; End; Inline($9C); <---push flags because we're done KbdIntVec; <---hand back to the original End; INT 15h handler {$F-} Begin GetIntVec($15,@KbdIntVec); SetIntVec($15,Addr(Catch_Int_15)); Keep(0); { Terminate, stay resident } End. --------end of our program--------- ...and there we go. We have just set up a program that would cause a key release be followed by a loud *BEEP* :) Ok...let's go through the program... GetIntVec gets the address of the original INT 15h handler and stores it in our variable KbdIntVec. We then set the handler address for INT 15h to point to our procedure namely Catch_Int_15 and we end the program with Keep which exits but leaves the program resident in memory. And now we have INT 15h calling our nifty little procedure ! When our procedure gets called we check AH for the service number. Since we are only interested in service 4Fh we pass all others to the original handler for INT 15h which you will remember we stored in KbdIntVec. If we detect service 4Fh we then proceed to check if the scan code (which is in AL) has bit 7 set. If it has then we know that this was a key release ! Wow...simple isn't it ? *grin*. Well to proclaim our achievement to the world we add a little sound :) and cause the key release to make a BEEP. Now we are done and like good little aspiring programmers we pass control back to the original handler for INT 15h. And folks...that's it ! Where do we go from here ? -------------------------- Well two EXCELLENT sources of information on interrupts are 1) Ralf Brown's Interrupt List INTER36A.ZIP to INTER36D.ZIP 2) HelpPc 2.10 - Quick Reference Utility by David Jurgens HELPPC21.ZIP both of which are obtainable from any of the large ftp sites. Well that's it... See ya, Alvin PS: please attempt to withhold flames 8-) and rather send constructive comments and help.