Article View: comp.os.msdos.programmer
Article #773Re: Need help on TSR's
From: Mark Addinall
Date: Thu, 16 Apr 1992 04:32
Date: Thu, 16 Apr 1992 04:32
1267 lines
42926 bytes
42926 bytes
In <1992Apr15.235445.9454@sequent.com> furballs@sequent.com writes: >In article <1992Apr15.033850.16536@uwm.edu> markh@csd4.csd.uwm.edu (Mark William Hopkins) writes: >>In article <oddt.4@sofus.dhhalden.no> oddt@sofus.dhhalden.no (ODD ROBERT TORJUSSEN) writes: >>>We've come so far in the development, that the 'prototype' tsr is up running >>>and seems to work ok. We're started to add some 'features' to this tsr. [deleted] >>If it's being run on a DOS, the problem is likely the DOS. System calls are >>usually critical regions in DOS. If two processes happen to be concurrently >>accessing the same critical region, they could destroy the integrity of the DOS. >> >>That might be the problem. sure is !!! :-) >DOS is the problem. Whenever you run a renegade process under DOS, >(a TSR is a good example), DOS does not know of it's existence and [deleted] >Having done both, I can recommend #1 as the greatest time saver and >least stress inducer. These guys have already done the home work. >Don't reinvent the wheel. We always seem to ;-) I am sure that the product you mentioned is first class, a netter rarely reccomends anything :-) Anyhoo, I see a lot of postings about how to manage TSR's from time to time and I thought that this might help. I've only just finished writing the thing myself, but I may be off the net for a while and unable to post the final (debugged ;-) version. Good Luck :-) ----------------------------CUT HERE---------------------------------------- COMMENT & +----------------------------------------------------------------------------+ | FILE : TSR.ASM | | AUTHOR : M. ADDINALL | | DATE : 01/04/92 | | VERSION : 1.0 | +----------------------------------------------------------------------------+ | Checks will be included in this TSR, i.e. no TSR recursion, possible | | DOS re-entrant calls etc. This TSR will also clean up after itself. This | | is the assembler part of the TSR, three functions, _tsr_init, _is_inst | | and _un_inst will be available to a C system. Described in functions. | +------------+------+--------------------------------------------------------+ | CHANGE | WHO | REASON FOR CHANGE | +------------+------+--------------------------------------------------------+ | 01/04/92 | MA | Initial coding | | | | | +----------------------------------------------------------------------------+ END-COMMENT & ;;--------------------------------------------------------------------------- ;; set up code and data groups to use ;;--------------------------------------------------------------------------- IGROUP group _TEXT ;;combination of program segments DGROUP group const,_bss,_data ;;combination of data segments assume CS:IGROUP, DS:DGROUP, ES:DGROUP, SS:DGROUP ;;--------------------------------------------------------------------------- ;; set up segment for read-only constants ;;--------------------------------------------------------------------------- CONST segment word public 'CONST' CONST ends ;;-------------------------------------------------------------------------- ;; set up area for uninitialised static variables ;;-------------------------------------------------------------------------- _BSS segment word public 'BSS' _BSS ends ;;-------------------------------------------------------------------------- ;; set up area for initialised and global static variables ;;-------------------------------------------------------------------------- _DATA segment word public 'DATA' extrn __psp : word ;; segment address of the C driver _DATA ends ;;------------------------------------------------------------------------- ;; constants ;;------------------------------------------------------------------------- TRUE EQU 1H FALSE EQU 0H DOS_INT EQU 21H VID_REQ EQU 10H TERM_FUNC EQU 31H SOFT_INT EQU 62H HARD_INT EQU 05H DOS_SHOW EQU 09H CR EQU 10H LF EQU 0DH GET_DTA EQU 2FH SET_DTA EQU 1AH GET_INDOS EQU 34H GET_PSP EQU 51H SET_PSP EQU 50H GET_INT_5 EQU 3505H GET_INT_62 EQU 3562H GET_INT_13 EQU 3513H SET_INT_5 EQU 2505H SET_INT_62 EQU 2562H SET_INT_13 EQU 2513H ENVIRONMENT EQU 02CH REL_MEMORY EQU 49H INSTALLED EQU 1H NOT_INST EQU 0H NO_FUNC EQU 0FFFFH PARAGRAPH EQU 0064 ID_LEN EQU 0004 ;; make it compatible with CICS ;; hey hey... ;;------------------------------------------------------------------------- ;; macros ;;------------------------------------------------------------------------- ;;---------------------------- say MACRO string ;; output macro push ax ;; AX onto stack push bx ;; ditto for BX mov bx,offset string ;; dope start of string mov ah,DOS_SHOW ;; function request, display ;; string int DOS_INT ;; do it pop bx ;; restore BX pop ax ;; ditto for AX ENDM ;;------------------- place_stack MACRO push bp ;; place BP on the stack mov bp,sp ;; and dope stack pointer ENDM ;;------------------- store_registers MACRO mov cs:c_ss,ss ;; get stack segment mov cs:c_sp,sp ;; stack pointer mov cs:c_es,es ;; extra segment mov cs:c_ds,ds ;; and data segment, all safe now :-) ENDM ;;------------------- fetch_id MACRO local j mov si,frame.idptr0 ;; DS:SI points to string id push cs ;; CS onto the stack pop es ;; and restore as ES mov di,offset id_buff ;; ES:DI points to storage mov cx,ID_LEN ;; prime counter j: lodsb ;; get a character stosb ;; and push into storage or al,al ;; end of string ? loopne j ;; while ( ch != 0 && cx != 0 ); ENDM ;;--------------------------- fetch_parameters MACRO mov ax,frame.fktptr0 ;; get the pointer to the C TSR func mov cs:tsr_adr0,ax ;; and save it mov ax,frame.fktptr1 ;; get pointer to the second function mov cs:tsr_adr1,ax ;; and save it ENDM ;;------------------- fetch_dta MACRO mov ah,GET_DTA ;; function request, get DTA address int DOS_INT ;; do it dos mov cs:c_dta_ofs,bx ;; store offset of DTA pointer mov cs:c_dta_seg,es ;; and its segment in memory ENDM ;;------------------- fetch_indos MACRO mov ah,GET_INDOS ;; function request, get INDOS flag int DOS_INT ;; do it dos mov cs:idos_ofs,bx ;; store offset of INDOS flag pointer mov cs:idos_seg,es ;; and its segment in memory ENDM ;;--------------------------- fetch_interrupts MACRO mov ax,GET_INT_5 ;; get interrupt vector 05H int DOS_INT ;; do it DOS mov cs:int5_ofs,bx ;; save the interrupt offset mov cs:int5_seg,es ;; and save the segment mov ax,GET_INT_13 ;; get interrupt vector 13H int DOS_INT ;; DISK BIOS mov cs:int13_ofs,bx ;; save the interrupt offset mov cs:int13_seg,es ;; and save the segment mov ax,GET_INT_62 ;; and now for the SINT 62 int DOS_INT ;; hello DOS mov cs:int62_ofs,bx ;; store offset mov cs:int62_seg,es ;; and the segment ENDM ;;--------------------------- install_interrupts MACRO push ds ;; save data segment mov ax,cs ;; CS to AX mov ds,ax ;; and onto DS mov ax,SET_INT_5 ;; dope function request mov dx,offset int5 ;; DS:DX has the address of handler int DOS_INT ;; do it DOS mov ax,SET_INT_13 ;; dope function request mov dx,offset int13 ;; DS:DX has the address of handler int DOS_INT ;; do it DOS mov ax,SET_INT_62 ;; dope function request mov dx,offset int62 ;; DS:DX has the address of handler int DOS_INT ;; hello DOS pop ds ;; restore data segment ENDM ;;----------------------- calculate_memory MACRO xor ax,ax ;; determine current break address push ax ;; as argument for SBRK on the stack call _sbrk ;; call C function pop ax ;; get argument off stack mov cs:break_addr,ax ;; store for later add ax,frame.heap0 ;; add required heap memory mov dx,ax ;; get the break address into DX add dx,15 ;; avoid integer division loss mov cl,4 ;; shift 4 times to the right then.. shr dx,cl ;; divide by 16 mov ax,ds ;; dope data segment mov bx,__psp ;; and the segment of the PSP mov cs:c_psp,bx ;; and store for later use sub ax,bx ;; subtract DS from PSP add dx,ax ;; add to the number of paragraphs ENDM ;;--------------------------- terminate_resident MACRO mov al,0 ;; clobber AL, who cares really mov ah,TERM_FUNC ;; set up function request int DOS_INT ;; and go to sleep ENDM ;;--------------------------- stack_context_switch MACRO mov cs:ce_seg,es ;; set up for context switch to C mov cs:u_prg_ss,ss ;; save stack segment mov cs:u_prg_sp,sp ;; and the stack pointer ;; critical ... cli ;; disable interrupts mov ss,es:c_ss ;; activate the TSR mov sp,es:c_sp ;; program sti ;; and turn interrupts back on ;; end critical ... ENDM ;;--------------------------- dta_context_switch MACRO push es ;; ES onto stack mov ah, GET_DTA ;; function request, get DTA int DOS_INT ;; do it DOS mov cs:u_prg_ss,ss ;; save the current stack mov cs:u_prg_sp,sp ;; segment and pointer pop es ;; ES off stack ENDM ;;--------------------------- psp_context_switch MACRO mov ah,GET_PSP ;; function request, get PSP mov bx,es:c_psp ;; and dope the seg addr of the PSP int DOS_INT ;; do it DOS ENDM ;;--------------------------- new_dta_context_switch MACRO push ds ;; DS onto the stack push es ;; ES onto the stack mov ah,SET_DTA ;; function request, set DTA mov dx,es:c_dta_ofs ;; get offset addres of new DTA mov ds,es:c_dta_seg ;; and the segment address int DOS_INT ;; do it DOS ENDM ;;--------------------------- execute_end_function MACRO mov ds,es:c_ds ;; set segment register mov es,es:c_es ;; registers for the C program call cs:[ce_ptr] ;; and call the function. ;; This pointer will probably ;; reset the board. If you guys ;; are going to do everything in ;; C, you'll be OK. If you write ;; external or inline assembler, ;; make sure you don't blow all these ;; carefully constructed segment ;; stores and critical context changes ENDM ;;--------------------------- restore_dta MACRO mov ah,SET_DTA ;; function request, set DTA mov dx,cs:u_dta_ofs ;; dope the offset and segment mov ds,cs:u_dta_seg ;; address of the interrupted program int DOS_INT ;; do it DOS pop es ;; segment addr of TSR from stack pop ds ;; restore TSR DS from stack ENDM ;;--------------------------- restore_psp MACRO mov ah,SET_PSP ;; function request, set PSP mov bx,__psp ;; load seg address of the PSP int DOS_INT ;; do it DOS ENDM ;;--------------------------- restore_stack MACRO ;; critical ... cli ;; interrupts off mov ss,cs:u_prg_ss ;; restore stack segment mov sp,cs:u_prg_sp ;; and stack pointer sti ;; interrupts on, phew :-) ENDM ;;--------------------------- restore_interrupts MACRO ;; critical ... cli ;; interrupts off mov ds,es:int5_seg ;; get the interrupt segment mov dx,es:int5_ofs ;; and offset mov ax,SET_INT_5 ;; function request, set interrupt vect int DOS_INT ;; do it DOS mov ds,es:int62_seg ;; get the interrupt segment mov dx,es:int62_ofs ;; and offset mov ax,SET_INT_62 ;; function request, set interrupt vect int DOS_INT ;; do it DOS mov ds,es:int13_seg ;; get the interrupt segment mov dx,es:int13_ofs ;; and offset mov ax,SET_INT_13 ;; function request, set interrupt vect int DOS_INT ;; do it DOS sti ;; interrupts on, pant ;-| ENDM ;;--------------------------- release_memory MACRO mov es,es:c_psp ;; segment address of the TSR PSP mov cx,es ;; and save it in the counter mov es,es:[ENVIRONMENT] ;; segment address of environment mov ah,REL_MEMORY ;; function request, release memory int DOS_INT ;; and free it up mov es,cx ;; restore es mov ah,REL_MEMORY ;; function request, release memory int DOS_INT ;; do it DOS ENDM ;;--------------------------- set_recurse_flag MACRO bool mov cs:recurse,bool ;; toggle recursion boolean ENDM ;;--------------------------- change_context MACRO mov cs:u_prg_ss,ss ;; save current stack segment mov cs:u_prg_sp,sp ;; and the stack pointer mov ss,cs:c_ss ;; activate the C segment mov sp,cs:c_sp ;; and the C stack pointer ENDM ;;--------------------------- push_the_cpu MACRO push ax ;; AX onto stack push bx ;; BX onto stack push cx ;; CX onto stack push dx ;; DX onto stack push bp ;; BP onto stack push si ;; SI onto stack push di ;; DI onto stack push ds ;; DS onto stack push es ;; ES onto stack ENDM ;;--------------------------- steal_some_stack MACRO local i mov cx,PARAGRAPH ;; dope loop counter mov ds,cs:u_prg_ss ;; set DS:DI to the end mov si,cs:u_prg_sp ;; of the DOS stack i: push word ptr [si] ;; save a word from the DOS stack inc si ;; onto the C stack and set SI to inc si ;; to the next stack word loop i ;; push a paragraph ENDM ;;--------------------------- get_start_psp MACRO mov ah,GET_PSP ;; function request, get address of PSP int DOS_INT ;; get DOS to do it mov cs:u_psp,bx ;; save address of psp ENDM ;;--------------------------- get_start_dta MACRO mov ah,GET_DTA ;; function request, get address of DTA int DOS_INT ;; get DOS to do it mov cs:u_dta_ofs,bx ;; store the address of the DTA of mov cs:u_dta_seg,es ;; of the interrupted program ENDM ;;--------------------------- set_start_psp MACRO mov ah,SET_PSP ;; function request, set PSP mov bx,cs:c_psp ;; dope the address of the C PSP int DOS_INT ;; get DOS to do it ENDM ;;--------------------------- set_start_dta MACRO mov ah,SET_DTA ;; function request, set DTA mov dx,cs:c_dta_ofs ;; get the offset address of new DTA mov ds,cs:c_dta_seg ;; and the segment address int DOS_INT ;; and do it DOS :-) ENDM ;;--------------------------- set_segments MACRO mov ds,cs:c_ds ;; set segment register for mov es,cs:c_es ;; the C program ENDM ;;--------------------------- reset_dta MACRO mov ah,SET_DTA ;; function request, set DTA mov dx,cs:u_dta_ofs ;; load the offset and segment mov ds,cs:u_dta_seg ;; of the interrupted program int DOS_INT ;; get DOS to do it ENDM ;;--------------------------- reset_psp MACRO mov ah,SET_PSP ;; function request, set PSP mov bx,cs:u_psp ;; reset segment address of PSP int DOS_INT ;; do it DOS... ENDM ;;--------------------------- restore_dos_stack MACRO local k mov cx,PARAGRAPH ;; dope the counter mov ds,cs:u_prg_ss ;; load DS:SI with the address of mov si,cs:u_prg_sp ;; the DOS stack add si, (PARAGRAPH * 2) ;; SI to the start of DOS stack k: dec si ;; SI to point to the previous dec si ;; stack word pop word ptr [si] ;; get the word back on DOS stack loop k ;; until finished ENDM ;;--------------------------- pull_the_cpu MACRO pop es ;; ES off the stack pop ds ;; DS off the stack pop di ;; DI off the stack pop si ;; SI off the stack pop bp ;; BP off the stack pop dx ;; DX off the stack pop cx ;; CX off the stack pop bx ;; BX off the stack pop ax ;; AX off the stack ENDM ;;--------------------------- reset_stack_pointer MACRO mov ss,cs:u_prg_ss ;; reset stack segment to program mov sp,cs:u_prg_sp ;; reset stack pointer to program ENDM ;;--------------------------- is_dos_alive MACRO bool local ok mov bool,FALSE ;; FALSE is good for this routine push ds ;; save DS onto the stack push bx ;; save BX onto the stack lds bx,cs:idos_ptr ;; DS:BX now points to the indos flag cmp byte ptr [bx],FALSE ;; is DOS active je ok ;; no worries mov bool,TRUE ;; sad but true, DOS is alive ok: pop bx ;; BX back from stack pop ds ;; DS back from stack ENDM ;;------------------------------------------------------------------------ ;; ok, let's start the code segment ;;------------------------------------------------------------------------ _TEXT segment byte public 'CODE' ;; the program segment ;;------------------------------------------------------------------------ ;; references to external C functions ;;------------------------------------------------------------------------ extrn _sbrk : near ;;----------------------------------------------------------------------- ;; declare our public function accessable to C ;;----------------------------------------------------------------------- public _tsr_init public _is_installed public _uninstall ;;------------------------------------------------------------------------ ;; declare and initialise some variables ;;------------------------------------------------------------------------ id_buff db (ID_LEN + 1) dup(0) ;; ID string buffer for TSR ce_ptr EQU this dword ;; points to call_end ce_ofs dw offset call_end ;; offset of routine call_end ce_seg dw ? ;; space for call_end segment c_ss dw 0 ;; C stack segment c_sp dw 0 ;; C stack pointer c_ds dw 0 ;; C data segment c_es dw 0 ;; C extra segment c_dta_ofs dw 0 ;; DTA address of the program c_dta_seg dw 0 ;; and DTA segment c_psp dw 0 ;; psp of the application program break_addr dw 0 ;; break address of the heap tsr_adr0 dw 0 ;; address of the C TSR function tsr_adr1 dw 0 ;; and the second function recurse db FALSE ;; no recursive TSR's please in_bios db FALSE ;; wise not to interrupt the BIOS in_dos db FALSE ;; or DOS for that matter success db TRUE ;; eternal bloody optimist in_5 db FALSE ;; interrupt type flag idos_ptr EQU this dword ;; pointer to the DOS indos flag idos_ofs dw 0 ;; pointer offset address idos_seg dw 0 ;; pointer segment address int5_ptr EQU this dword ;; activation hardware interrupt int5_ofs dw 0 ;; offset of the pointer int5_seg dw 0 ;; pointer segment int62_ptr EQU this dword ;; activation software interrupt int62_ofs dw 0 ;; offset of the pointer int62_seg dw 0 ;; pointer segment address int13_ptr EQU this dword ;; get the BIOS disk interrupt int13_ofs dw 0 ;; offset of the pointer int13_seg dw 0 ;; pointer segment address u_dta_ofs dw 0 ;; DTA address of interrupted u_dta_seg dw 0 ;; program u_psp dw 0 ;; segment address of psp of same u_prg_ss dw 0 ;; stack segment of same u_prg_sp dw 0 ;; stack pointer of same hello db CR,LF db "IO TSR Version 1.nothing ",CR,LF db "--------------Loading------------",CR,LF db "Using IRQ5 && SINT62 ",CR,LF,"$" COMMENT & +----------------------------------------------------------------------------+ | FUNCTION : _tsr_init | | AUTHOR : M. ADDINALL | | DATE : 01/04/92 | | VERSION : 1.0 | +----------------------------------------------------------------------------+ | Abstract | +----------------------------------------------------------------------------+ | void tsr_init( void (fkt *) (void), | | void (fk2 *) (void), | unsigned heap_byte, | | char * id_string ) ; | | | | Called from the C driver, this function initialises the TSR. The function | | is_inst will already have been called to stop the event of a recursive | | TSR load (if the programmers awake, that is). | | | +------------+------+--------------------------------------------------------+ | CHANGE | WHO | REASON FOR CHANGE | +------------+------+--------------------------------------------------------+ | 04/03/92 | MA | Initial coding | | | +----------------------------------------------------------------------------+ END-COMMENT & _tsr_init proc near sframe0 struc ;; structure for accessing stack bp0 dw ? ;; store for BP ret_adr0 dw ? ;; return address fktptr0 dw ? ;; pointer to C TSR function fktptr1 dw ? ;; another C function heap0 dw ? ;; heap bytes required idptr0 dw ? ;; pointer to the ID string sframe0 ends ;; end of structure frame EQU [ bp - bp0 ] ;; calculate this code frame say hello ;; hello world place_stack ;; position stack pointer store_registers ;; fetch register data into memory fetch_id ;; load the identification string fetch_parameters ;; get the function arguments fetch_dta ;; get the DTA address of the C program fetch_indos ;; get the address of the INDOS flag fetch_interrupts ;; get the addresses of the interrupts install_interrupts ;; put our interrupt handlers in calculate_memory ;; figure out how much memory to use terminate_resident ;; go sleepy bo bo's. Passive TSR loaded :-) _tsr_init endp COMMENT & +----------------------------------------------------------------------------+ | FUNCTION : _is_installed | | AUTHOR : M. ADDINALL | | DATE : 01/04/92 | | SYSTEM : MS-DOS Stallion IO Drivers | | VERSION : 1.0 | +----------------------------------------------------------------------------+ | Abstract | +----------------------------------------------------------------------------+ | BOOL _is_installed( unsigned bp, | | void * return_address, | | char * id_string ); | | | | Called by a C program to see if this thing is already running, | | | +------------+------+--------------------------------------------------------+ | CHANGE | WHO | REASON FOR CHANGE | +------------+------+--------------------------------------------------------+ | 01/04/92 | MA | Initial coding | | | | | | | +----------------------------------------------------------------------------+ END-COMMENT & _is_installed proc near sframe1 struc ;; structure to get stack bp1 dw ? ;; hold BP ret_adr1 dw ? ;; return address idptr1 dw ? ;; pointer to ID string sframe1 ends ;; close the structure frame EQU [bp - bp1] ;; establish code frame place_stack ;; position stack pointer push di ;; DI onto stack push si ;; SI onto stack push es ;; ES onto stack mov ax,GET_INT_5 ;; dope function request int DOS_INT ;; do it DOS mov di,offset id_buff ;; ES:DI points to ID_BUFF mov si,frame.idptr1 ;; DS:SI points to the ID_STRING passed mov cx,NOT_INST ;; dope return value search: ;; string compare label lodsb ;; load a character from string cmp al,es:[di] ;; compare strings jne ninst ;; failed, not installed inc di ;; increment string pointer or al,al ;; end of string ? jne search ;; no, keep comparing mov cl,INSTALLED ;; we're installed already :-) ninst: ;; exit label target mov ax,cx ;; prime return code pop es ;; restore ES pop si ;; restore SI pop di ;; restore DI pop bp ;; restore BP ret ;; and bugger off _is_installed endp COMMENT & +----------------------------------------------------------------------------+ | FUNCTION : _call_end | | AUTHOR : M. ADDINALL | | DATE : 01/04/92 | | VERSION : 1.0 | +----------------------------------------------------------------------------+ | Abstract | +----------------------------------------------------------------------------+ | void _call_end( void ) ; | | | | | | | | Calls the end function on reinstallation of the TSR. Internal use | | only, not intended to be public. | | | | | +------------+------+--------------------------------------------------------+ | CHANGE | WHO | REASON FOR CHANGE | +------------+------+--------------------------------------------------------+ | 01/04/92 | MA | Initial coding | | | | | | | +----------------------------------------------------------------------------+ END-COMMENT & call_end proc far call di ;; call the end function ret ;; back to the caller call_end endp COMMENT & +----------------------------------------------------------------------------+ | FUNCTION : _uninstall | | AUTHOR : M. ADDINALL | | DATE : 01/04/92 | | VERSION : 1.0 | +----------------------------------------------------------------------------+ | Abstract | +----------------------------------------------------------------------------+ | void _uninstall( void ( endfkt * ) ( void ) ) ; | | | | | | | | Calls the end function on reinstallation of the TSR. | | If the value 0xffff is passed to this function, no end_function will | | be called. This function releases allocated memory. | | | +------------+------+--------------------------------------------------------+ | CHANGE | WHO | REASON FOR CHANGE | +------------+------+--------------------------------------------------------+ | 01/04/92 | MA | Initial coding | | | | | | | +----------------------------------------------------------------------------+ END-COMMENT & _uninstall proc far sframe2 struc bp2 dw ? ;; storage for BP ret_adr2 dw ? ;; return address ftnptr2 dw ? ;; pointer to the end function sframe2 ends frame EQU [ bp - bp2 ] ;; calculate code frame assume es:IGROUP ;; allow access to CS through ES place_stack ;; update stack pointer push di ;; DI onto stack push si ;; SI onto stack push ds ;; DS onto stack push es ;; ES onto stack mov ax,GET_INT_5 ;; get current interrupt vector int DOS_INT ;; for int 5 mov di,frame.ftnptr2 ;; get address of end function cmp di,NO_FUNC ;; -1 parameter ? jne call_function ;; work to do, jump a few bytes jmp no_function ;; brain dead assembler ;; dontcha hate that :-) call_function: ;; dopey target stack_context_switch ;; activate TSR stack dta_context_switch ;; set up current DTA psp_context_switch ;; set up current PSP new_dta_context_switch ;; now the new DTA execute_end_function ;; carry out the code restore_dta ;; fetch DTA back restore_psp ;; fetch PSP back restore_stack ;; fetch stack back no_function: restore_interrupts ;; fetch interrupts back release_memory ;; release allocated memory pop es ;; ES off stack pop ds ;; DS off stack pop si ;; SI off stack pop di ;; DI off stack pop bp ;; BP off stack ret ;; and bugger off assume es:DGROUP ;; combine ES with DGROUP again _uninstall endp COMMENT & +----------------------------------------------------------------------------+ | FUNCTION : _start_tsr | | DATE : 06/04/92 | | SYSTEM : MS-DOS Stallion IO Drivers | | VERSION : 1.0 | +----------------------------------------------------------------------------+ | Abstract | +----------------------------------------------------------------------------+ |void _start_tsr(void); | | | |This procedure will be called on the first instance of an interrupt | |recieved by the resident TSR code lurking around in memory. For speed | |considerations on start ( i.e. the ramp time this procedure needs on | |start as opposed to the initial incoming interrupt rate on the bus ), | |we may make this one public to be called from the application, although, | |depending on when this is loaded into memory, a whole bunch of INT13H's | |might be generated before the call to start communications. Who knows. | | | +------------+------+--------------------------------------------------------+ | CHANGE | WHO | REASON FOR CHANGE | +------------+------+--------------------------------------------------------+ | 06/04/92 | MA | Initial coding | | | +----------------------------------------------------------------------------+ END-COMMENT & _start_tsr proc near cli ;; no interrupts at this point set_recurse_flag TRUE ;; no recursive TSR's please :-) change_context ;; activate the C program stack push_the_cpu ;; push all registers on stack steal_some_stack ;; get 64 words of the DOS stack get_start_psp ;; fetch initial PSP get_start_dta ;; fetch initial DTA set_start_psp ;; install start psp set_start_dta ;; install start dta set_segments ;; set segment register for C cmp in_5,FALSE ;; is this an interrupt 05 jne do_a_62 ;; nope, do some other stuff sti ;; turn interrupts back on call cs:tsr_adr0 ;; call the TSR routine for int05 cli ;; interrupts back off for a moment jmp all_done ;; get out of here do_a_62: ;; target for interrupt 62 code sti ;; interrupts back on call cs:tsr_adr1 ;; call TSR routines for interrupt 62 cli ;; interrupts off all_done: ;; exit target for the interrupt 5 code reset_dta ;; put the DTA back to normal reset_psp ;; put the PSP back to normal restore_dos_stack ;; return stack we stole :-) pull_the_cpu ;; pop all registers offa stack reset_stack_pointer ;; tidy up ss:sp set_recurse_flag FALSE ;; reset TSR recursion flag sti ;; enable interrupts now ret ;; return to caller _start_tsr endp COMMENT & +----------------------------------------------------------------------------+ | FUNCTION : int13 | | AUTHOR : M. ADDINALL | | DATE : 06/04/92 | | VERSION : 1.0 | +----------------------------------------------------------------------------+ | Abstract | +----------------------------------------------------------------------------+ | This is a stub that replaces the entry point to the BIOS int13. Of course | | int 13 is DASD BIOS activity. As this interrupt could be active for a | | number of cycles, we want the rest of the system to know that the BIOS | | is servicing a disk request. No more dissapearing database, heh guys ;-) | | | | | +------------+------+--------------------------------------------------------+ | CHANGE | WHO | REASON FOR CHANGE | +------------+------+--------------------------------------------------------+ | 06/04/92 | MA | Initial coding | | | | | | | +----------------------------------------------------------------------------+ END-COMMENT & int13 proc far mov cs:in_bios,TRUE ;; toggle BIOS active flag pushf ;; call the one and only true call cs:int13_ptr ;; BIOS service mov cs:in_bios,FALSE ;; all over, safe to go on ret 2 ;; clean up stack from flag push int13 endp COMMENT & +----------------------------------------------------------------------------+ | FUNCTION : int5 | | AUTHOR : M. ADDINALL | | DATE : 06/04/92 | | VERSION : 1.0 | +----------------------------------------------------------------------------+ | Abstract | +----------------------------------------------------------------------------+ |This interrupt routine will service the interrupts generated by the | |xxxxxxxx X.25 communication device. The generation of this interrupt is | |the action of STREAMS based software running on the X.25 board. It is | |the responsibility of this procedure to intercept the interrupt and to | |call the appropriate X.25 PDK function running on the HOST machine. | | | +------------+------+--------------------------------------------------------+ | CHANGE | WHO | REASON FOR CHANGE | +------------+------+--------------------------------------------------------+ | 06/04/92 | MA | Initial coding | | | +----------------------------------------------------------------------------+ END-COMMENT & int5 proc far ;; OK Antonio && Kieth, ;; what do you want to happen ;; in here. Please read source, ;; questions gratefully received, ;; white-board session now on ;; where to go ;; cheers :-) Mark... mov in_5,TRUE ;; we're in an int 5 routine mov success,TRUE ;; assume we'll suceed :-) cmp recurse,FALSE ;; are we recursing jne fail ;; re-entrancy is naughty cmp in_bios,FALSE ;; are we in a disk write ? jne fail ;; don't interrupt the BIOS is_dos_alive in_dos ;; is there a DOS function happening ? cmp in_dos,FALSE ;; well ? jne fail ;; don't interrupt active processes call _start_tsr ;; ok, do the stuff jmp fin_05 ;; get out fail: mov success,FALSE ;; damn, something went wrong fin_05: mov ah,0 ;; blat AH, who cares mov al,success ;; did we do anything useful ? push ax ;; tell the world we could(n't) ;; process this interrupt :-( mov in_5,FALSE ;; no longer in an interrupt 5 iret ;; and back to caller int5 endp COMMENT & +----------------------------------------------------------------------------+ | FUNCTION : int62 | | AUTHOR : M. ADDINALL | | DATE : 06/04/92 | | VERSION : 1.0 | +----------------------------------------------------------------------------+ | Abstract | +----------------------------------------------------------------------------+ |This function will respond to a software interrupt. This interrupt would | |have been generated by an application call to the X.25 PDK through the | |X.25 PDK API/NPI. The responsibility of this function is to respond to | |the interrupt and to respond to the appropriate X.25 PDK function that is | |running on the HOST machine. It will check to see if we are re-entrant, | |and the activity level of the DASD BIOS before using system resource. | | | +------------+------+--------------------------------------------------------+ | CHANGE | WHO | REASON FOR CHANGE | +------------+------+--------------------------------------------------------+ | 06/04/92 | MA | Initial coding | | | +----------------------------------------------------------------------------+ END-COMMENT & int62 proc far ;; OK Antonio && Kieth, ;; what do you want to happen ;; in here. Please read source, ;; questions gratefully received, ;; white-board session now on ;; where to go ;; cheers :-) Mark... mov success,TRUE ;; assume we'll suceed :-) cmp recurse,FALSE ;; are we recursing jne fail ;; re-entrancy is naughty cmp in_bios,FALSE ;; are we in a disk write ? jne fail ;; don't interrupt the BIOS is_dos_alive in_dos ;; is there a DOS function happening ? cmp in_dos,FALSE ;; well ? jne fail62 ;; don't interrupt active processes call _start_tsr ;; ok, do the stuff jmp fin_62 ;; get out fail62: mov success,FALSE ;; damn, something went wrong fin_62: mov ah,0 ;; blat AH, ho hum... mov al,success ;; send the world a message push ax ;; whether we could or couldn't ;; process this interrupt :-( iret ;; and back to caller int62 endp ;;-------------------------------------------------------------------------- ;; ok, we'll end the code segment and give the linker an entry point ;;-------------------------------------------------------------------------- _TEXT ends ;; end of the code segment end ;; end of the program ;;-------------------------------------------------------------------------- ;; end of file <tsr.asm> ;;-------------------------------------------------------------------------- ---------------------------CUT HERE----------------------------------------- I hope the concepts are clear. I worked from a tsr I developed some time ago for another company. A lot of the mechanics a due to an exellent book 'PC System Programming', Abacus press, by Micheal Tischer. I would recommend that anyone wanting to do serious system work on a PC get this book. It describes TSR's, device drivers, the BIOS interface etc., etc.
Technical Details
Message-ID:
<addinall.703398778@cluster>Path:
arc1-ca.pugleaf.net!sparky!uunet!munnari.oz.au!bunyip.cc.uq.oz.au!uqcspe!stallion!addinallReferences:
<oddt.4@sofus.dhhalden.no> <1992Apr15.033850.16536@uwm.edu> <1992Apr15.235445.9454@sequent.com>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!sparky!uunet!munnari.oz.au!bunyip.cc.uq.oz.au!uqcspe!stallion!addinall From: addinall@stallion.oz.au (Mark Addinall) Newsgroups: comp.os.msdos.programmer Subject: Re: Need help on TSR's Message-ID: <addinall.703398778@cluster> Date: 16 Apr 92 04:32:58 GMT References: <oddt.4@sofus.dhhalden.no> <1992Apr15.033850.16536@uwm.edu> <1992Apr15.235445.9454@sequent.com> Sender: news@stallion.stallion.oz.au Lines: 1267