Q35968: CALL SetUEvent in Assembly Routine to Disable PRINT SCREEN
Article: Q35968 Product(s): See article Version(s): 4.00b 4.50 Operating System(s): MS-DOS Keyword(s): ENDUSER | B_BasicCom | mspl13_basic Last Modified: 12-JAN-1990 This article provides an example of calling BASIC's SetUEvent routine from an assembly-language interrupt routine to disable the screen dump performed by the PRINT SCREEN key (found on enhanced IBM keyboards) or the SHIFT+PRSCR or SHIFT+PRTSC key (found on earlier, nonenhanced IBM PC keyboards). Special steps must be taken when triggering BASIC's user-defined events from assembly-language interrupt routines. Primarily, the assembly routine needs to make sure that the DS register points to BASIC's default data segment before making the call to SetUEvent. Also, the interrupt routine should be disabled before, and re-enabled after, a CHAIN or RUN statement. This information applies to Microsoft QuickBASIC Versions 4.00b and 4.50, to Microsoft BASIC Compiler Versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC PDS Version 7.00 for MS-DOS and MS OS/2. Note: The SetUEvent routine is not provided in QuickBASIC Version 4.00 or earlier. SetUEvent was introduced in QuickBASIC Version 4.00b and the BASIC compiler Version 6.00 and later. BASIC user-defined interrupts are triggered by a call to SetUEvent. This routine can be called from an external assembly routine, usually an interrupt handler. However, in QuickBASIC 4.00b, in the BASIC compiler 6.00 and 6.00b, and in BASIC PDS 7.00, SetUEvent assumes that DS is pointing to BASIC's default data segment; if it isn't, the call to SetUEvent will not trigger the BASIC interrupt routine. To ensure that DS is pointing to the correct place, save the value of DS in a location accessible to the interrupt routine when installing it. Then, in the interrupt routine, place that value in DS directly before making the call to SetUEvent. In QuickBASIC Version 4.50, you don't have to set DS equal to the BASIC Data Segment. When CHAINing or RUNning other BASIC programs that use the same interrupt routine, the first BASIC program must deinstall the interrupt handler, CHAIN (or RUN) the second program, and reinstall the handler again. The sample program below demonstrates how to install, deinstall, and properly CALL SetUEvent in an interrupt handler situation. The following is a BASIC code example: DECLARE SUB PrScr () DECLARE SUB DeInst () ON UEVENT GOSUB handler UEVENT ON CALL PrScr PRINT "Screen Dump interrupt has been disabled." PRINT "Press PRINT SCREEN (or SHIFT+PRTSC) key to trigger event." PRINT "Press any other key to end program." WHILE i$ = "" i$ = INKEY$ WEND CALL DeInst PRINT "Screen Dump interrupt has been re-enabled." END handler: PRINT "Screen dumps are currently disabled." RETURN The following is an assembly-language program that redefines the interrupt that occurs when you press the PRINT SCREEN (or SHIFT+PRTSC) key: ; PRSCR.ASM cr equ 0dh lf equ 0ah .model medium .code extrn SetUEvent:proc public prscr tsr_active db 0 old_seg dw ? old_off dw ? bds dw ? handler proc far sti push ax push bx push cx push dx push si push di push bp push ds push es ;save regs cmp cs:tsr_active, byte ptr 0 ;are we already up? je do_int ;no, go display message jmp ex_int ;yes, get out! do_int: mov cs:tsr_active, byte ptr 1 ;okay, we're up now... mov ax,bds mov ds,ax ;set DS = BASIC's data segment call SetUEvent ;trigger the user event mov cs:tsr_active, 0 ;re-activate interrupt ex_int: pop es pop ds pop bp pop di pop si pop dx pop cx pop bx pop ax cli ; CLI corresponds to STI at Handler beginning. iret handler endp prscr proc far push bp mov bp, sp push ds push es mov cs:bds,ds ;put BASIC's DS here mov ax, 3505h ;get interrupt vector int 21h ;for PrScr mov cs:old_seg,es mov cs:old_off,bx ;save it mov dx, seg handler mov ds,dx mov dx, offset handler ;reset interrupt 5 mov ax, 2505h ;to point to handler int 21h pop es pop ds pop bp ret ;back to BASIC prscr endp public deinst deinst proc far ;to de-install our Prscr interrupt push bp mov bp,sp push ds mov dx,cs:old_seg mov ds, dx mov dx,cs:old_off ;get old INT 5 vector mov ax, 2505h int 21h ;and restore it pop ds pop bp ret deinst endp END
THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.
Copyright Microsoft Corporation 1986-2002.