📄 tsrutil.asm
字号:
;TSRUTIL.ASM
;Define segment names used by C
;
_TEXT segment byte public 'CODE'
_TEXT ends
CONST segment word public 'CONST'
CONST ends
_BSS segment word public 'BSS'
_BSS ends
_DATA segment word public 'DATA'
_DATA ends
DGROUP GROUP CONST, _BSS, _DATA
assume CS:_TEXT, DS:DGROUP
public _new_int13, _init_intr
IFDEF MULTI
public _timer_int_chain
public _new_int10, _new_int25, _new_int26
ELSE
public _deinstall
ENDIF
extrn _ss_save:near ;save foreground SS
extrn _sp_save:near ;save foreground SP
extrn _unsafe_flag:near ;if true, don't interrupt
extrn _old_int13:near
IFDEF MULTI
extrn _old_int8:near
extrn _old_int10:near
extrn _old_int25:near ; note difference between
extrn _old_int26:near ; old_int25 and _old_int25!
ELSE
extrn _multiplex_id:near ;our int 2f id byte
ENDIF
_TEXT segment
IFNDEF MULTI
;*****
;void far deinstall(void)
;function to use int 2f to ask TSR to deinstall itself
;the registers are probably all changed when our tsr exits
;so we save then and perform the INT 2f. The TSR exit will
;eventually bring us back here. Then the registers are restored
;This function is called from the foreground, not the TSR
DEINSTALL equ 1
_deinstall proc far
push si
push di
push bp
mov word ptr _ss_save,ss ;save our stack frame
mov word ptr _sp_save,sp
mov cs:_ds_save,ds ; save DS for later restore
mov bx,cs
mov dx,offset TerminateAddr ;bx:dx points to terminate address
mov ah, byte ptr _multiplex_id
mov al, DEINSTALL
int 2fh ;call our TSR
;
;if TSR terminates ok, we'll skip this code and return to Terminate Addr
;
jmp short NoTerminate
TerminateAddr:
;Restore DS and stack
mov ax,cs:_ds_save ;bring back our data segment
mov ds,ax ;destroyed by int 2f
mov al,2 ;Set value for success
mov ss, word ptr _ss_save ;restore our stack
mov sp, word ptr _sp_save ;destroyed by int 2f
NoTerminate:
cbw ;Extend return value to word
pop bp
pop di
pop si
ret
_deinstall endp
ENDIF
;*****
;void inc_unsafe_flag(void) - increment unsafe flag
;*****
inc_unsafe_flag proc far
push ax
push ds
mov ax,DGROUP ;make DS = to our TSR C data segment
mov ds,ax
inc word ptr _unsafe_flag
pop ds ;put DS back to whatever it was
pop ax
ret
inc_unsafe_flag endp
;*****
;void dec_unsafe_flag(void) - decrement unsafe flag
;*****
dec_unsafe_flag proc far
push ax
push ds
mov ax,DGROUP ;make DS = to our TSR 'C' data segment
mov ds,ax
dec word ptr _unsafe_flag
pop ds ;put DS back to whatever it was
pop ax
ret
dec_unsafe_flag endp
;we can't trap the following interrupts in C for a number of
;reasons
; INT 13 returns info in the FLAGS, but a normal IRET
; restores the flags
;
; INT 25 & 26 leave the flags on the stack. The user
; must pop the off after performing an INT 25 or 26
;
; These interrupts pass information via registers such
; as DS. We don't want to change DS.
;
; Since DS is unknown, we must call the old interrupts
; via variables in the code segment. The _init_intr routine
; sets up these CS variables from ones with nearly-identical
; names in the C data segment in TSREXAMP.C.
;*****
;void far init_intr(void)
;move interrupt pointer saved in the C program to our CS data area
;*****
_init_intr proc far
push es
push bx
IFDEF MULTI
les bx,dword ptr _old_int10
mov word ptr cs:old_int10,bx
mov word ptr cs:old_int10+2,es
les bx,dword ptr _old_int25
mov word ptr cs:old_int25,bx
mov word ptr cs:old_int25+2,es
les bx,dword ptr _old_int26
mov word ptr cs:old_int26,bx
mov word ptr cs:old_int26+2,es
ENDIF
; note incredibly confusing distinction
; between e.g. _old_int13 and old_int13
les bx,dword ptr _old_int13
mov word ptr cs:old_int13,bx
mov word ptr cs:old_int13+2,es
pop bx
pop es
ret
_init_intr endp
;*****
;void far new_int13(void) - disk interrupt
;*****
_new_int13 proc far
call inc_unsafe_flag
pushf ;simulate interrupt call
call cs:old_int13
call dec_unsafe_flag
ret 2 ; leave flags intact
_new_int13 endp
IFDEF MULTI
;*****
;void far new_int10(void) - video interrupt
;*****
_new_int10 proc far
call inc_unsafe_flag
pushf ;simulate interrupt call
call cs:old_int10
call dec_unsafe_flag
iret
_new_int10 endp
;*****
;void far new_int25(void) - MS-DOS absolute sector read
;*****
_new_int25 proc far
call inc_unsafe_flag
call cs:old_int25
call dec_unsafe_flag
ret ; user must pop flags - MS-DOS convention
; so leave them on the stack
_new_int25 endp
;*****
;void far new_int26(void) - MS-DOS absolute sector write
;*****
_new_int26 proc far
call inc_unsafe_flag
call cs:old_int26
call dec_unsafe_flag
ret ; user must pop flags - MS-DOS convention
; so leave them on the stack
_new_int26 endp
;*****
;void far timer_int_chain(void) - jump to next timer ISR
;we need to clean up the stack because of this call
;*****
_timer_int_chain proc far
mov _ax_save,ax
pop ax
pop ax
mov ax,_ax_save
jmp dword ptr _old_int8
_timer_int_chain endp
ENDIF
;
;save areas for original interrupt vectors
;
IFDEF MULTI
old_int10 dd 0 ;video
old_int25 dd 0 ;sector read
old_int26 dd 0 ;sector write
ENDIF
old_int13 dd 0 ;disk
_ds_save dw 0
_TEXT ends
_DATA segment
IFDEF MULTI
_ax_save dw 0
ENDIF
_DATA ends
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -