home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS - Coast to Coast
/
simteldosarchivecoasttocoast.iso
/
pcmag
/
vol5n22.zip
/
FREEZE.ASM
next >
Wrap
Assembly Source File
|
1987-12-13
|
18KB
|
332 lines
;FREEZE.COM for the IBM Personal Computer - 1986 by Jeff Prosise
;
kb_data equ 60h ;keyboard data port
kb_ctrl equ 61h ;keyboard control port
numlock_key equ 69 ;scan code of NumLock key
del_key equ 83 ;scan code of Del key
alt_key equ 8 ;shift code for Alt key
ctrl_key equ 4 ;shift code for Ctrl Key
eoi equ 20h ;end-of-interrupt signal
int_ctrl_port equ 20h ;8259 interrupt controller port
;
bios_data segment at 40h ;BIOS data area
org 63h
addr_6845 dw ? ;address of 6845 index register
bios_data ends
;
code segment para public 'code'
assume cs:code
org 100h
begin: jmp initialize ;goto initialization routine
;
adapter db 0 ;0 = EGA, 1 = CGA or MDA
freeze_status db 0 ;interrupt routine status flag
char_count dw ? ;length of password
msr_address dw ? ;address of Mode Select Register
msr_values db 2Ch,28h,2Dh,29h ;Mode Select Register values to
db 2Ah,2Eh,1Eh,29h ;re-enable CGA/MDA video display
ibm_signature db 'IBM' ;EGA BIOS signature
errmsg db 13,10,'Freeze Already Loaded',13,10,'$'
copy_right db 13,10,'Copyright 1986 Ziff-Davis Publishing Co.',13,10,'$'
;
old_int_9h label dword ;holding area for INT 9h vector
int_9h_ptr dw 2 dup (?)
old_int_16h label dword ;holding area for INT 16h vector
int_16h_ptr dw 2 dup (?)
;
;------------------------------------------------------------------------------
;All calls to INT 16h will henceforth be routed thru here. If AH = 255 on
;entry, BH is set to 255 to signal the caller that this routine was indeed
;invoked.
;------------------------------------------------------------------------------
new_int_16h proc near
cmp ah,255 ;AH = 255?
jne newint1 ;no, then jump
mov bh,ah ;yes, set BH to 255 and exit
iret
newint1: jmp old_int_16h ;goto normal 16h handler
new_int_16h endp
;
;------------------------------------------------------------------------------
;Execution comes here every time an interrupt 9 is generated from the keyboard.
;------------------------------------------------------------------------------
freeze proc near
sti ;restore interrupts
push ax ;save registers
push bx
push cx
push dx
push si
push di
push ds
push es
in al,kb_data ;read keypress (or break)
and al,7Fh ;strip the break bit
cmp freeze_status,0 ;freeze routine currently active?
je freeze1 ;no, then check for Alt-NumLock
;
;The freeze routine is already in progress. Check for a press of Ctrl-Alt-Del
;and block it out if it just occurred.
;
cmp al,del_key ;was the Del key pressed?
jne exit ;no, then goto old INT 9 routine
mov ah,2 ;INT 16h - get shift status
int 16h ;get status of shift keys
and al,alt_key+ctrl_key ;Ctrl-Alt pressed?
cmp al,alt_key+ctrl_key
jne exit ;no, then goto old INT 9 routine
call kb_reset ;Ctrl-Alt-Del pressed - reset kb
jmp unfrz1 ;exit
;
;The freeze routine is not already active. See if Alt-NumLock was pressed.
;
freeze1: cmp al,numlock_key ;is it the NumLock key?
jne exit ;no, then goto old INT 9 routine
mov ah,2 ;INT 16h - get shift status
int 16h ;get current status of shift keys
test al,alt_key ;is the Alt key pressed?
jne freeze2 ;yes, goto freeze routine
;
;Exit routine restores registers before exiting thru the normal keyboard
;interrupt handler.
;
exit: pop es ;pop registers off stack
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax
jmp old_int_9h ;exit to normal interrupt handler
;
;Trigger keys are pressed. Reset the keyboard, send an EOI signal to the 8259,
;and execute our freeze routine.
;
freeze2: call kb_reset ;reset keyboard and issue EOI
mov freeze_status,1 ;set status byte
push cs ;set DS and ES to the code segment
pop ds
push cs
pop es
assume ds:code
;
;Begin freeze routine by disabling video and getting a password from the user.
;
call video_disable ;disable video display
xor di,di ;point DI to start of PSP
call get_password ;get the password
or cx,cx ;any characters input?
je unfreeze ;no, then exit interrupt routine
cmp al,27 ;was input terminated with ESC key?
je unfreeze ;yes, then exit
mov char_count,cx ;save length of password
;
;The password is now entered and the keyboard 'frozen,' awaiting input of a
;matching password. Accept input from the keyboard but continue to loop until
;the password is correctly re-entered.
;
freeze3: mov di,128 ;point DI to middle of PSP
call get_password ;get password
cmp cx,char_count ;same number of characters entered?
jne freeze3 ;no, then passwords don't match
cmp al,27 ;was input ended with ESC key?
je freeze3 ;yes, then start input loop over
xor si,si ;point SI to first password
mov di,128 ;point DI to second password
cld ;clear DF for string operations
repe cmpsw ;compare the two passwords
jne freeze3 ;not equal, then continue looping
;
;Exit freeze routine by clearing the status flag, enabling the video display,
;and executing an IRET instruction.
;
unfreeze: mov freeze_status,0 ;reset status byte
call video_enable ;re-enable video display
unfrz1: pop es ;restore register values
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax
iret ;exit freeze routine
freeze endp
;
;------------------------------------------------------------------------------
;VIDEO_ENABLE and VIDEO_DISABLE enable and disable the EGA, CGA, or MDA video
;signal depending upon the value of ADAPTER.
;------------------------------------------------------------------------------
video_disable proc near ;disable the video display
cmp adapter,0 ;is video adapter an EGA?
je ega_disable ;yes, then jump
mov dx,msr_address ;no, then load MSR address
mov al,25h ;disable value for CGA/MDA
out dx,al ;disable video display
ret
ega_disable: xor al,al ;zero AL (clear bit 5)
call set_ega ;disable EGA
ret
video_disable endp
;
video_enable proc near ;enable the video display
cmp adapter,0 ;is video adapter an EGA?
je ega_enable ;yes, then jump
mov dx,msr_address ;set MSR or CP1 port address in DX
mov ah,15 ;INT 10h function - get video mode
int 10h ;get current video mode
lea bx,msr_values ;point BX to MSR_VALUES table
xlat msr_values ;get enable value for current mode
out dx,al ;enable video display
ret
ega_enable: mov al,20h ;set bit 5 of AL
call set_ega ;enable EGA video
ret
video_enable endp
;
;------------------------------------------------------------------------------
;SET_EGA is called by VIDEO_ENABLE and VIDEO_DISABLE routines to selectively
;set or clear bit 5 of the EGA Attribute Address Register.
;Entry: AL - value to OUT to Attribute Address Register
;------------------------------------------------------------------------------
set_ega proc near
push ax ;save AL
mov dx,3BAh ;reset monochrome flip-flop...
in al,dx ;for write to Address Register
mov dx,3DAh ;reset color flip-flop
in al,dx
mov dx,3C0h ;set DX to Attr Addr Register
pop ax ;retrieve entry value of AL
out dx,al ;write value to register
ret
set_ega endp
;
;------------------------------------------------------------------------------
;KB_RESET subroutine resets the keyboard and issues an EOI to the 8259 PIC.
;------------------------------------------------------------------------------
kb_reset proc near
in al,kb_ctrl ;get current control port value
mov ah,al ;save it
or al,80h ;set the keyboard clear bit (bit 7)
out kb_ctrl,al ;send reset value to port
mov al,ah ;get the original value
out kb_ctrl,al ;enable the keyboard
cli ;disable interrupts
mov al,eoi ;get EOI value
out int_ctrl_port,al ;send EOI signal to the 8259
sti ;restore interrupts
ret ;done
kb_reset endp
;
;------------------------------------------------------------------------------
;GET_PASSWORD subroutine reads up to 64 characters entered from the keyboard
;and stores them in the designated buffer. Backspace key is active as an
;editing key.
;Entry: ES:DI - buffer address | Exit: CX - character count
;------------------------------------------------------------------------------
get_password proc near
cld ;clear DF for string operations
xor cx,cx ;zero CX - initialize char count
getpas1: mov ah,0 ;INT 16h function - get keypress
int 16h ;get character from keyboard
cmp al,13 ;ENTER key?
je done ;yes, then exit
cmp al,27 ;ESC key?
je done ;yes, then exit
cmp al,8 ;BACKSPACE key?
je backspace ;yes, then goto backspace routine
cmp cx,64 ;is the buffer full?
je buffer_full ;yes, then don't accept entry
inc cx ;char entered - increment count
stosw ;deposit character in buffer
jmp getpas1 ;return for more input
backspace: or cx,cx ;any characters to delete?
je getpas1 ;no, then goto input loop
sub di,2 ;decrement buffer pointer
dec cx ;decrement char count
jmp getpas1 ;return to input loop
buffer_full: mov ah,14 ;INT 10h function - Write TTY
mov al,7 ;ASCII code for beep
int 10h ;sound the beep
jmp getpas1 ;and return for more input
done: ret ;return to calling routine
get_password endp
;
;------------------------------------------------------------------------------
;INITIALIZE routine checks to see if FREEZE has already been loaded. If it
;has, execution aborts with an error message. If it hasn't, then the value of
;ADAPTER is set according to the type of display adapter present in the system
;and the vectors in low memory pointing to the INT 9h and 16h routines are set
;to point to our own newly installed code.
;------------------------------------------------------------------------------
initialize proc near
;
;See if FREEZE has been previously loaded by calling INT 16h with AH set to
;255 and BH set to 0. If BH comes back unchanged, then FREEZE is NOT
;currently resident in memory; if BH = 255, then FREEZE has been loaded.
;
mov ah,255 ;set AH and BH
xor bh,bh
int 16h ;call interrupt routine
or bh,bh ;is BH = 0?
je init1 ;yes, then continue
lea dx,errmsg ;no, print error message and exit
mov ah,9
int 21h
ret
;
;Check for the presence of an Enhanced Graphics Adapter by looking for an 'IBM'
;signature in the EGA BIOS area.
;
init1: mov ax,0C000h ;set ES to EGA BIOS segment
mov es,ax
mov di,1Eh ;starting address of signature
lea si,ibm_signature ;point SI to 'IBM' text
mov cx,3 ;three characters to check
cld ;clear DF
repe cmpsb ;compare the three bytes
je init2 ;signature found - EGA present
;
;The display adapter is not an EGA, so it must be either a CGA or an MDA. Get
;the address of the 6845 Index Register from the BIOS data area, calculate the
;port address of the Mode Select Register, and save it for later.
;
mov adapter,1 ;set ADAPTER for CGA or MDA
mov ax,bios_data ;set ES to BIOS data area
mov es,ax
assume es:bios_data
mov ax,addr_6845 ;get 6845 address
add ax,4 ;add 4 to get MSR address
mov msr_address,ax ;save address
;
;Save the current interrupt 16h vector and replace it with our own.
;
init2: mov ah,35h ;DOS function - get vector
mov al,16h ;interrupt 16h
int 21h ;get the vector
mov int_16h_ptr,bx ;save offset portion of vector
mov int_16h_ptr[2],es ;save segment portion of vector
mov ah,25h ;DOS function - set vector
mov al,16h ;interrupt 16h
lea dx,new_int_16h ;pointer to new routine
int 21h ;set vector
;
;Now save the old interrupt 9 vector, replace it with the new one, and exit.
;
mov ah,35h ;DOS function - get vector
mov al,9h ;interrupt 9
int 21h ;get vector
mov int_9h_ptr,bx ;save offset
mov int_9h_ptr[2],es ;save segment
mov ah,25h ;DOS function - set vector
mov al,9h ;interrupt 9
lea dx,freeze ;point to our freeze routine
int 21h ;set vector
lea dx,initialize ;prepare DX for exit
int 27h ;terminate-but-stay-resident
initialize endp
;
code ends
end begin