home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast.iso / pcmag / vol5n22.zip / FREEZE.ASM next >
Assembly Source File  |  1987-12-13  |  18KB  |  332 lines

  1. ;FREEZE.COM for the IBM Personal Computer - 1986 by Jeff Prosise
  2. ;
  3. kb_data            equ 60h                  ;keyboard data port
  4. kb_ctrl            equ 61h                  ;keyboard control port
  5. numlock_key        equ 69                   ;scan code of NumLock key
  6. del_key            equ 83                   ;scan code of Del key
  7. alt_key            equ 8                    ;shift code for Alt key
  8. ctrl_key           equ 4                    ;shift code for Ctrl Key
  9. eoi                equ 20h                  ;end-of-interrupt signal
  10. int_ctrl_port      equ 20h                  ;8259 interrupt controller port
  11. ;
  12. bios_data     segment at 40h                ;BIOS data area
  13.               org 63h
  14. addr_6845     dw ?                          ;address of 6845 index register
  15. bios_data     ends
  16. ;
  17. code          segment para public 'code'
  18.               assume cs:code
  19.               org 100h
  20. begin:        jmp initialize                ;goto initialization routine
  21. ;
  22. adapter            db 0                     ;0 = EGA, 1 = CGA or MDA
  23. freeze_status      db 0                     ;interrupt routine status flag
  24. char_count         dw ?                     ;length of password
  25. msr_address        dw ?                     ;address of Mode Select Register
  26. msr_values         db 2Ch,28h,2Dh,29h       ;Mode Select Register values to
  27.                    db 2Ah,2Eh,1Eh,29h       ;re-enable CGA/MDA video display
  28. ibm_signature      db 'IBM'                 ;EGA BIOS signature
  29. errmsg             db 13,10,'Freeze Already Loaded',13,10,'$'
  30. copy_right         db 13,10,'Copyright 1986 Ziff-Davis Publishing Co.',13,10,'$'
  31. ;
  32. old_int_9h         label dword              ;holding area for INT 9h vector
  33. int_9h_ptr         dw 2 dup (?)
  34. old_int_16h        label dword              ;holding area for INT 16h vector
  35. int_16h_ptr        dw 2 dup (?)
  36. ;
  37. ;------------------------------------------------------------------------------
  38. ;All calls to INT 16h will henceforth be routed thru here.  If AH = 255 on
  39. ;entry, BH is set to 255 to signal the caller that this routine was indeed
  40. ;invoked.
  41. ;------------------------------------------------------------------------------
  42. new_int_16h   proc near
  43.               cmp ah,255                    ;AH = 255?
  44.               jne newint1                   ;no, then jump
  45.               mov bh,ah                     ;yes, set BH to 255 and exit
  46.               iret
  47. newint1:      jmp old_int_16h               ;goto normal 16h handler
  48. new_int_16h   endp
  49. ;
  50. ;------------------------------------------------------------------------------
  51. ;Execution comes here every time an interrupt 9 is generated from the keyboard.
  52. ;------------------------------------------------------------------------------
  53. freeze        proc near
  54.               sti                           ;restore interrupts
  55.               push ax                       ;save registers
  56.               push bx
  57.               push cx
  58.               push dx
  59.               push si
  60.               push di
  61.               push ds
  62.               push es
  63.               in al,kb_data                 ;read keypress (or break)
  64.               and al,7Fh                    ;strip the break bit
  65.               cmp freeze_status,0           ;freeze routine currently active?
  66.               je freeze1                    ;no, then check for Alt-NumLock
  67. ;
  68. ;The freeze routine is already in progress.  Check for a press of Ctrl-Alt-Del
  69. ;and block it out if it just occurred.
  70. ;
  71.               cmp al,del_key                ;was the Del key pressed?
  72.               jne exit                      ;no, then goto old INT 9 routine
  73.               mov ah,2                      ;INT 16h - get shift status
  74.               int 16h                       ;get status of shift keys
  75.               and al,alt_key+ctrl_key       ;Ctrl-Alt pressed?
  76.               cmp al,alt_key+ctrl_key
  77.               jne exit                      ;no, then goto old INT 9 routine
  78.               call kb_reset                 ;Ctrl-Alt-Del pressed - reset kb
  79.               jmp unfrz1                    ;exit
  80. ;
  81. ;The freeze routine is not already active.  See if Alt-NumLock was pressed.
  82. ;
  83. freeze1:      cmp al,numlock_key            ;is it the NumLock key?
  84.               jne exit                      ;no, then goto old INT 9 routine
  85.               mov ah,2                      ;INT 16h - get shift status
  86.               int 16h                       ;get current status of shift keys
  87.               test al,alt_key               ;is the Alt key pressed?
  88.               jne freeze2                   ;yes, goto freeze routine
  89. ;
  90. ;Exit routine restores registers before exiting thru the normal keyboard
  91. ;interrupt handler.
  92. ;
  93. exit:         pop es                        ;pop registers off stack
  94.               pop ds
  95.               pop di
  96.               pop si
  97.               pop dx
  98.               pop cx
  99.               pop bx
  100.               pop ax
  101.               jmp old_int_9h                ;exit to normal interrupt handler
  102. ;
  103. ;Trigger keys are pressed.  Reset the keyboard, send an EOI signal to the 8259,
  104. ;and execute our freeze routine.
  105. ;
  106. freeze2:      call kb_reset                 ;reset keyboard and issue EOI
  107.               mov freeze_status,1           ;set status byte
  108.               push cs                       ;set DS and ES to the code segment
  109.               pop ds
  110.               push cs
  111.               pop es
  112.               assume ds:code
  113. ;
  114. ;Begin freeze routine by disabling video and getting a password from the user.
  115. ;
  116.               call video_disable            ;disable video display
  117.               xor di,di                     ;point DI to start of PSP
  118.               call get_password             ;get the password
  119.               or cx,cx                      ;any characters input?
  120.               je unfreeze                   ;no, then exit interrupt routine
  121.               cmp al,27                     ;was input terminated with ESC key?
  122.               je unfreeze                   ;yes, then exit
  123.               mov char_count,cx             ;save length of password
  124. ;
  125. ;The password is now entered and the keyboard 'frozen,' awaiting input of a
  126. ;matching password.  Accept input from the keyboard but continue to loop until
  127. ;the password is correctly re-entered.
  128. ;
  129. freeze3:      mov di,128                    ;point DI to middle of PSP
  130.               call get_password             ;get password
  131.               cmp cx,char_count             ;same number of characters entered?
  132.               jne freeze3                   ;no, then passwords don't match
  133.               cmp al,27                     ;was input ended with ESC key?
  134.               je freeze3                    ;yes, then start input loop over
  135.               xor si,si                     ;point SI to first password
  136.               mov di,128                    ;point DI to second password
  137.               cld                           ;clear DF for string operations
  138.               repe cmpsw                    ;compare the two passwords
  139.               jne freeze3                   ;not equal, then continue looping
  140. ;
  141. ;Exit freeze routine by clearing the status flag, enabling the video display,
  142. ;and executing an IRET instruction.
  143. ;
  144. unfreeze:     mov freeze_status,0           ;reset status byte
  145.               call video_enable             ;re-enable video display
  146. unfrz1:       pop es                        ;restore register values
  147.               pop ds
  148.               pop di
  149.               pop si
  150.               pop dx
  151.               pop cx
  152.               pop bx
  153.               pop ax
  154.               iret                          ;exit freeze routine
  155. freeze        endp
  156. ;
  157. ;------------------------------------------------------------------------------
  158. ;VIDEO_ENABLE and VIDEO_DISABLE enable and disable the EGA, CGA, or MDA video
  159. ;signal depending upon the value of ADAPTER.
  160. ;------------------------------------------------------------------------------
  161. video_disable proc near                     ;disable the video display
  162.               cmp adapter,0                 ;is video adapter an EGA?
  163.               je ega_disable                ;yes, then jump
  164.               mov dx,msr_address            ;no, then load MSR address
  165.               mov al,25h                    ;disable value for CGA/MDA
  166.               out dx,al                     ;disable video display
  167.               ret
  168. ega_disable:  xor al,al                     ;zero AL (clear bit 5)
  169.               call set_ega                  ;disable EGA
  170.               ret
  171. video_disable endp
  172. ;
  173. video_enable  proc near                     ;enable the video display
  174.               cmp adapter,0                 ;is video adapter an EGA?
  175.               je ega_enable                 ;yes, then jump
  176.               mov dx,msr_address            ;set MSR or CP1 port address in DX
  177.               mov ah,15                     ;INT 10h function - get video mode
  178.               int 10h                       ;get current video mode
  179.               lea bx,msr_values             ;point BX to MSR_VALUES table
  180.               xlat msr_values               ;get enable value for current mode
  181.               out dx,al                     ;enable video display
  182.               ret
  183. ega_enable:   mov al,20h                    ;set bit 5 of AL
  184.               call set_ega                  ;enable EGA video
  185.               ret
  186. video_enable  endp
  187. ;
  188. ;------------------------------------------------------------------------------
  189. ;SET_EGA is called by VIDEO_ENABLE and VIDEO_DISABLE routines to selectively
  190. ;set or clear bit 5 of the EGA Attribute Address Register.
  191. ;Entry:  AL - value to OUT to Attribute Address Register
  192. ;------------------------------------------------------------------------------
  193. set_ega       proc near
  194.               push ax                       ;save AL
  195.               mov dx,3BAh                   ;reset monochrome flip-flop...
  196.               in al,dx                      ;for write to Address Register
  197.               mov dx,3DAh                   ;reset color flip-flop
  198.               in al,dx
  199.               mov dx,3C0h                   ;set DX to Attr Addr Register
  200.               pop ax                        ;retrieve entry value of AL
  201.               out dx,al                     ;write value to register
  202.               ret
  203. set_ega       endp
  204. ;
  205. ;------------------------------------------------------------------------------
  206. ;KB_RESET subroutine resets the keyboard and issues an EOI to the 8259 PIC.
  207. ;------------------------------------------------------------------------------
  208. kb_reset      proc near
  209.               in al,kb_ctrl                 ;get current control port value
  210.               mov ah,al                     ;save it
  211.               or al,80h                     ;set the keyboard clear bit (bit 7)
  212.               out kb_ctrl,al                ;send reset value to port
  213.               mov al,ah                     ;get the original value
  214.               out kb_ctrl,al                ;enable the keyboard
  215.               cli                           ;disable interrupts
  216.               mov al,eoi                    ;get EOI value
  217.               out int_ctrl_port,al          ;send EOI signal to the 8259
  218.               sti                           ;restore interrupts
  219.               ret                           ;done
  220. kb_reset      endp
  221. ;
  222. ;------------------------------------------------------------------------------
  223. ;GET_PASSWORD subroutine reads up to 64 characters entered from the keyboard
  224. ;and stores them in the designated buffer.  Backspace key is active as an
  225. ;editing key.
  226. ;Entry:  ES:DI - buffer address        | Exit:  CX - character count
  227. ;------------------------------------------------------------------------------
  228. get_password  proc near
  229.               cld                           ;clear DF for string operations
  230.               xor cx,cx                     ;zero CX - initialize char count
  231. getpas1:      mov ah,0                      ;INT 16h function - get keypress
  232.               int 16h                       ;get character from keyboard
  233.               cmp al,13                     ;ENTER key?
  234.               je done                       ;yes, then exit
  235.               cmp al,27                     ;ESC key?
  236.               je done                       ;yes, then exit
  237.               cmp al,8                      ;BACKSPACE key?
  238.               je backspace                  ;yes, then goto backspace routine
  239.               cmp cx,64                     ;is the buffer full?
  240.               je buffer_full                ;yes, then don't accept entry
  241.               inc cx                        ;char entered - increment count
  242.               stosw                         ;deposit character in buffer
  243.               jmp getpas1                   ;return for more input
  244. backspace:    or cx,cx                      ;any characters to delete?
  245.               je getpas1                    ;no, then goto input loop
  246.               sub di,2                      ;decrement buffer pointer
  247.               dec cx                        ;decrement char count
  248.               jmp getpas1                   ;return to input loop
  249. buffer_full:  mov ah,14                     ;INT 10h function - Write TTY
  250.               mov al,7                      ;ASCII code for beep
  251.               int 10h                       ;sound the beep
  252.               jmp getpas1                   ;and return for more input
  253. done:         ret                           ;return to calling routine
  254. get_password  endp
  255. ;
  256. ;------------------------------------------------------------------------------
  257. ;INITIALIZE routine checks to see if FREEZE has already been loaded.  If it
  258. ;has, execution aborts with an error message.  If it hasn't, then the value of
  259. ;ADAPTER is set according to the type of display adapter present in the system
  260. ;and the vectors in low memory pointing to the INT 9h and 16h routines are set
  261. ;to point to our own newly installed code.
  262. ;------------------------------------------------------------------------------
  263. initialize    proc near
  264. ;
  265. ;See if FREEZE has been previously loaded by calling INT 16h with AH set to
  266. ;255 and BH set to 0.  If BH comes back unchanged, then FREEZE is NOT
  267. ;currently resident in memory; if BH = 255, then FREEZE has been loaded.
  268. ;
  269.               mov ah,255                    ;set AH and BH
  270.               xor bh,bh
  271.               int 16h                       ;call interrupt routine
  272.               or bh,bh                      ;is BH = 0?
  273.               je init1                      ;yes, then continue
  274.               lea dx,errmsg                 ;no, print error message and exit
  275.               mov ah,9
  276.               int 21h
  277.               ret
  278. ;
  279. ;Check for the presence of an Enhanced Graphics Adapter by looking for an 'IBM'
  280. ;signature in the EGA BIOS area.
  281. ;
  282. init1:        mov ax,0C000h                 ;set ES to EGA BIOS segment
  283.               mov es,ax
  284.               mov di,1Eh                    ;starting address of signature
  285.               lea si,ibm_signature          ;point SI to 'IBM' text
  286.               mov cx,3                      ;three characters to check
  287.               cld                           ;clear DF
  288.               repe cmpsb                    ;compare the three bytes
  289.               je init2                      ;signature found - EGA present
  290. ;
  291. ;The display adapter is not an EGA, so it must be either a CGA or an MDA.  Get
  292. ;the address of the 6845 Index Register from the BIOS data area, calculate the
  293. ;port address of the Mode Select Register, and save it for later.
  294. ;
  295.               mov adapter,1                 ;set ADAPTER for CGA or MDA
  296.               mov ax,bios_data              ;set ES to BIOS data area
  297.               mov es,ax
  298.               assume es:bios_data
  299.               mov ax,addr_6845              ;get 6845 address
  300.               add ax,4                      ;add 4 to get MSR address
  301.               mov msr_address,ax            ;save address
  302. ;
  303. ;Save the current interrupt 16h vector and replace it with our own.
  304. ;
  305. init2:        mov ah,35h                    ;DOS function - get vector
  306.               mov al,16h                    ;interrupt 16h
  307.               int 21h                       ;get the vector
  308.               mov int_16h_ptr,bx            ;save offset portion of vector
  309.               mov int_16h_ptr[2],es         ;save segment portion of vector
  310.               mov ah,25h                    ;DOS function - set vector
  311.               mov al,16h                    ;interrupt 16h
  312.               lea dx,new_int_16h            ;pointer to new routine
  313.               int 21h                       ;set vector
  314. ;
  315. ;Now save the old interrupt 9 vector, replace it with the new one, and exit.
  316. ;
  317.               mov ah,35h                    ;DOS function - get vector
  318.               mov al,9h                     ;interrupt 9
  319.               int 21h                       ;get vector
  320.               mov int_9h_ptr,bx             ;save offset
  321.               mov int_9h_ptr[2],es          ;save segment
  322.               mov ah,25h                    ;DOS function - set vector
  323.               mov al,9h                     ;interrupt 9
  324.               lea dx,freeze                 ;point to our freeze routine
  325.               int 21h                       ;set vector
  326.               lea dx,initialize             ;prepare DX for exit
  327.               int 27h                       ;terminate-but-stay-resident
  328. initialize    endp
  329. ;
  330. code          ends
  331.               end begin
  332.