dean@ucbruby.berkeley.edu (04/07/86)
[chomp chomp chomp...]
The assembly program below was written as an attempt to do a small, quick,
and dirty keyboard remapping routine for a friend. It attempts to intercept
the DOS keyboard read/look/status interrupt (16h) and translate the character
and scan codes returned. I attempted to intercept and translate both READ
and LOOK (non-destructive reads) function requests. The routine essentially
never worked until I removed the check for LOOK requests (see the ";*****"
commented lines in the listing). At present, the routine works, but only
without the LOOK request check.
The symptoms it displayed until then were, I think, a bit bizarre and I would
like any help in interpreting them. By using DEBUG and inserting debugging
statements, I determined the following:
1) When it failed, it failed at installation, either freezing the
keyboard or causing the screen to fill with garbage. The ROM keyboard
routine was still working (I think), since the keyboard buffer would
beep when full and ^C's echoed as "^C" on the screen.
2) It failed at the moment the new interrupt routine was being inserted
in the DOS interrupt vector table.
* 3) Attempts to isolate the failure succeeded when all code except the
JMP to the old keyboard routine were removed (it still failed if any
code containing the PUSHF; CALL sequence was present). Note that
removal of the PUSHF; CALL sequence allowed proper *installation* of
the interrupt, as well as proper execution of the routine (though
of course, it now did nothing).
* 4) In desperation I eventually tried removing the innocuous looking
lines that checked for the "LOOK" function. Then everything worked.
In summary, the presence of the PUSHF; CALL sequence *and* the test-for-LOOK
code in the replacement interrupt handler seem to cause the *installation*
of the handler to go bye-bye!
Someone please explain. By mail if I am doing something patently stupid that
everyone notices, or maybe post it to the net if it is subtle and of general
interest.
Equipment and software used:
Zenith Z-150 running MS-DOS 2.? (same on a Z-158 running DOS 2.?)
MASM 1.27
MS-Link 2.40
Exe2bin 1.5
_Many_ thanks to any who take the trouble to look this over!
Dean Pentcheff, Dep't of Zoology, U of California, Berkeley, CA 94720
dean@ucbruby
=========== MASM LISTING BEGINS HERE =============
page ,132
; remap.asm
; Quick and dirty keyboard remapping
; Dean Pentcheff 4/86
; Interrupt shell based on: Wadlow, T. (1985) Writing desk accessories.
; _Byte_ (Fall) 10(11):105-22.
dos_keyboard_io equ 16h ; keyboard i/o vector number
dos_function equ 21h ; dos function interrupt number
dos_terminate_resident equ 27h ; terminate-but-stay-resident interrupt
dos_read_keyboard equ 00h ; dos destructive keyboard read function
dos_look_keyboard equ 01h ; dos non-destr. keyboard read function
get_vector equ 35h ; dos get-interrupt-address function
set_vector equ 25h ; dos set-interrupt-address function
cseg segment
assume cs:cseg,ds:cseg ; tell the assembler about segment registers
org 100h ; all .COM programs begin at 100h
start:
jmp initialize ; run installation code first
; All Data Definitions
; --------------------
old_keyboard_io dd ? ; storage for old kbd int. handler
include remap.def ; include character and scan code map tables
; (two 256 byte tables: char_map_tab and
; scan_map_tab which map characters and
; scan codes)
; New Keyboard Interrupt Routine
; ------------------------------
keyboard_interceptor proc far
assume cs:cseg,ds:cseg ; set default segments for assembler
sti ; turn interrupts back on
;****** cmp ah,dos_look_keyboard ; check for LOOK function...
;****** je do_translate ; if so, prepare to translate
cmp ah,dos_read_keyboard ; check for READ function...
jne no_translate ; if not, just jump to old interrupt
do_translate:
pushf ; simulate normal Keyboard Interrupt
assume ds:nothing
call old_keyboard_io
cmp al,00h ; do we have a "special" keypress?
je return ; if yes, don't screw around with it
pushf ; save clobberable stuff
push bx
mov bx,offset char_map_tab ; set up for character translate
xlat char_map_tab ; translate character
xchg ah,al ; swap character and scan code
mov bx,offset scan_map_tab ; set up for scan code translate
xlat scan_map_tab ; translate scan code
xchg ah,al ; unswap character and scan code
pop bx ; restore clobbered stuff
popf
return:
iret ; return to caller
no_translate:
assume ds:nothing
jmp old_keyboard_io ; do normal interrupt, let it return to caller
keyboard_interceptor endp
; Installation Code (discarded after installation)
; ------------------------------------------------
initialize:
mov bx,cs ; make sure dseg=cseg
mov ds,bx
mov al,dos_keyboard_io ; get old kbd interrupt address via
mov ah,get_vector ; dos function call
int dos_function
mov old_keyboard_io,bx ; store old kbd interrupt address
mov old_keyboard_io[2],es
mov bx,cs ; DS<-current segment for dos fn call
mov ds,bx
mov dx,offset keyboard_interceptor ; DX<-new kbd interrupt offset
mov al,dos_keyboard_io ; set new kbd interrupt address via
mov ah,set_vector ; dos function call
int dos_function
mov bx,cs ; set up to discard unneeded code
mov ds,bx ; set data segment appropriately
mov dx,offset initialize ; set offset above which to discard
int dos_terminate_resident ; terminate but leave handler resident
cseg ends
end start
====== MASM LISTING ENDS HERE ==================================perkins@bnrmtv.UUCP (Henry Perkins) (04/09/86)
> The assembly program below was written as an attempt to do a small, quick, > and dirty keyboard remapping routine for a friend. It attempts to intercept > the DOS keyboard read/look/status interrupt (16h) and translate the character > and scan codes returned. [lots of assembly code, and request for enlightenment, deleted] A basic problem with your interrupt service routine is that is mucks about with the flags before passing them on to the original routine. You do STI and CMP instructions, then PUSHF -- this passes flags substantially different from what was intended. You should instead do something like: PUSH BP MOV BP,SP PUSH [BP+6] ; Get the original flags off the stack -- {hplabs,amdahl,3comvax}!bnrmtv!perkins --Henry Perkins