Методическое пособие для выполнения лабораторных работ и КР (1075934), страница 17
Текст из файла (страница 17)
Кроме того, добавляетсяразмер области PSP и корректировочная константа. Полученное значение нужно разделить на 16 для получения размера в параграфах (16 байт). Причем:- 100h – размер PSP, а0Fh – коррекция при делении нацело (16) для округления целого числа параграфов.Для прерывания 027Н указывается адрес конца резидента как адрес начала частиинициализации (INIT):MOVINTDX, OFFSET INIT027h18.9.
Запуск части инициализацииРезидентная программа обычнооформляется в формате *.COM. Поэтому точка входа должна быть расположена непосредственно после области выделяемой под PSP процесса (ORG 100H). Поэтому точкавхода должна быть помечена в первой строке после предполагаемой области PSP(меткаBEGIN). В директиве конца программы END эта метка также должна быть задана. После2010 год 2 курс 4-й семестр Большаков С.А.“Системное программирование”76запуска программы из командной строки выполняется безусловный переход на меткуинициализации (JMP INIT). Начало резидента может быть оформлено и в виде процедуры(BEGIN PROC … BEGIN ENDP), но это не имеет особого значения, так как в эту процедуру возврат не осуществляется.; Начало резидентаCODEPR SEGMENT PARAASSUME CS:CODEPR , DS:CODEPR; Начало части резидента (Часть 1)ORG 100H ; установка счетчика команд (байт) на 100H для последующей;вставки PSPBEGIN:JPM INIT; это метка начала части инициализации; Определение данных резидента…; Начало части инициализации (Часть 2)INIT:…END BEGIN; Определение точки входа при запуске в командной строкеОбласть данных резидента обычно располагается после этой метки, хотя эти данные можно расположить в любом месте резидентной части (Часть 1 – располагается между метками BEGIN и INIT).18.10.
Определение и запоминание старого обработчикаДля каждого прерывания, которое будет обрабатываться в резиденте, нужно определить и запомнить адрес старого обработчика прерывания. Это делается для того, чтобыпосле завершения работы резидентной программы модно было восстановить старый обработчик и, при необходимости, вызвать его из собственного обработчика для выполнениястандартных действий (например, при обработке прерывания от клавиатуры).
Эти действия могут быть выполнены либо с помощью специально прерывания (35H – 21H) либо спомощью непосредственного обращения в область вектора прерывания (см. ниже).Адрес обработчика считывается в поле длинной в 4 байта (длинный адрес). Нужнопомнить, что двойные слова сохраняются в памяти в обратном порядке (сначала младшееслово – смещение, а затем старшее слово – сегмент).
После обращения к прерыванию035Н ,в регистрах мы получим дальний адрес из вектора прерывания (ES:BX). При этомна AL указывается номер прерывания. Для приведения адресного выражения к слову используется спецификация WORD PTR.; область данных части резидентаOLD_09 dd ?; адрес старого обработчика 09h…; часть инициализации…MOV AH, 35hMOV AL , 09h ; номер обработчикаINT 21hMOV WORD PTR CS:OLD_09, BXMOV WORD PTR CS:OLD_09+2, ESТакие действия необходимо выполнить в программе для каждого обработчика прерывания, задаваемого в программе.18.11. Задание нового обработчика прерыванияДля каждого прерывания, которое обслуживает резидентная программа нужно определить новый обработчик прерывания. Это делается с помощью функции 025h-21h илис помощью непосредственного запись в область вектора прерывания (см.
ниже). В приведенном ниже фрагменте предполагается, что в регистре CS записан адрес сегмента кода2010 год 2 курс 4-й семестр Большаков С.А.“Системное программирование”77программы. Новый обработчик располагается в резидентной части программы. На регистре AL должен быть задан номер нового обработчика прерывания, а на регистре DX смещение обработчика - NEW_09 (для CS). Ниже приведены фрагменты для части резидентной и части инициализации для установки нового прерывания.; часть резидентаNEW_09 PROC…IRETNEW_09 ENDP…; часть инициализацииMOV AH, 25hMOV AL , 09h ; номер прерывания обработчикаLEA DX, NEW_09INT 21h18.12. Вызов старого обработчика прерыванияВызов старого обработчика прерывания может быть выполнен как с помощью безусловного перехода (JMP), так и как перехода с возвратом (CALL).
И первом и во второмслучае адресом вызова должен быть запомненный в резидентной части адрес старого обработчика (например: OLD_09).При безусловном переходе вызов выполняется так:; тело нового обработчика прерывания…; вызов старого обработчика прерывания без возвратаJMP DWORD PTR CS:OLD_09При переходе с возвратом:; тело нового обработчика прерывания…; вызов старого обработчика прерывания с возвратомPUSHF ; !!!!CALL DWORD PTR CS:OLD_09; продолжение тела нового обработчика прерывания…IRETРазличие в этих вызовах заключается, в том числе, в наличии команды PUSHF, запоминающей в стеке регистр флагов. Это необходимо для того, чтобы при выполнениикоманды IRET стек корректно освобождался.
Кроме этого, при вызове без возврата нетнеобходимости задавать команду IRET, так как завершений работы резидента и возврат кпрерванной программе выполняется в старом обработчике.18.13. Пример простейшего резидентаНа основе материала изложенного выше можно построить простейшую резидентную программу. В этой программе не будет некоторых важных возможностей (проверкиповторности, выгрузки резидент, обработки параметров и т.д.), но для простоты понимания задачи пока их опустим.Задача: Написать резидентную программу, которая при нажатии клавиши ESC выводит на экран цепочку одинаковых символов (в программе ‘B’). При загрузке резидентадолжно выдаваться сообщение “Start TSR”.Текст программы такого резидента приведен ниже.;CODEPRСимволы по нажатию ESCSEGMENT PARAASSUME CS:CODEPR , DS:CODEPRORG 100H; Область PSP782010 год 2 курс 4-й семестр Большаков С.А.“Системное программирование”;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Резидентная частьBEGIN:JMPINIT; Переход к части инициализации;Данные резидентаSAVEINT9 DD ?; Сохранение старого обработчика;Новый обработчик прерывания 09НNEWINT9: PUSHAX; Сохранение используемых регистровPUSHCXPUSHBX;Запрос сканкода из клавиатурыINAL, 60H; Взять из порта 60 Н на регистр ALCMPAL, 1; Проверка сканкода ESC он равен 1JNEEXIT;Переход если не ESC;Вывод на экран 10-ти символов ’В’ с помощью BIOS функции 0AH – 010HPUSHAXPUSHBXPUSHCXMOV AH , 0AHMOV AL, 'B'MOV BH , 0MOV CX, 10; Число символовINT 010HPOPCXPOPBXPOPAX; Восстановление регистров и вызов старого обработчика без возвратаEXIT:POPBXPOPCXPOPAXJMPCS:SAVEINT9; Вызов старого обработчика;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Часть инициализацииINIT:CLI; Запрет прерываний; Установка DSPUSH CSPOP DS; Получение адреса старого обработчикаMOVAH, 35HMOVAL, 09H; Номер прерыванияINT 21H; Сохранение адреса старого обработчикаMOVWORD PTR SAVEINT9 , BXMOVWORD PTR SAVEINT9+2 , ES; Установка нового обработчика в вектор прерыванияMOVAH,25HMOVAL, 09H; Номер прерыванияMOVDX, OFFSETNEWINT9INT21H; Вывод сообщения о загрузке резидентаMOV AH , 09HMOV DX, OFFSET MSGINT21H; Завершить и оставить резидентной (TSR)MOVAX, 3100HMOVDX, (init - begin +10FH)/16; Размер резидентаSTI; Разрешение прерыванийINT21H; Данные части инициализацииMSGDB 'Start TSR', 10,13,'$'CODEPRENDSENDBEGIN2010 год 2 курс 4-й семестр Большаков С.А.“Системное программирование”79В данной программе вывод сообщения о старте резидента выводится с помощьюфункции DOS (09Н – 21Н), а вывод цепочки символов с помощью прерывания BIOS (0АН– 10Н), так как использование функций DOS в резидентной части ограничено и практически недопустимо (!!!).Компиляция такой программы (fast.asm) выполняется командным файлом, содержащем следующие директивы:tasm /l /zi fast.asmtlink /v /t /l fast.objPAUSEДиректива PAUSE необходима для контроля наличия ошибок в программе.
Послезапуска резидента при нажатии клавиши ESC на экране будет выведена следующая строка:C:\work>fast.comStart TSR…После нажатия клавиши ESC на экран в командную строку будет выведено:C:\work>\BBBBBBBBBДолжно было быть выведено 10 символов, а на самом деле всего 9. Это объясняется тем, что при нажатии ESC на экран выводиться символ '\', а так как в BIOS прерываниис повторением курсор не перемещается, то символ '\' заменяет первую букву 'В'.Чтобы исправить эту “ошибку” необходимо выполнить полностью обработку прерывания, включая выдачу сигналов клавиатуре о прочитанном символе, а контроллерупрерывания сигнала о завершении обработки прерываний.
Для обработки клавиатурныхпрерываний это существенно. В следующем фрагменте показано, как это сделать.; Сохранение регистров перед выводом на экран цепочкиPUSH AXPUSH BXPUSH CX; Выдача сигнала через порт контроллера 8255 о чтении сканкодаIN AL, 61HOR AL, 10000000b; установим бит 7 порта ВOUT 61H, ALAND AL, 01111111bOUT 61H, AL; сбросим бит 7 порта В (символ прочитан);Вывод цепочки 10 символовMOV AH , 0AHMOV AL, 'B'; символ ’B’MOV BH , 0MOV CX, 10; Число символовINT 010H; прерывание BIOS DOS dghzve. ytkmpzPOP CX; восстановление регитсровPOP BXPOP AX;Сигнал контроллеру прерываний через порт 20Н сигнал (EOI = 20H)MOV AL,20HOUT 20H , AL; в порт ведущего контроллера 8259APOP AXIRET; завершение нового обработчика при вводе ESCВ результате мы получим строку, которая расположена ниже, причем курсор будетрасполагаться в первой позиции, так как 0А-010Н не переводит курсора.:C:\work>BBBBBBBBBBТеперь продолжим рассмотрение других особенностей построения и реализациирезидентных программ.2010 год 2 курс 4-й семестр Большаков С.А.“Системное программирование”8018.14.
Работа с вектором прерываний напрямуюРаботать с вектором прерываний можно напрямую. В реальном режиме доступнався память, достаточно задать длинный адрес (сегмент смещение). Адрес расположениязависит от номера прерывания, достаточно этот номер умножить на 4 и получим необходимое смещение. Значение сегментного регистра (ES) в этом случае должно быть нулевым.
Необходимо также учесть, что в памяти двойное слово по словам располагается вобратном порядке, с начала смещение, а затем сегмент. Текст этих фрагментов программыприведен ниже:Запоминание старого обработчика:MOV AX, 0PUSH AXPOP ESMOV BX, WORDMOV WORD PTRMOV BX, WORDMOV WORD PTR; задание в ES значения 0PTR ES: 09h*4; считаем первое словоCS:OLD_09, BX; замомним его в поле старого обработчикаPTR ES: 09h*4 + 2 ; считаем второе словоCS:OLD_09+2, BX ; замомним его в поле старого обработчикаИ запись нового обработчика:MOV AX, 0PUSH AXPOP ESLEA BX , NEW_09MOV WORD PTR ES: 09h*4, BXMOV BX, СSMOV WORD PTR ES: 09h*4 + 2, BXНесмотря на рассмотренную возможность, более корректно использовать для этихцелей функции 035Н и 025Н прерывания 21Н. Подумайте почему.18.15.