home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
assemblr
/
library
/
buffy
/
buffy.asm
Wrap
Assembly Source File
|
1994-02-14
|
34KB
|
969 lines
TITLE BUFFY.ASM
PAGE 60,132
;
;
;
;
;
;
;
;
;
;
;
;
;----------------------------------------------------------------------------
PUBLIC initialize
max_value = 36
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
;
; This data is used by both interupt service routines (ISR's)
;
;----------------------------------------------------------------------------
BUFFY_DATA SEGMENT PARA PUBLIC 'DATA'
db "Unique StringXYZ"
psp_pointer dw (?)
isr_2f_seg dw (?)
int_2f_id db (?)
error_code db (?)
counter dw (?)
screen_buffer dw (?)
org_screen dw 80 * 25 dup (?)
display_lines label word
db " WW WW EEEEEEE LL CCCCCC OOOOO MMM MMM EEEEEEE "
db " WW WW EE LL CC OO OO MM M M MM EE "
db " WW W WW EEEE LL CC OO OO MM M MM EEEE "
db " WW W W WW EE LL CC OO OO MM MM EE "
db " WWW WWW EEEEEEE LLLLLLL CCCCCC OOOOO MM MM EEEEEEE "
db " "
db " TTTTTTTTT OOOOO "
db " TT OO OO "
db " TT OO OO "
db " TT OO OO "
db " TT OOOOO "
db " "
db " BBBBBB UU UU FFFFFFF FFFFFFF YY YY '' SSSSSS "
db " BB BB UU UU FF FF YY YY '' SS S "
db " BB BB UU UU FFFFF FFFFF YY SS "
db " BB BB UU UU FF FF YY S SS "
db " BBBBBB UUUUU FF FF YY SSSSSS "
db " "
db " WW WW OOOOO RRRRRR LL DDDDDD "
db " WW WW OO OO RR RR LL DD DD "
db " WW W WW OO OO RRRRRR LL DD DD "
db " WW W W WW OO OO RR RR LL DD DD "
db " WWW WWW OOOOO RR RR LLLLLLL DDDDDD "
db " "
db " Press any key to return to reality "
screen_length = $ - display_lines
BUFFY_DATA ENDS
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
MULTIPLEX_RTN SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:MULTIPLEX_RTN, DS:NOTHING, ES:NOTHING
int_2f_rtn PROC FAR
push bx
push ds
;----------------------------------------------------------------------------
; Check to see if the multiplex id is ours.
; If it is, set ES to point to our copy of BUFFY_DATA, AL=FF and return.
; If not, restore registers and call next interupt vector in line.
;----------------------------------------------------------------------------
mov bx,BUFFY_DATA
mov ds,bx
ASSUME DS:BUFFY_DATA, ES:NOTHING
cmp ah,int_2f_id
jne exit_multiplex_rtn
mov es,bx
pop ds
pop bx
mov al,0FFh
iret
exit_multiplex_rtn:
pop ds
pop bx
ASSUME DS:NOTHING, ES:NOTHING
jmp DWORD PTR cs:next_int_2f
next_int_2f dd (?)
int_2f_rtn ENDP
MULTIPLEX_RTN ENDS
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
KEYB_INTR_RTN SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:KEYB_INTR_RTN, DS:NOTHING, ES:NOTHING
keyb_isr PROC FAR
push ax
push ds
pushf
mov ax,BUFFY_DATA
mov ds,ax
ASSUME DS:BUFFY_DATA, ES:NOTHING
cmp counter,max_value
jng exit_keyb_rtn
call NEAR PTR restore_screen
exit_keyb_rtn:
mov counter,0
popf
pop ds
pop ax
ASSUME DS:NOTHING, ES:NOTHING
jmp DWORD PTR cs:org_keyb_vector
keyb_isr ENDP
;----------------------------------------------------------------------------
; Copy the screen into the screen buffer.
;----------------------------------------------------------------------------
restore_screen PROC NEAR
ASSUME DS:BUFFY_DATA
push cx
push si
push di
push es
;----------------------------------------------------------------------------
; Set the destination pointer (ES:DI) to B000:screen_buffer
;----------------------------------------------------------------------------
mov di,0B000h
mov es,di
mov di,screen_buffer
;----------------------------------------------------------------------------
; Set the source pointer (DS:SI) to BUFFY_DATA:org_screen
;----------------------------------------------------------------------------
mov si,OFFSET org_screen
;----------------------------------------------------------------------------
; Copy the original screen back onto the display.
;----------------------------------------------------------------------------
mov cx,80 * 25
cld
rep movsw
pop es
pop di
pop si
pop cx
ret
restore_screen ENDP
org_keyb_vector dd (?)
KEYB_INTR_RTN ENDS
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
CLK_INTR_RTN SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:CLK_INTR_RTN, DS:NOTHING, ES:NOTHING
clk_isr PROC FAR
push ax
push ds
pushf
mov ax,BUFFY_DATA
mov ds,ax
ASSUME DS:BUFFY_DATA, ES:NOTHING
;----------------------------------------------------------------------------
; Check the counter value.
; If the counter > max_value the screen has already been swapped.
; If the counter = max_value then try to swap the screen.
; If the counter < max_value then increment the counter.
;----------------------------------------------------------------------------
cmp counter,max_value
je attempt_swap
jl increment_and_exit ; Still counting up to screen swap.
jg no_action ; Screen has already been swapped.
increment_and_exit:
inc counter
no_action:
popf
pop ds
pop ax
ASSUME DS:NOTHING, ES:NOTHING
jmp DWORD PTR cs:org_clk_vector
;----------------------------------------------------------------------------
; At this point the counter = max_value.
; Check the video mode to make sure that it is one of 2,3 or 7.
; If it is then save the screen buffer start position and
; swap the screen and increment the counter variable.
;----------------------------------------------------------------------------
ASSUME DS:BUFFY_DATA, ES:NOTHING
attempt_swap:
call NEAR PTR get_current_video_mode ; Returns BIOS video mode in AL
mov screen_buffer,0000
cmp al,7
je swap_screen ; can swap in mode 7
mov screen_buffer,8000h
cmp al,3
je swap_screen ; can swap in mode 3
cmp al,2
je swap_screen ; can swap in mode 2
jmp SHORT no_action
swap_screen:
call NEAR PTR screen_save
call NEAR PTR screen_clear
call NEAR PTR buffy_screen
jmp SHORT increment_and_exit
clk_isr ENDP
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
;
; Return the BIOS video mode in the AL register.
;
;----------------------------------------------------------------------------
get_current_video_mode PROC NEAR
ASSUME DS:NOTHING, ES:NOTHING
push ds
mov ax,40h
mov ds,ax
mov al,ds:[49h] ; get display mode variable.
pop ds
ret
get_current_video_mode ENDP
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
; Copy the screen into the screen buffer.
;----------------------------------------------------------------------------
screen_save PROC NEAR
ASSUME DS:NOTHING, ES:NOTHING
push ax
push cx
push di
push si
push ds
push es
pushf
;----------------------------------------------------------------------------
; Set up DS to point to B000 and ES to point to BUFFY_DATA
;----------------------------------------------------------------------------
mov ax,0B000h
mov ds,ax
mov ax,BUFFY_DATA
mov es,ax
ASSUME DS:NOTHING, ES:BUFFY_DATA
;----------------------------------------------------------------------------
; Set up SI to point to start of screen buffer, DI to <org_screen>
;----------------------------------------------------------------------------
mov si,es:screen_buffer
mov di,OFFSET BUFFY_DATA:org_screen
;----------------------------------------------------------------------------
; Copy display screen (DS:SI) to screen save buffer (BUFFY_DATA:org_screen)
;----------------------------------------------------------------------------
mov cx,80 * 25
cld
rep movsw
popf
pop es
pop ds
pop si
pop di
pop cx
pop ax
ret
screen_save ENDP
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
;
; Clear the screen. Use attribute 7 (normal) and character 'space'.
;
;----------------------------------------------------------------------------
screen_clear PROC NEAR
ASSUME DS:NOTHING, ES:NOTHING
push ax
push cx
push di
push es
pushf
mov ax,BUFFY_DATA
mov es,ax
ASSUME DS:NOTHING, ES:BUFFY_DATA
mov di,es:screen_buffer
mov ax,0B000h
mov es,ax
ASSUME DS:NOTHING, ES:NOTHING
mov cx,80 * 25
mov ax,720h
cld
rep stosw
popf
pop es
pop di
pop cx
pop ax
ret
screen_clear ENDP
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
buffy_screen PROC NEAR
ASSUME DS:NOTHING, ES:NOTHING
push ax
push cx
push di
push si
push ds
push es
pushf
mov ax,BUFFY_DATA
mov ds,ax
ASSUME DS:BUFFY_DATA, ES:NOTHING
mov di,screen_buffer ; Offset of screen buffer.
mov si,OFFSET display_lines ; BX points to current display item
mov ax,0B000h ; Segment of screen buffer.
mov es,ax
mov ah,07 ; This is the characters attribute
mov cx,screen_length
next_character:
lodsb
stosw
loop next_character
exit_buffy_screen:
popf
pop es
pop ds
pop si
pop di
pop cx
pop ax
ret
buffy_screen ENDP
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
; Data area in same segment.
;----------------------------------------------------------------------------
org_clk_vector dd (?)
CLK_INTR_RTN ENDS
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
BUFFY_CODE SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:BUFFY_CODE, DS:NOTHING, ES:NOTHING
initialize PROC FAR
mov ax,BUFFY_DATA
mov ds,ax
ASSUME DS:BUFFY_DATA, ES:NOTHING
;----------------------------------------------------------------------------
; Save the PSP in the BUFFY_DATA segment for possible use later.
;----------------------------------------------------------------------------
mov psp_pointer,es ; Save the segment of the PSP.
mov counter,0 ; Set the counter to 0
mov error_code,0 ; Set the error code to 0
;----------------------------------------------------------------------------
; Get the original multiplex interupt vector and save it in a memory
; variable in the MULTIPLEX_RTN segment.
;----------------------------------------------------------------------------
mov ah,35h ; Get the interupt 2Fhex vector
mov al,2Fh ; returned in ES:BX
int 21h
mov ax,MULTIPLEX_RTN ; Store original vector
mov ds,ax
ASSUME DS:MULTIPLEX_RTN, ES:NOTHING
mov WORD PTR next_int_2f[2], es
mov WORD PTR next_int_2f[0], bx
;----------------------------------------------------------------------------
; Get the original keyboard interupt vector and save it in a memory
; variable in the KEYB_INTR_RTN segment.
;----------------------------------------------------------------------------
mov ah,35h ; Get the interupt 9 vector
mov al,09h ; returned in ES:BX
int 21h
mov ax,KEYB_INTR_RTN ; Store original vector
mov ds,ax
ASSUME DS:KEYB_INTR_RTN, ES:NOTHING
mov WORD PTR org_keyb_vector[2], es
mov WORD PTR org_keyb_vector[0], bx
;----------------------------------------------------------------------------
; Get the original clock (1Chex) interupt vector and save it in a memory
; variable in the CLK_INTR_RTN segment.
;----------------------------------------------------------------------------
mov ah,35h ; Get the interupt 1Chex vector
mov al,1Ch ; returned in ES:BX
int 21h
mov ax,CLK_INTR_RTN ; Store original vector
mov ds,ax
ASSUME DS:CLK_INTR_RTN, ES:NOTHING
mov WORD PTR org_clk_vector[2], es
mov WORD PTR org_clk_vector[0], bx
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
; call NEAR PTR debug_proc
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
; Check to see if a copy is already installed.
; If a copy is already installed, check for a command line option to
; uninstall it "/U", otherwise print error message and exit.
; If no copy is currently running then install this copy.
;----------------------------------------------------------------------------
mov ax,BUFFY_DATA
mov ds,ax
ASSUME DS:BUFFY_DATA, ES:NOTHING
call NEAR PTR check_for_existing_copy
jnc install_buffy
call NEAR PTR check_for_uninstall
jnc @F
push ds
push cs
pop ds
mov dx,OFFSET CS:msg_already_installed
mov ah,9
int 21h
pop ds
jmp SHORT exit_with_error
@@: call NEAR PTR uninstall
mov error_code,0
jmp SHORT exit_no_error
;----------------------------------------------------------------------------
; After uninstalling or issuing error message, exit without installing.
;----------------------------------------------------------------------------
exit_with_error:
mov error_code,1
exit_no_error:
mov ah,4Ch
mov al,error_code
int 21h
install_buffy:
call NEAR PTR set_int_2f_id
;----------------------------------------------------------------------------
; Set the keyboard interupt vector to the new routine
;----------------------------------------------------------------------------
mov ax,KEYB_INTR_RTN
mov ds,ax
ASSUME DS:KEYB_INTR_RTN, ES:NOTHING
mov dx,OFFSET KEYB_INTR_RTN:keyb_isr
mov ah,25h ; Set the interupt 9 vector
mov al,09h ; set to DS:DX
int 21h
;----------------------------------------------------------------------------
; Set the clock interupt vector to the new routine
;----------------------------------------------------------------------------
mov ax,CLK_INTR_RTN
mov ds,ax
ASSUME DS:CLK_INTR_RTN, ES:NOTHING
mov dx,OFFSET CLK_INTR_RTN:clk_isr
mov ah,25h ; Set the interupt 1Chex vector
mov al,1Ch ; set to DS:DX
int 21h
;----------------------------------------------------------------------------
; Set the multiplex interupt vector to the new routine
;----------------------------------------------------------------------------
mov ax,MULTIPLEX_RTN
mov ds,ax
ASSUME DS:MULTIPLEX_RTN, ES:NOTHING
mov dx,OFFSET MULTIPLEX_RTN:int_2f_rtn
mov ah,25h ; Set the interupt 2Fhex vector
mov al,2Fh ; set to DS:DX
int 21h
;----------------------------------------------------------------------------
; Release environment block.
;----------------------------------------------------------------------------
mov ax,BUFFY_DATA ; Make data segment addressable
mov ds,ax
ASSUME DS:BUFFY_DATA, ES:NOTHING
mov ax,psp_pointer ; Load pointer to PSP into DS
mov ds,ax
ASSUME DS:NOTHING, ES:NOTHING
mov es,ds:[2Ch] ; Get segment of Environment from PSP
mov ah,49h ; Release segment of Environment.
int 21h
;----------------------------------------------------------------------------
; Terminate and stay resident, leaving enough memory to hold the
; interupt service routines and the screen buffers.
;----------------------------------------------------------------------------
mov ax,BUFFY_DATA
mov ds,ax
ASSUME DS:BUFFY_DATA
mov dx,BUFFY_CODE
sub dx,ax
add dx,16
mov ah,31h
mov al,error_code
int 21h
initialize ENDP
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
debug_proc PROC NEAR
push ax
push ds
mov ax,BUFFY_DATA
mov ds,ax
call NEAR PTR uninstall
pop ds
pop ax
ret
debug_proc ENDP
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
check_for_existing_copy PROC NEAR
ASSUME DS:BUFFY_DATA, ES:NOTHING
push ax
push cx
push di
push si
push es
mov ah,80h
next_check:
xor al,al
int 2fh
cmp al,0FFh
je check_16_bytes
or al,al
je could_not_find
failed_check:
inc ah
jnz next_check
jmp SHORT could_not_find
check_16_bytes:
xor si,si
xor di,di
cld
mov cx,16
repe cmpsb
jne failed_check
mov isr_2f_seg,es
stc
jmp SHORT exit_check
could_not_find:
clc
exit_check:
pop es
pop si
pop di
pop cx
pop ax
ret
check_for_existing_copy ENDP
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
check_for_uninstall PROC NEAR
ASSUME DS:BUFFY_DATA, ES:NOTHING
push ds
mov ds,psp_pointer
ASSUME DS:NOTHING, ES:NOTHING
or BYTE PTR ds:[80h],0
je error_exit_check_for_uninstall
check_parameter_value:
cmp BYTE PTR ds:[82h], '/'
jne error_exit_check_for_uninstall
cmp BYTE PTR ds:[83h], 'U'
jne error_exit_check_for_uninstall
clc
jmp SHORT exit_check_for_uninstall
error_exit_check_for_uninstall:
stc
exit_check_for_uninstall:
pop ds
ret
check_for_uninstall ENDP
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
uninstall PROC NEAR
push ax
push bx
push dx
push si
push ds
push es
;----------------------------------------------------------------------------
; Switch active PSP to the copy of BUFFY that was found.
; 1) Unlink all interupt vectors from found copy of BUFFY.
; 2) get current PSP address from DOS
; 3) get PSP from found copy of BUFFY
; 4) call DOS 'Set psp' with found copy
; 5) release memory starting at found copy of PSP
; 6) reset to current PSP
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
; Set DS to point to the found copy of BUFFY_DATA
; We can let the assembler think that we are still pointing to the current
; copy of BUFFY_DATA because the assembler just uses this for segment
; overrides and offset calculations (both of which will be the same).
;----------------------------------------------------------------------------
mov ax,BUFFY_DATA
mov ds,ax
ASSUME DS:BUFFY_DATA, ES:NOTHING
mov ax,isr_2f_seg
mov es,ax
ASSUME DS:NOTHING, ES:BUFFY_DATA
;----------------------------------------------------------------------------
; ES now points to found copy of BUFFY_DATA.
; Calculate the position of the original int 2F vector and reset the
; vector via DOS.
;----------------------------------------------------------------------------
mov ax,MULTIPLEX_RTN
sub ax,BUFFY_DATA
mov bx,es
add ax,bx
mov ds,ax
ASSUME DS:MULTIPLEX_RTN, ES:BUFFY_DATA
;----------------------------------------------------------------------------
; DS now points to the found copy of MULTIPLEX_RTN.
; ES points to the found copy of BUFFY_DATA,
; Save a copy of the segment address of the original int_2f_isr
; Get the current vector from DOS
; Compare the current vector with the address of found copy,
; If they are the same they can be unlinked
; otherwise they cannot be unlinked (chain would be cut)
;----------------------------------------------------------------------------
mov si,es
mov ah,35h ; Get vector to current int 2F handler
mov al,2Fh
int 21h ; Returns ES:BX
mov ax,ds
mov bx,es
sub ax,bx ; Compare found segment with INT 2F segment
jz @F
jmp could_not_unlink
@@: mov es,si ; Restore segment of BUFFY_DATA
mov dx,WORD PTR next_int_2f[0]
mov ds,WORD PTR next_int_2f[2]
ASSUME DS:NOTHING, ES:BUFFY_DATA
mov ah,25h ; Reset int 2F vector to previous vector
mov al,2Fh
int 21h
;----------------------------------------------------------------------------
; ES now points to found copy of BUFFY_DATA.
; Calculate the position of the original int 9 vector and reset the
; vector via DOS.
;----------------------------------------------------------------------------
mov ax,KEYB_INTR_RTN
sub ax,BUFFY_DATA
mov bx,es
add ax,bx
mov ds,ax
ASSUME DS:KEYB_INTR_RTN, ES:BUFFY_DATA
;----------------------------------------------------------------------------
; DS now points to the found copy of KEYB_INTR_RTN
; ES points to the found copy of BUFFY_DATA,
; Save a copy of the segment address of the original keyb_isr
; Get the current vector from DOS
; Compare the current vector with the address of found copy,
; If they are the same they can be unlinked
; otherwise they cannot be unlinked (chain would be cut)
;----------------------------------------------------------------------------
mov si,es
mov ah,35h ; Get vector to current int 9 handler
mov al,9
int 21h ; Returns ES:BX
mov ax,ds
mov bx,es
sub ax,bx ; Compare found segment with int 9 segment
jz @F
jmp could_not_unlink
@@: mov es,si ; Restore segment of BUFFY_DATA
mov dx,WORD PTR org_keyb_vector[0]
mov ds,WORD PTR org_keyb_vector[2]
ASSUME DS:NOTHING, ES:BUFFY_DATA
mov ah,25h ; Reset int 9 vector to previous vector
mov al,9 ; Vector in DS:DX
int 21h
;----------------------------------------------------------------------------
; ES now points to found copy of BUFFY_DATA.
; Calculate the position of the original int 1C vector and reset the
; vector via DOS.
;----------------------------------------------------------------------------
mov ax,CLK_INTR_RTN
sub ax,BUFFY_DATA
mov bx,es
add ax,bx
mov ds,ax
ASSUME DS:CLK_INTR_RTN, ES:BUFFY_DATA
;----------------------------------------------------------------------------
; DS now points to the found copy of CLK_INTR_RTN
; ES points to the found copy of BUFFY_DATA,
; Save a copy of the segment address of the original clk_isr
; Get the current vector from DOS
; Compare the current vector with the address of found copy,
; If they are the same they can be unlinked
; otherwise they cannot be unlinked (chain would be cut)
;----------------------------------------------------------------------------
mov si,es
mov ah,35h ; Get vector to current int 1C handler
mov al,1Ch
int 21h ; Returns ES:BX
mov ax,ds
mov bx,es
sub ax,bx ; Compare found segment with int 1C segment
jz @F
jmp could_not_unlink
@@: mov es,si ; Restore segment of BUFFY_DATA
mov dx,WORD PTR org_clk_vector[0]
mov ds,WORD PTR org_clk_vector[2]
ASSUME DS:NOTHING, ES:BUFFY_DATA
mov ah,25h ; Reset int 1C vector to previous vector
mov al,1Ch ; Vector in DS:DX
int 21h
;----------------------------------------------------------------------------
; The interupt service routines have now been unlinked.
; Now we get our PSP and save it.
; Get the found copies PSP and make it active.
;----------------------------------------------------------------------------
mov ah,51h ; Get our PSP
int 21h ; Returned in BX
push bx ; Save this so we can reset later.
mov bx,psp_pointer ; Set found PSP to be active
mov ah,50h
int 21h
;----------------------------------------------------------------------------
; Release the memory originally consumed by the found copy of BUFFY.
;----------------------------------------------------------------------------
mov es,psp_pointer
mov ah,49h
int 21h
jnc @F
mov ax,cs
mov ds,ax
mov dx,OFFSET cs:msg_memory_failure
int 21h
add sp,2
stc
jmp SHORT exit_uninstall
;----------------------------------------------------------------------------
; Reset PSP back to current process.
;----------------------------------------------------------------------------
@@: pop bx
mov ah,50h
int 21h
jmp SHORT exit_uninstall
could_not_unlink:
mov ax,cs
mov ds,ax
mov dx,OFFSET cs:msg_interupt_taken
int 21h
stc
exit_uninstall:
pop es
pop ds
pop si
pop dx
pop bx
pop ax
ret
uninstall ENDP
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
set_int_2f_id PROC NEAR
ASSUME DS:BUFFY_DATA, ES:NOTHING
push ax
mov ah,80h
xor al,al
set_check:
int 2fh
or al,al
je set_2f_id
inc ah
jnz set_check
stc
jmp exit_set_2f_id
set_2f_id:
mov int_2f_id,ah
clc
exit_set_2f_id:
pop ax
ret
set_int_2f_id ENDP
msg_already_installed db 13,10,'TSR is already installed',13,10,'$'
msg_interupt_taken db 13,10,'Could not uninstall',13,10,'$'
msg_memory_failure db 13,10,'Memory deallocation failure - Reboot',13,10,'$'
BUFFY_CODE ENDS
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
STACK SEGMENT STACK 'STACK'
db 64 dup ('stack...')
STACK ENDS
END initialize