Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

11.3 Примеры простейших резидентных программ




11. 3 Примеры простейших резидентных программ

Примеры простейших резидентных программ типа COM

Следующий пример демонстрирует полностью законченную резидентную программу, которая перехватывает прерывание от клавиатуры (вектор прерывания для клавиатуры под номером 09H) и в программе обработки прерывания вызывает старый обработчик прерывания от клавиатуры.

CODE SEGMENT

ASSUME CS: CODE, DS: CODE

ORG 100H

Start:                           ; начало резидентной части

JMP Init

OLD_VEC DD?             ; значение старого вектора

KbProc PROC                    ; процедура обработки прерывания

PUSHF

CALL CS: OLD_VEC; вызов старого обработчика

IRET                                ; возврат из процедуры

KbProc ENDP

Init:                             ; начало нерезидентной части

MOV BX, 09H * 4; вычисление смещения

XOR AX, AX

MOV ES, AX        ; настройка ES на таблицу

MOV AX, ES: [BX]; векторов прерываний

; сохранение значения старого вектора прерывания

MOV WORD PTR OLD_VEC, AX

MOV AX, ES: [BX + 2]

MOV WORD PTR OLD_VEC + 2, AX

; установка нового значения вектора прерывания

CLI

MOV ES: [BX], OFFSET KbProc

MOV ES: [BX + 2], CS

STI

; завершение программы и загрузка резидентной части

MOV DX, (Init – Start + 10FH) / 16

MOV AH, 31H

MOV AL, 0

INT 21H

CODE ENDS

END Start

 

Перед установкой нового значения вектора прерывания нужно запретить немаскируемые прерывания. Дело в том, что во время установки значения вектора прерывания может возникнуть сигнал прерывания и процессор попытается вызвать обработчик по вектору, значение которого еще до конца не установлено. Это может повлечь за собой непредсказуемые результаты. Поэтому перед установкой значения вектора прерывания всегда нужно ставить команду запрета маскируемых прерываний CLI. По окончании установки значения вектора прерывания нужно разрешить маскируемые прерывания командой STI.

В этом примере нужно обратить внимание на следующие строки:

PUSHF

CALL CS: OLD_VEC

Дело в том, что вызвать старый обработчик через команду INT нельзя, поскольку его вектор прерывания указывает на наш обработчик. Поэтому нужно «смоделировать» работу команды INT, которая помимо занесения в стек значений регистров CS и IP заносит туда еще и значение регистра флагов. Таким образом, перед вызовом дальней процедуры нужно занести в стек значение регистра флагов, чтобы при входе в старый обработчик стек имел такую же структуру, как если бы сначала вызывался старый обработчик при обработке процессором прерывания от клавиатуры.

Пример резидентной программы типа COM с переключением стеков и настройкой регистра DS на сегмент команд:

CODE SEGMENT

ASSUME CS: CODE, DS: CODE

ORG 100H

Start:                           ; начало резидентной части

JMP Init

OLD_VEC DD?             ; значение старого вектора

KbProc PROC                    ; процедура обработки прерывания

PUSHF

CALL CS: OLD_VEC; вызов старого обработчика

MOV CS: OLD_AX, AX   ; сохранение AX

MOV CS: OLD_SS, SS; сохранение SS

MOV CS: OLD_SP, SP; сохранение SP

MOV AX, CS

MOV SS, AX            ; переключение стека

MOV SP, OFFSET Stac + 128       

PUSH DS              ; сохранение DS

PUSH CS

POP DS                 ; настройка DS на CS

POP DS                 ; восстановление DS

MOV AX, CS: OLD_SS

MOV SS, AX            ; восстановление стека

MOV SP, CS: OLD_SP

MOV AX, CS: OLD_AX   ; восстановление AX

IRET                      ; возврат из процедуры

KbProc ENDP

OLD_SS DW?

OLD_SP DW?

OLD_AX DW?

Stac DB 128 DUP (? )

Init:                             ; начало нерезидентной части

MOV BX, 09H * 4; вычисление смещения

XOR AX, AX

MOV ES, AX        ; настройка ES на таблицу

MOV AX, ES: [BX]; векторов прерываний

; сохранение значения старого вектора прерывания

