A terminate-and-stay-resident program (commonly TSR) is a computer program running under DOS that uses a system call to return control to DOS as though it has finished, but remains in computer memory so it can be reactivated later. This technique partially overcame DOS's limitation of executing only one program, or task, at a time. TSRs are used only in DOS, not in Windows.

Some TSRs are utility software that a computer user might call up several times a day, while working in another program, using a hotkey. Borland Sidekick was an early and popular example of this type. Others serve as device drivers for hardware that the operating system does not directly support.

Terminate-and-stay-resident program

Use

Normally DOS can run only one program at a time. When a program finishes, it returns control to DOS using the system call . The memory and system resources used are then marked as unused. This makes it impossible to restart parts of the program without having to reload it all. However, if a program ends with the system call or , the operating system does not reuse a certain specified part of its memory.

Terminate-and-stay-resident program

The original call, , is called "terminate but stay resident", hence the name "TSR". Using this call, a program can make up to 64 KB of its memory resident. MS-DOS version 2.0 introduced an improved call, ('Keep Process'), which removed this limitation and let the program return an exit code. Before making this call, the program can install one or several interrupt handlers pointing into itself, so that it can be called again. Installing a hardware interrupt vector allows such a program to react to hardware events. Installing a software interrupt vector allows it to be called by the currently running program. Installing a timer interrupt handler allows a TSR to run periodically (see ISA and programmable interval timer, especially the section "IBM PC compatible").

Terminate-and-stay-resident program

The typical method of using an interrupt vector involves reading its present value (the address), storing it within the memory space of the TSR, and replacing it with an address in its own code. The stored address is called from the TSR, in effect forming a singly linked list of interrupt handlers, also called interrupt service routines, or ISRs. This procedure of installing ISRs is called chaining or hooking an interrupt or an interrupt vector.

By chaining the interrupt vectors TSRs can take complete control of the computer. A TSR can have one of two behaviors: Take complete control of an interrupt by not calling other TSRs that had previously altered the same interrupt vector. Cascade with other TSRs by calling the old interrupt vector. This can be done before or after they executed their actual code. This way TSRs can form a chain where each calls the next.

The terminate-and-stay-resident method is used by most DOS viruses and other malware, which can either take control of the PC or stay in the background. This malware will react to disk I/O or execution events by infecting executable (.EXE or .COM) files when it is run and data files when they are opened.

TSRs can be loaded at any time; either during the DOS startup sequence (for example, from AUTOEXEC.BAT), or at the user's request (for example, Borland's Sidekick and Turbo Debugger, Quicken's QuickPay, or FunStuff Software's Personal Calendar). Parts of DOS itself use this technique, especially in DOS versions 5.0 and later. For example, the DOSKEY command-line editor and various other utilities are installed by running them at the command line (manually, or from AUTOEXEC.BAT or through INSTALL from within CONFIG.SYS) rather than loading them as device drivers through DEVICE statements in CONFIG.SYS.

Some TSRs have no way to unload themselves, so they will remain in memory until a reboot. However unloading is possible externally, using utilities like the MARK.EXE/RELEASE.EXE combo by TurboPower Software or soft reboot TSRs which will catch a specific key combination and release all TSRs loaded after them. As the chain of ISRs is singly linked, and a TSR may store the link to its predecessor anywhere it chooses, there is no general way for a TSR to remove itself from the chain. So usually a stub must be left in memory when unloading a TSR, causing memory fragmentation. This problem gave rise to TSR cooperation frameworks such as TesSeRact and AMIS.