Int 16H is the software interrupt to get a key from the BIOS keyboard
buffer.
Int 9 is the actual keyboard hardware interrupt service routine.
Here's some old assembly code which shows how to re-vector Int9 (to look
for a hot key) and stuff keystrokes into the BIOS buffer (to fake an
application program). The same basic principles can be used in your
Pascal program to achieve what you are trying to do:
; STUFFS THE FOLLOWING KEYSTROKES INTO THE
; BIOS KBD BUFFER when Alt-X is pressed:
; ^]CQ<CR>
;
; This sequence is used to exit Kermit.
jmp start
credit: db ' Written by NetNews ',26
active db 0 ; switch turns macroing on or off
ID equ 07743h ;change ID for each application
LOADED equ 03334h ; function number to test if already loaded
DISABLE EQU 03335h ; function number to disable macro.
ENABLE EQU 03336H ; function number to enable macroing.
SCANCODE EQU 45 ; SCAN CODE FOR 'X' HOT KEY
parm macro
mov bx,80h
cs mov bl,[bx]
cmp bl,2
jne >M1
mov bx,81h
cs mov bl,[bx]
cmp bl,' '
jne >M1
mov bx,82h
cs mov bl,[bx]
cmp bl,#1
M1:
#EM
ClearKeyboard:
;entry: nothing.
;all registers are preserved.
;
;example usage:
;
;call ClearKeyboard
;pop ax (assuming it was pushed before call)
;iret
;
push ax
IN AL,61h ;get value of kbd control port (61h)
MOV AH,AL ;save a copy
OR AL,80h ;set enable kbd bit
OUT 61h,AL ;write it out
XCHG AL,AH ;get original value
OUT 61h,AL ;put it back
CLI
MOV AL,20h ;send end-of-interrupt code (20h)
OUT 20h,AL ;to 8259 interrupt controller chip port (20h)
pop ax
ret
GetVector macro
mov al,#1
call GetIntVec
mov #2,bx
mov #3,es
#EM
SetVector macro
mov al,#1
mov dx, #2
call SetIntVec
#EM
old028h: ; allow DOS interrupt
old028hofs dw ?
old028hseg dw ?
old09h: ; KEYBOARD
old09hofs dw ?
old09hseg dw ?
old016h: ; BIOS KBD BUFFER
old016hofs dw ?
old016hseg dw ?
;;;;;;;;;;;;;;;;;;;;;;;;;; 028H
;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;; allow DOS Interrupt
;;;;;;;;;;;;;;;;;;;;;;;;;;;
my028h:
sti
cli
cs jmp far old028h
HotKey:
push ax,bx,cx,dx,di,si,es,ds
cmp al,SCANCODE
jne >L9
mov ax,040h
mov ds,ax
mov al,[0017h]
test al,08h
jz >L9
mov bx,001eh
cli
mov [001ah],bx
mov [001ch],bx
mov b [bx],29
inc bx
mov b [bx],']'
dec bx
add bx,2
mov b [bx],'c'
add bx,2
mov b [bx],'q'
add bx,2
mov b [bx],13
add bx,2
mov [001c],bx
sti
L9:
pop ds,es,si,di,dx,cx,bx,ax
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 09H ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;; KEYBOARD INTERRUPT ;;;;;;;;;;;;;;;;;;;;;;;;
my09h:
sti
push ax
in al,60h
cs cmp active,1
if e call HotKey
pop ax
cli
cs jmp far old09h
;;;;;;;;;;;;;;;;;;;;;;;;;;; 16H ;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;; BIOS KEYBOARD BUFFER ;;;;;;;;;;;;;;;;;
my016h:
sti
cmp bx,ID
jne >L9 ; don't service the interrupt if the ID is wrong.
; determine which function is requested:
cmp ax,LOADED
je >L7
cmp ax,DISABLE
je >L8
cmp ax,ENABLE
je >L6
L9:
; unrecognized function - don't do anything
cli
cs jmp far old016h
L6:
; enable macroing
cs mov active,1
iret
L7:
; yes - already loaded - tell caller:
mov ax,bx
iret
L8:
; disable macroing
cs mov active,0
iret
START:
mov bx,ID
mov ax,loaded
int 16h
cmp ax,ID
if ne jmp LOAD
; already loaded. disable or enable?
parm '0'
je >L1
; parm is not 0, already loaded, so enable:
mov bx,id
mov ax,enable
int 16h
mov dx,mss3
mov ah,9
int 21h
int 20h
L1:
; already installed, parm is 0, so disable macroing:
mov bx,id
mov ax,disable
int 16h
mov dx,mss0
mov ah,9
int 21h
int 20h
LOAD:
; this is first invokation. not yet loaded. so load it:
; load without enabling?
mov active,1
parm '0'
if e mov active,0
GetVector 028h, Old028hOfs, Old028hSeg ; allow DOS
GetVector 009h, Old09hOfs, Old09hSeg ; KEYBOARD
GetVector 016h, Old016hOfs, Old016hSeg ; BIOS KBD BUFFER
SetVector 028h, My028h
SetVector 009h, My09h
SetVector 016h, My016h
cmp active,1
je >L1
mov dx,mss4
mov ah,9
int 21h
mov dx, start
int 27h
L1:
mov dx,mss1
mov ah,9
int 21h
mov dx, start
int 27h
GetIntVec:
;entry: al contains the int to get
;exit: es:bx contains the int address
;
mov ah,35h
int 21h
ret
SetIntVec:
;entry: al contains interrupt to set
; ds:dx contains the address of the ISR
;all other regs preserved
;
mov ah,25h
int 21h
ret
mss0: db 'already installed, disabled$'
mss1: db 'ALTX 1.0.0T (c) 1988 NetNews, enabled$'
mss3: db 'already installed, enabled$'
mss4: db 'ALTX 1.0.0T (c) 1988 NetNews, disabled$'
Good Luck.
In article <7i1kcl$m8...@news1.tc.umn.edu>,
"Jimb Esser" <jims...@R3M0VEMEDOTgeocities.com> wrote:
Quote
> Hello!
> I am trying to write a program that will launch an external
> program, and while it's running, intercept any calls to the keyboard
> interrupt ($16, if I'm not mistaken), filter any requests for
> keypresses, and insert characters from a buffer (previously read
> from a file) into the appropriate spot so that it simulates the
> pressing of keys in the external program.
> I have tried fiddling with some of the example source code in
> the help files, in order to just get a program running so that it
> will hook on, and just call the original interrupt (as it would do
> for any function calls my interrupt vector doesn't handle when it's
> done), but it just ends up freezing whenever int $16 is called in
> the external program.
> At the end of this post is the source code for what I've tried,
> and just a test program to launch from within the other code (just
> one readln).
> So, what I'd like to know is whether or not this is anywhere
> near the correct way to write an interrupt to do this.
> Is there any other way that this could be done that would be
> simpler? Maybe attaching to the timer interrupt, and putting
> characters directly into the keyboard buffer if it's not full (if
> you can do that from within an interrupt)? Or if there's a way to
> attach this process to a hot key or something (I tried a hotkey-tsr
> unit, calling the functions to insert text into the keyboard buffer,
> but because of the size of the text and size of the keyboard buffer,
> I could not send all of it at once).
> Thanks in advance for your help! Comments of any kind would be
> greatly appreciated!
> jimb
> // macro.pas:
> {$M $2000,0,0 } { 8K stack, no heap }
> {$C FIXED PRELOAD PERMANENT}
> uses Dos, Crt;
> var
> ProgramName, CmdLine: string;
> KbdIntVec : Procedure;
> {$F+}
> procedure Keyclick; interrupt;
> var
> wrd:word;
> begin
> inline ($9C); { PUSHF -- Push flags }
> { Call old ISR using saved vector }
> KbdIntVec;
> end;
> {$F-}
> begin
> { Insert ISR into keyboard chain }
> WriteLn('Hooking vectors...');
> GetIntVec($16,@KbdIntVec);
> SetIntVec($16,Addr(Keyclick));
> Write('Program to Exec (full path): ');
> ReadLn(ProgramName);
> WriteLn('About to Exec...');
> Exec(ProgramName, '');
> WriteLn('...back from Exec');
> if DosError <> 0 then{ Error? }
> WriteLn('Dos error #', DosError)
> else
> WriteLn('Exec successful. ',
> 'Child process exit code = ',
> DosExitCode);
> WriteLn('Unhooking vectors...');
> SetIntVec($16,@KbdIntVec);
> end.
> // test.pas
> var s:string;
> begin
> Write('Enter something : ');
> ReadLn(s);
> WriteLn(s);
> end.
> --
> jimsoft at geocities d com
> http://www.horningabout.com/jimb
--== Sent via Deja.com http://www.deja.com/ ==--
---Share what you know. Learn what you don't.---