MOV WORD PTR OLD_VEC, AX

MOV AX, ES: [BX + 2]

MOV WORD PTR OLD_VEC + 2, AX

; установка нового значения вектора прерывания

CLI

MOV ES: [BX], OFFSET KbProc

MOV ES: [BX + 2], CS

STI

; завершение программы и загрузка резидентной части

MOV DX, (Init – Start + 10FH) / 16

MOV AH, 31H

MOV AL, 0

INT 21H

CODE ENDS

END Start

 

Последний пример будет использоваться в дальнейшем для добавления к программе типа COM других элементов структуры резидентной программы.

 

Примеры простейших резидентных программы типа EXE

Следующий пример демонстрирует программу типа EXE с раздельными программными сегментами для различных элементов резидентной и нерезидентной частей. Действие программы аналогично первому примеру резидентной COM программы – вызывается старый обработчик прерывания от клавиатуры, переключения стеков не происходит.

Data SEGMENT

OLD_VEC DD?

Data ENDS

 

Resident SEGMENT

ASSUME CS: Resident, DS: Data

KbProc PROC

PUSH DS

PUSH AX

MOV AX, Data

MOV DS, AX

PUSHF

CALL OLD_VEC

POP AX

POP DS

IRET

KbProc ENDP

Resident ENDS

 

Code SEGMENT PARA

ASSUME CS: Code, DS: Data

Start:

MOV AX, Data

MOV DS, AX

MOV BX, 09H * 4; вычисление смещения

XOR AX, AX

MOV ES, AX        ; настройка ES на таблицу

MOV AX, ES: [BX]; векторов прерываний

; сохранение значения старого вектора прерывания

MOV WORD PTR OLD_VEC, AX

MOV AX, ES: [BX + 2]

MOV WORD PTR OLD_VEC + 2, AX

; установка нового значения вектора прерывания

CLI

MOV WORD PTR ES: [BX], OFFSET KbProc

MOV WORD PTR ES: [BX + 2], Resident

STI

; завершение программы и загрузка резидентной части

MOV DX, Code

SUB DX, Data

ADD DX, 10H

MOV AH, 31H

MOV AL, 0

INT 21H

Code ENDS

 

Stac SEGMENT PARA STACK

DB 128 DUP (? )

Stac ENDS

END Start

 

В разделе изменения значения вектора прерывания необходимо указать конструкции «WORD PTR», поскольку смещение процедуры KbProc может быть меньше 256 и тогда значение этого выражения можно записать как в байт, так и в слово; в следующей строке значение выражения Resident неизвестно на этапе трансляции и для него тоже необходимо указать тип.

Следующий пример дополняет предыдущий переключением стека в резидентной части.

Data SEGMENT

DB 32 DUP 0

Data ENDS

 

Stac SEGMENT PARA

DB 128 DUP (? )

Stac ENDS

 

Resident SEGMENT

ASSUME CS: Resident, DS: Data

KbProc PROC

PUSHF

CALL CS: OLD_VEC

MOV CS: OLD_AX, AX   ; сохранение AX

MOV CS: OLD_SS, SS; сохранение SS

MOV CS: OLD_SP, SP; сохранение SP

MOV AX, Stac

MOV SS, AX            ; переключение стека

MOV SP, 128       

PUSH DS              ; сохранение DS

MOV AX, Data

MOV DS, AX       ; настройка DS на сегмент данных

POP DS                 ; восстановление DS

MOV AX, CS: OLD_SS

MOV SS, AX            ; восстановление стека

MOV SP, CS: OLD_SP

MOV AX, CS: OLD_AX   ; восстановление AX

IRET

OLD_SS DW?

OLD_SP DW?

OLD_AX DW?

KbProc ENDP

OLD_VEC DD?

Resident ENDS

 

Code SEGMENT PARA

ASSUME CS: Code, DS: Data

Start:

MOV AX, Data

MOV DS, AX

MOV BX, 09H * 4; вычисление смещения

XOR AX, AX

MOV ES, AX        ; настройка ES на таблицу

MOV AX, ES: [BX]; векторов прерываний

; сохранение значения старого вектора прерывания

MOV WORD PTR OLD_VEC, AX

MOV AX, ES: [BX + 2]

Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...