1.3.4 Сохранение программы в памяти после завершения.

  Программы, оставленные резидентными  в памяти, могут служить в
качестве утилит для других программ. Обычно такие программы вызы-
ваются через неиспользуемый вектор  прерывания. MS DOS рассматри-
вает  такие программы как часть операционной системы, защищая  их
от наложения других программ, которые  будут загружены впоследст-
вии. Резидентные программы обычно пишутся в форме COM, что обсуж-
дается в пункте [1.3.6].  Программы, написанные в форме EXE оста-
вить резидентными в памяти немного труднее.
   Завершение  программы прерыванием 27H оставляет ее резидентной
в памяти.  CS должен указывать  на начало PSP для того, чтобы эта
функция работала правильно. В программах COM, CS сразу устанавли-
вается  соответствующим  образом,  поэтому  надо просто завершить
программу  прерыванием 27H.  В программах EXE , CS  первоначально
указывает на первый байт, следующий  за PSP (т.е. 100H). При нор-
мальном завершении EXE программы последняя инструкция RET  вытал-
кивает из стека  первые  положенные  туда значения: PUSH DX / MOV
AX,0  / PUSH AX.  Поскольку DS первоначально указывает на  начало
PSP, то при получении этих значений  из стека счетчик команд ука-
зывает  на смещение 0 в PSP, где при  инициализации  записывается
инструкция INT 20H. Поэтому INT  20H выполняется, а это стандарт-
ная функция для завершения программы и передачи управления в DOS.
На рис. 1-5 показан этот процесс.  Чтобы заставить прерывание 27H
работать  в EXE программе надо поместить 27H во второй  байт  PSP
(первый содержит машинный код  инструкции INT), а затем завершить
программу обычным RET.  Для обоих типов файлов прежде чем  выпол-
нить прерывание 27H, DX должен  содержать смещение конца програм-
мы, отсчитываемое от начала PSP.

   Средний уровень.

   Вектор прерывания устанавливается с помощью функции 25H преры-
вания 21H, как  показано  в  [1.2.3]  (здесь  используется вектор
70H).   Позаботьтесь,  чтобы процедура оканчивалась IRET.   Кроме
самой процедуры, устанавливаемая программа не должна делать ниче-
го, кроме инициализации вектора прерывания, присвоения DX  значе-
ния смещения конца процедуры и завершения.  Для COM файлов просто
поместите  оператор  INT 27H в конец программы.  Для  EXE  файлов
поместите этот оператор в первое  слово PSP и завершите программу
обычным оператором RET. Для того чтобы выполнить процедуру, впос-
ледствии загруженная программа должна вызвать INT 70H.
   Приведены примеры для обоих типов файлов (COM и EXE).  В обоих
установлена  метка FINISH для отметки конца процедуры  прерывания
(напоминаем, что знак $  дает  значение  счетчика  команд  в этой
точке).  Для COM файлов FINISH дает смещение от начала PSP, как и
требуется для прерывания  27H.  Для  EXE файлов смещение отсчиты-
вается  от первого байта, следующего за PSP, поэтому к нему необ-
ходимо прибавить 100H, чтобы пересчитать  на начало PSP. Заметим,
что  поместив  процедуру в начало программы, мы  можем  исключить
установочную часть кода из  резидентной  порции. Другой возможный
фокус состоит в использовании инструкции MOVSB для пересылки кода
процедуры вниз в  неиспользуемую  часть  PSP, начиная со смещения
60H, что освобождает 160 байт памяти.


   Случай файла COM:
;---здесь процедура прерывания
BEGIN:     JMP   SHORT SET_UP  ;переход на установку
ROUTINE    PROC  FAR
           PUSH  DS            ;сохранение регистров
            .
      (процедура)
            .
           POP   DS            ;восстановление регистров
           IRET                ;возврат из прерывания
FINISH     EQU   $             ;отметка конца процедуры
ROUTINE    ENDP

;---установка вектора прерывания
SET_UP:    MOV   DX,OFFSET ROUTINE  ;смещение процедуры в DX
           MOV   AL,70H             ;номер вектора прерывания
           MOV   AH,25H             ;функция установки вектора
           INT   21H                ;устанавливаем вектор
;---завершение программы, оставляя резидентной
           LEA   DX,FINISH          ;определяем треб. смещение
           INT   27H                ;завершение

   Случай файла EXE:

;---здесь резидентная процедура
           JMP   SHORT SET_UP   ;переход на установку
ROUTINE    PROC  FAR
           PUSH  DS             ;сохранение регистров
            .
       (процедура)
            .
           POP   DS             ;восстановление регистров
           IRET                 ;возврат из прерывания
FINISH     EQU   $              ;отметка конца процедуры
ROUTINE    ENDP

;---установка вектора прерывания
SET_UP:    MOV   DX,OFFSET ROUTINE  ;смещение процедуры в DX
           MOV   AX,SEG ROUTINE     ;сегмент процедуры в DS
           MOV   DS,AX              ;
           MOV   AL,70H             ;номер вектора прерывания
           MOV   AH,25H             ;функция установки вектора
           INT   21H                ;установка вектора
;---завершение программы
           MOV   DX,FINISH+100H     ;вычисляем смещение конца
           MOV   BYTE PTR ES:1,27H  ;посылаем 27H в PSP
           RET                      ;завершаем процедуру

   Функция 31H прерывания 21H работает аналогично, за исключением
того, что в DX  должно  содержаться  число 16-байтных параграфов,
требуемых  процедуре  (вычисление размера процедуры,  начиная  от
начала PSP - см.  в примере [1.3.1]).  Преимуществом этой функции
является  то, что она передает родительской программе код выхода,
дающий информацию о  статусе  процедуры.  Родительская  программа
получает  этот  код с помощью функции 4DH прерывания  21H.   Коды
выхода обсуждаются в [7.2.5].

 

Вы находитесь в разделе: 
Также вам будет интересно:

Добавить коментарий