home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / asmutil / tbones07.zip / TSRKEY.ASM < prev    next >
Assembly Source File  |  1991-01-20  |  16KB  |  369 lines

  1. ;***************************
  2. PAGE    55,132          ;Format .LST listing at 55 lines by 132 columns.
  3. TITLE   TSRKEY Version 0.4 Jan 20 1991 Robert Curtis Davis
  4. SUBTTL  Introduction
  5. ;******************************************************************************
  6. ;
  7. ;       TSRKEY.ASM      Version 0.4     Jan 20 91
  8. ;       A part of the TBONES software package.
  9. ;
  10. ;       Copyright (C) 1990, 1991 by Robert Curtis Davis,
  11. ;    All Rights Reserved.
  12. ;
  13. ;    DESCRIPTION:
  14. ;    ASM Program template for Terminate-and-Stay-Resident (TSR) programs
  15. ;        that are activated by a specified HotKey..
  16. ;
  17. ;    PURPOSE:
  18. ;       Provides a skeletal framework program useful as a starting point
  19. ;       in the design of your own HotKey TSRs.
  20. ;
  21. ;                   E-mail address:
  22. ;              Internet: sonny@trantor.harris-atd.com
  23. ;
  24. ;                          US Mail:
  25. ;                                   430 Bahama Drive
  26. ;                                   Indialantic, FL 32903
  27. ;
  28. ;***************************************************************************
  29. ;
  30. ; Special thanks to David Kirschbaum, whose Toad Hall Tweaks significantly
  31. ; improved TBONES' code:
  32. ;
  33. ;v0.11    Toad Hall Tweak, 25 Nov 90
  34. ; - Idiosyncracy: I like my constant labels all-upper-case
  35. ;   and my variable labels lower-case.
  36. ; - Load AX with words, not byte-by-byte
  37. ; - Load ES directly with environ seg, no need to pass thru AX.
  38. ; - Save ES directly to variable, no need to pass thru AX.
  39. ; - Let compiler do basic arithmetic (figuring paras of memory to save).
  40. ; - Use processes just to be neat.  (That FAR NewInt09 is important!)
  41. ; - INS is a reserved word for TASM v1.0. Changed to INSRT.
  42. ;**************************************************************************
  43. SUBTTL  Code Segment (Resident)
  44. PAGE
  45. ;**************************************************************************
  46. ;
  47. CodeSeg        segment
  48.                 assume  cs:CodeSeg,ds:CodeSeg
  49. BeginDump       EQU     $       ;This, from Roy Silvernail, makes
  50.                                 ;TASM v.1.0 happy below.
  51. ;
  52.         org    2CH        ;0.11
  53. envseg        label    word        ;0.11
  54. ;
  55.         org    100h        ;ORG for all COM programs.
  56. ;
  57. Entry           PROC    NEAR            ;v0.11
  58.         jmp    TSRinit        ;Jump over resident portion and
  59.                     ;initialize things and make code
  60.                     ;between Entry: and TSRinit: resident.
  61. ;  
  62. ; Old Keyboard Interrupt Vector (Int 09h handler address) is stored 
  63. ; here during TSR initialization:
  64. oldint09        dd      ?
  65. ;
  66. Entry           ENDP                    ;v0.11
  67.  
  68. ; For this HotKey TSR Template, specify Keyboard Interrupt 09h as the Hook:
  69. HOOK09            equ     09h   ;Hooked Interrupt number.
  70. ;
  71. bellgate    db    0    ;Gate closed (=1) when in Bell routine.
  72.                 ;Gate open (=0) when not in Bell routine.
  73. ;
  74. ; EQUs defining Key Flag weights in the Key Flag Byte:
  75. RSHIFT        equ    00000001B        ;Right Shift Key Flag weight.
  76. LSHIFT        equ    00000010B        ;Left Shift  Key Flag weight.
  77. CTRL        equ    00000100B        ;Ctrl        Key Flag weight.
  78. ALT        equ    00001000B        ;Alt         Key Flag weight.
  79. ;SCROLL          equ     00010000B               ;Scroll Lock Key Flag weight.
  80. ;NUM             equ     00100000B               ;Num Lock    Key Flag weight.
  81. ;CAPS            equ     01000000B               ;Caps Lock   Key Flag weight.
  82. INSRT        equ    10000000B        ;Ins         Key Flag weight.
  83. ;*************************************************************************
  84. ;       Mask to mask out Num, Caps, and Scroll Lock bits from key flag byte.
  85. LockKeyMask     EQU     10001111B
  86. ;
  87. ;       Your HotKey is specified here:
  88. ;       (This sample HotKey is set for Ctrl-Alt-K)
  89. ;
  90. ; Specify TSR's HotKey Shift Keys:
  91. KEYFLAGBYTE    equ    CTRL+ALT        ;HotKey Flags
  92. ;
  93. ; Specify TSR's HotKey Scan Code:
  94. HOTKEY          equ     25h                     ;'K' key.
  95. ;
  96. ;*************************************************************************
  97. SUBTTL User-supplied TSR Routine
  98. PAGE
  99. ;*************************************************************************
  100. ROUTINE         PROC    NEAR
  101. ;*************************************************************************
  102. ;    Code for your HotKey-triggered TSR routine  GOES HERE:
  103. ;    ( Here, a dummy routine has been placed which simply rings the
  104. ;      terminal Bell whenever the TSR is triggered. )
  105. ;
  106. ;    Announce this dummy TSR's trigger by a Bell signal:
  107. ;
  108. Enter:
  109.                 mov     al,07h          ;al = ASCII Bell.
  110.                 mov     bh,0            ;Video page.
  111.                 mov     cx,1            ;No. of bytes to write.
  112.                 mov     ah,0Eh          ;BIOS Int10,OEh=TTY Screen.
  113.                 Int     10h             ;Write ASCII Bell to screen.
  114. ;
  115. Exit:
  116.                 ret                     ;Return from TSR routine.
  117. ;
  118. ROUTINE         endp
  119. ;
  120. ;    End of your HotKeyed TSR routine.
  121. ;***************************************************************************
  122. SUBTTL Hooked Interrupts
  123. PAGE
  124. ;***************************************************************************
  125. ;
  126. NewInt09    PROC    FAR        ;v0.01
  127. ;
  128. ; The following three instructions often are said to "simulate an interrupt"
  129. ; that calls the PRIOR interrupt handler routine and then the prior interrupt
  130. ; handler's IRET instruction pops the flags and returns here to the point
  131. ; after the following CALL instruction.
  132. ;    The reason for "simulating the interrupt" here is to give prior (and
  133. ; presumably more time-critical) handlers a shot at processing this interrupt
  134. ; before we process with this TSR's code.
  135. ;
  136.         pushf            ;Push flags as a true interrupt would.
  137.                 cli                     ;Be sure interrupts are disabled.
  138.         call    CS:oldint09    ;Call FAR PTR address of old interrupt
  139. ;                    ;     handler routine.
  140. ;
  141. ;
  142.                 push    ax      ;Prepare to check for Hotkey.
  143.                 push    bx      ;Save all registers (DS is already pushed).
  144.                 push    cx
  145.                 push    dx
  146.                 push    si
  147.                 push    di
  148.                 push    bp
  149.                 push    ds
  150.                 push    es
  151. ;
  152.                 push    CS              ;Set up data segment
  153.                 pop     DS              ;register to point to code segment.
  154. ;
  155.                 ASSUME  DS:CodeSeg      ;v0.01
  156. ;
  157. ;       Determine if the current Keyboard Interrupt (Int09h) occurred
  158. ;       because this TSR's HotKey was pressed:
  159.                 in      al,60h          ;Get current Key Scan Code.
  160.                 cmp     al,HOTKEY       ;Is it HotKey's Scan Code?
  161.                 jne     Exit09          ;Exit if not.
  162.                 mov     ah,02h          ;Int16h,Fcn02h:GetKEYFLAGBYTE.
  163.                 Int     16h             ;Return Key Flag Byte in al.
  164.                 and     al,LockKeyMask  ;Mask out Num, Caps, Scroll Lock bits.
  165.                 cmp     al,KEYFLAGBYTE  ;Are the HotKey Flags active ?
  166.                 jne     Exit09          ;Exit if not.
  167. ;
  168. ;       At this point, Hotkey is known to have been pressed. First, purge
  169. ;       the DOS Keyboard type-ahead buffer of the hot key(s) so they won't
  170. ;       be passed on to DOS:
  171. ;
  172. ClrKbdBuf:      ;Clear Keyboard buffer:
  173.                 mov     ah,01h          ;Get Keyboard buffer status
  174.                 int     16h             ;via BIOS Interrupt 16h.
  175.                 jz      BufClr          ;Jump if buffer empty.
  176.                 mov     ah,00h          ;Get key from buffer (to purge it)
  177.                 int     16h             ;via BIOS Interrupt 16h.
  178.                 jmp     ClrKbdBuf       ;Loop back to purge another key.
  179. BufClr:
  180. ;
  181. ; We shall allow other interrupts to occur during our TSR ROUTINE.
  182. ; If we didn't allow other interrupts (through the STI instruction),
  183. ; we could lock out time-critical interrupts from access to the CPU during
  184. ; our TSR routine. However, by allowing interrupts during our routine, we 
  185. ; have an increased responsibility to make sure critical portions of our
  186. ; own code is not re-entered. (The "bellgate" stuff below is an example
  187. ; of a measure necessary to keep us from re-entering our own TSR's code).
  188. ; What we really want to do by allowing interrupts is to make the CPU avail-
  189. ; able to OTHER critical interrupt service routines WITHOUT swarming all over 
  190. ; ourselves through multiple detections of our own HotKey.
  191. ;               This "gate" technique is a good one to keep in
  192. ;               mind whenever you have a code region in an interrupt handler
  193. ;               that needs to be protected from re-entry:
  194. ;
  195.                 cmp     bellgate,0      ;Is it clear to re-enter Hotkey code?
  196.                 jne     Exit09          ;Exit if not,
  197.                 mov     bellgate,1      ;Else, close gate and proceed.
  198. ;
  199.                 STI                     ;Allow other interrupts in our TSR.
  200. ;
  201.                 call    ROUTINE         ;All is clear!, so call routine.
  202. ;
  203.                 mov     CS:bellgate,0   ;Open gate allowing new HotKey detect.
  204. ;
  205. Exit09:
  206.                 pop     es              ;Restore all registers
  207.                 pop     ds
  208.                 ASSUME  DS:NOTHING      ;v0.01
  209.                 pop     bp
  210.         pop    di
  211.         pop    si
  212.         pop    dx
  213.         pop    cx
  214.         pop    bx
  215.         pop    ax
  216. ;
  217. ;
  218. ;    Return from this TSR's Keyboard Interrupt 09h handler routine:
  219.         iret
  220. ;
  221. NewInt09    ENDP            ;v0.01
  222. ;
  223. ;*************************************************************************
  224. ;
  225. ;    -END OF TSR's RESIDENT CODE-
  226. ;    Only the code above will remain locked in memory
  227. ;        after the initialization performed below.
  228. ;*************************************************************************
  229. SUBTTL  TSR Initialization Code (Nonresident). The "BOOSTER".
  230. PAGE
  231. ;*************************************************************************
  232. ;       BEGINNING OF TSR's INITIALIZATION CODE:
  233. ;    The following code is protected in RAM *ONLY* during initialization
  234. ;        of the TSR that occurs when the TSR name is first entered
  235. ;        at the DOS command level. All the following code is abandonned
  236. ;        unprotected in RAM after the Terminate-and-Stay-Resident
  237. ;        call to Function 31h of DOS Interrupt 21h below. This
  238. ;        is allowed to happen because the code's work is complete at
  239. ;        that point. The code will be overwritten as the memory which
  240. ;        it temporarily occupied is needed by DOS for other purposes.
  241. ;         I have seen this following section of code colorfully called
  242. ;        the TSR "Booster". And this is quite appropriate since the code
  243. ;        sits here, strapped to the very end of the code. It is of use
  244. ;        only during the initialization of the TSR, when it is used to
  245. ;        put the TSR into "orbit" (residency), and after which it is
  246. ;        "jettisoned" by the DOS TSR call, Int 21h, Fcn 31h.
  247. ;                                                                              
  248. TSRinit         PROC    NEAR                            ;v0.11
  249. EndDump         EQU     $       ;From Roy Silvernail. Keeps TASM v.1.0 happy.
  250. ;
  251. ; TSRKEY requires DOS Version 2 or later. Be sure DOS Version 1 not used:
  252. ;
  253. ;       Get DOS Version Number:
  254.                 mov     ah,30h                  ;Fcn 30h = Get DOS Version
  255.                 int     21h                     ;DOS Version = al.ah
  256. ;
  257. ;       If this is DOS v.1.x, this TSR cannot work, so go print message
  258. ;       and exit without installing:
  259.                 cmp     al,1         ;Is this DOS Version 1.x?
  260.                 ja      DOSverOK     ;If not, DOS version is OK.
  261. ;
  262. DOSver1:
  263. ;If here, DOS Version 1.x is being run and TSR won't work, so bail out:
  264. ;
  265.         mov    dx,OFFSET BailOutMsg    ;TBONES needs DOS 2.x or later.
  266.         mov    ah,09h            ;Say we're sorry, but NO GO
  267.         int    21h            ;via DOS.
  268.                 pop     bx                      ;Clear stack.
  269.         int    20h            ;Terminate without installing
  270.                         ;in only way DOS 1.x knows.
  271. ;
  272. BailOutMsg:
  273.                 db      0Dh,0Ah
  274.                 db      'Sorry. TSRBONES needs DOS v.2+. You have v.1.x'
  275.                 db      0Dh,0Ah,'$'
  276. ;
  277. DOSverOK:
  278. ;       If here, DOS version is 2.0 or later. TSR can work, so proceed.
  279. ;
  280. ;       To conserve RAM usage, release from memory the copy of the DOS 
  281. ;    Environment passed to this TSR (this assumes, of course, that
  282. ;    your Interrupt handler routine will not need to reference this
  283. ;    de-allocated Environment):
  284. ;
  285.         mov    ES,envseg        ;ES=PSP's environment seg v0.11
  286.         mov    ah,49h            ;DOS Fcn 49h = Release Memory
  287.         int    21h            ;Release it via DOS interrupt.
  288. ;
  289. ; In order to make the TSR's command name show under the "owner" column in 
  290. ;    the "MAPMEM" command of Kim Kokkonen's excellent TSR Mark/Release 
  291. ;       package, allocate a tiny 1-paragraph "Pseudo-Environment" here which
  292. ;       contains nothing but the TSR name. This costs only 16 bytes in
  293. ;       TSR resident code.
  294. ;
  295. ; Allocate the memory needed by the tiny 'Pseudo-Environment":
  296.         mov    bx,1            ;Allocate one parag. (16bytes)
  297.         mov    ah,48h            ;and return allocation
  298.         int    21h            ;segment in ax via DOS call.
  299. ;
  300.                 mov     ES,ax                   ;Pseudo-Env. Segment to ES.
  301.         mov    si,OFFSET PseudoEnv    ;si=source string OFFSET.
  302.         mov    di,0            ;di=destination string OFFSET.
  303.         mov    cx,ENVLNGTH        ;cx=Bytes in Pseudo-Env.string.
  304.         cld                ;Forward string move direction.
  305.         rep    movsb    ;Move Pseudo-Env. string @ DS:si to ES:di
  306. ;
  307. ; Set PSP's Environment segment pointer to point to tiny Pseudo-Environment.
  308.         mov    envseg,ES    
  309. ;
  310. ;*****************************************************************************
  311. ; Hook Interrupt 09h vector:
  312. ;
  313. ;       Get Old Interrupt Vector:
  314.                 mov     ax,3500H+HOOK09         ;Get Hooked interrupt vec v0.11
  315.         int    21h            ;Int.Vector in ES:BX via DOS.
  316. ;
  317. ;    Save Old Interrupt Vector:
  318.                 mov     Word Ptr oldint09,bx      ;Save Offset of Old Interrupt.
  319.                 mov     word ptr oldint09+2,ES    ;save segment           v0.11
  320. ;
  321. ;       Install New Interrupt Vector to this TSR's "NewInt09:" Label:
  322.                 mov     ax,2500H+HOOK09         ;Set Hooked int vector v0.11
  323.                 mov     dx,offset NewInt09      ;dx=Offset of New Int Handler.
  324.         int    21h            ;Set New Int via DOS.
  325. ;
  326. ; Announce the TSR's Installation:
  327.         mov    dx,Offset InstallMsg    ;DX points to message.
  328.         mov    ah,09h            ;DOS Fcn. 09h=Display String.
  329.         int    21h            ;Display String via DOS.
  330. ;
  331. ; Lock resident code in memory via Terminate-and-Stay-Resident (TSR) DOS call:
  332. ;
  333. ;v0.11    DX requires size of resident code (in 16-byte paragraphs)
  334. ;    This awkward construct is required to keep
  335. ;    DOS Function 31h happy.  Notice how we first compute
  336. ;    the length of the TSR code in bytes [i.e., end of
  337. ;    the TSR code (TSRinit) minus start of the TSR code
  338. ;    (0, our CodeSeg)], round it up to the next whole paragraph ( + 0Fh),
  339. ;    and then divide by 16 (SHR 4) to get the number of resident paragraphs:
  340. ;
  341. ;       Roy Silvernail discovered that the EndDump and BeginDump constants
  342. ;       kept his TASM 1.0 assembler happy on the following statement:
  343.                 mov     dx,(EndDump-BeginDump+0FH)/16   ;v0.11
  344. ;
  345.         mov    ah,31h            ;DOS FCN 31h=TSR Call.
  346.         int    21h            ;Go Resident via DOS TSR call.
  347. ;
  348. PseudoEnv:      DB      ' ',0,0,1,0,'TSRKEY',0
  349. ENVLNGTH    EQU    $-PseudoEnv
  350. ;
  351. InstallMsg:
  352.         db    0Dh,0Ah
  353.         db    'YOUR HOT KEY TSR IS NOW INSTALLED.'
  354.         db    0Dh,0Ah
  355.                 db      'HotKey => Ctrl-Alt-K'
  356.         db    0Dh,0Ah
  357.         db    0Dh,0Ah
  358.                 db      'TSRKEY Version 0.4'
  359.         db    0Dh,0Ah
  360.                 db      'Copyright (C) 1990, 1991 by Robert Curtis Davis'
  361.         db    0Dh,0Ah,'$'
  362. ;
  363. TSRinit    ENDP                    ;v0.11
  364.  
  365. CodeSeg        ends
  366.         end    Entry
  367. ;
  368. ;******************************************************************************
  369.