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