Большой класс программ, обеспечивающих функционирование вычислительной системы (драйверы устройств, программы шифрации и защиты данных, русификаторы, обслуживающие программы типа электронных блокнотов или калькуляторов и др.), должны постоянно находиться в памяти и быстро реагировать на запросы пользователя или на какие-то события, происходящие в вычислительной системе. Такие программы носят названя программ, резидентных в памяти (Terminate and Stay Resident, TSR), или просто, резидентных программ. Сделать резидентной можно как программу типа .COM, так и программу типа .EXE, однако ввиду того, что резидентная программа должна быть максиматьно компактной, чаще всего в качестве резидентных используют программы типа .COM.
Рассмотрим типичную структуру резидентной программы и системные средства оставления ее в памяти после инициализации
text segment ‘code’
assume CS:text, DS:text
org 100h
main proc
jmp init ; Переход на секцию
; инициализации
; данные резидентной секции программы
…
entry: ; текст резидентной части программы
…
main endp
init proc
…
mov DX,(init-main+10Fh)/16
mov AH,3100h
int 21h
init endp
text ends
end main
Программа пишется в формате .COM, поэтому в ней предусматривается только один сегмент, с которым связываются сегментные регистры CS и DS; В начале сегмента резервируется 100h байт для PSP.
При запуске программы с клавиатуры управление передается (в соответствии с параметром директивы end) на начало процедуры main. Командой jmp сразу же осуществляется переход на секцию инициализации, которая может быть оформлена в виде отдельной процедуры или входить в состав процедуры main. В секции инициализации, в частности, подготавливаются условия для работы программы уже в резидентном состоянии. Последними строками секции инициализации вызывается функция DOS 31h, которая выполняет завершение программы, с оставлением в памяти указанной ее части. Размер резидентной части программы (в параграфах) передается DOS в регистре DX. Определить размер резидентной секции можно, например, следующим образом. К разности смещений init-main, которая равна длине резидентной части программы в байтах, прибавляется размер PSP (100h) и еще число 15 (0Fh) для того, чтобы после целочисленного деления на 16 результат был округлен в большую сторону.
С целью экономии памяти секция инициализации распологается в конце программы и отбрасывается при ее завершении.
Функция 31h, закрепив за резидентной программой необходимую для ее функционирования память, передает управление командному процессору и вычислительная система переходит в исходное состояние. Наличие программы, резидентной в памяти, никак не отражается на ходе вычислительного процесса, за исключением того, что уменьшается объем свободной памяти. Одновременно в память может быть загружено любое число резидентных программ. На рисунке прказаны элементы резидентной прграммы и их взаимодействие.
|
main jmp init |
Резидентная часть программы |
|||
|
* * * |
Резидентные поля данных |
|||
|
entry |
||||
|
* * * |
Резидентные коды |
|||
|
iret |
||||
|
init |
Завершение программы |
|||
|
* * * |
Секция инициализации |
|||
Любая резидентная программа имеет по крайней две точки входа. При запуске с клавиатуры программы типа .COM управление передается на первый байт после PSP (IP=100h). Поэтому практически всегда первой командой резидентной программы является команда jmp, передающая управление на начало секции инициализации.
После отработки функции DOS 31h программа остается в памяти в пассивном состоянии. Для того, чтобы активизировать резидентную программу, ей надо как-то передать управление и, возможно, параметры. Вызвать к жизни резидентную программу можно разными способами, но наиболее употребительным является механизм аппаратных или программных прерываний. В этом случае в секции инициализации необходимо заполнить соответствующий вектор адресом резидентной части программы (точка entry на схеме). Адрес entry образует вторую точку входа в программу, через которую осуществляется ее активизация. Очевидно, что резидентная секция программы должна заканчиваться командой выхода из прерывания iret.
