Жанр: Учеба
Справочник программиста на IBM PC
...е 14H в порт с адресом 70H, а затем
прочитайте содержимое регистра через порт 71H. Вот значение битов
этого регистра:
биты 7-6 00 = 1 НГМД, 01 = 2 НГМД
5-4 01 = вывод на цветной дисплей, 40 строк
10 = вывод на цветной дисплей, 80 строк
11 = вывод на монохромный дисплей
3-2 не используется
1 1 = имеется мат. сопроцессор
0 0 = нет НГМД, 1 = имеется НГМД
Высокий уровень.
В Бейсике нужно просто прочитать байты статуса из области
данных BIOS. В приложении Б объяснено выполнение битовых операций
в Бейсике. В приведенном примере проверка наличия дисковых накопителей
достигается проверкой четности младшего байта статусного
регистра (четный - нет накопителей).
100 DEF SEG = 0 'указывыаем на дно памяти
110 X = PEEK(&H410) 'получаем младший байт регистра
120 IF X MOD 2 = 0 THEN 140 'он четный - нет накопителей
130 PRINT "Имеется диск" 'иначе имеется накопитель
140 GOTO 160 'идем ко второму сообщению
150 PRINT "Нет накопителей" 'второе сообщение
160 ... 'продолжаем...
Проверка наличия COM1:
100 DEF SEG = 40H 'указываем на область данных BIOS
110 PORT = PEEK(0) + 256*PEEK(1) 'получаем слово со смещением 0
120 IF PORT = 0 THEN... '... то нет адаптера COM1
Средний уровень.
Прерывание 11H BIOS возвращает байт статуса оборудования в AX.
На входе ничего подавать не надо. В примере определяется число
дисковых накопителей.
; ---получение числа дисковых накопителей:
INT 11H ;получаем байт статуса
TEST AL,0 ;имеются накопители?
JZ NO_DRIVES ;переход, если нет
AND AL,1100000B ;выделяем биты 5-6
MOV CL,5 ;подготовка к сдвигу регистра
SHR AL,CL ;сдвиг вправо на 5 битов
INC AL ;добавляем 1, т.к. отсчет идет с 1
Низкий уровень.
Ассемблерная программа работает так же, как и программа на
Бейсике. В примере читается информация о конфигурации для AT,
определяя установлен ли математический сопроцессор:
MOV AL,14H ;номер регистра
OUT 70H,AL ;посылаем запрос
IN AL,71H ;читаем регистр
TEST AL,10B ;проверяем бит 1
JZ NO_COPROCESSOR ;если не установлен, то сопроцессора нет
1.1.7 Ревизия количества памяти.
Вопрос: "Сколько имеется памяти?",- может иметь три смысла.
О каком количестве памяти сообщают переключатели, установленные
на системной плате? Сколько микросхем памяти реально установлено
в машине? И, наконец, сколько остается свободной памяти, которую
DOS может использовать для выполнения Ваших программ? Машина
может иметь 10 банков памяти по 64K, но переключатели могут указывать
на наличие только 320K, оставляя половину памяти для каких-либо
специальных целей. А как может Ваша программа узнать,
сколько из доступных 320K она может использовать, учитывая, что
другое программное обеспечение может быть загружено резидентным в
верхнюю или нижнюю часть памяти?
Ответ на каждый вопрос можно получить своим способом. Для PC и
XT установка переключателей может быть просто прочитана через
порт B микросхемы интерфейса с периферией 8255. В пункте [1.1.1]
описано как это делается. BIOS хранит двухбайтную переменную по
адресу 0040:0013, которая сообщает число килобайт используемой
памяти. Для PCjr бит 3 порта 62H (порт C микросхемы 8255) равен
нулю, когда машина имеет добавочные 64K памяти. AT дает особо
полную информацию о памяти. Регистры 15H (младший) и 16H (старший)
микросхемы информации о конфигурации говорят сколько памяти
установлено на системной плате (возможны три значения: 0100H -
для 256K, 0200H - для 512K и 0280H для 512K плюс 128K на плате
расширения). Память канала ввода/вывода для AT сообщается регистрами
17H и 18H (с инкрементом 512K). Память сверх 1 мегабайта
доступна через регистры 30H и 31H (опять с инкрементом 512K,
вплоть до 15 мегабайт). Если AT имеет 128K на плате расширения,
то установлен бит 7 регистра 33. Во всех случаях надо сначала
послать номер регистра в порт 70H, а затем прочитать значение из
порта 71H.
Легко написать программу, которая прямо тестирует наличие
памяти через определенные интервалы адресного пространства. Поскольку
минимальная порция памяти 16 килобайт, то достаточно проверить
одну ячейку памяти в каждом 16-килобайтном сегменте, чтобы
убедиться, что все 16K присутствуют. Когда данная ячейка памяти
отсутствует, то при чтении из нее получаем значение 233. Для
проверки можно записать в ячейку произвольное число, отличное от
233 и сразу же считать его. Если вместо посланного числа возвращается
233, то соответствующий банк памяти отсутствует. Не применяйте
этот способ на AT, где при попытке писать в несуществующую
память вступает в действие встроенная обработка несуществующей
памяти. Диагностика AT настолько хороша, что Вы можете целиком
положиться на системную информацию о конфигурации.
Память постоянно занимается частями операционной системы,
драйверами устройств, резидентными программами обработки прерываний
и управляющими блоками MS DOS. При проверке банков памяти Вы
не должны вносить необратимых изменений в содержимое памяти.
Сначала надо сохранить значение, хранящееся в тестируемой ячейке,
затем проверить ее и восстановить первоначальное значение.
Имеется еще одна проблема. Если Ваша процедура хотя бы временно
модифицирует свой код, то это может привести к краху. Поэтому
для проверки надо выбирать такую ячейку из блока 64K, которая не
будет занята текстом Вашей процедуры. Для этого поместите процедуру
тестирования впереди программы, а для тестирования выберите
ячейку со смещением равным смещению для кодового сегмента. Например,
если регистр кодового сегмента содержит 13E2, то сегмент
начинается со смещения 13E2 во втором 64K-байтном блоке памяти.
Поскольку Ваша подпрограмма проверки не может находиться по этому
адресу, то Вы можете безопасно проверять значение 3E2 в каждом
блоке. Запрет прерываний [1.2.2] позволяет не беспокоиться о
модификации кода из-за аппаратных прерываний, которые могут
происходить во время проверки.
Определение количества памяти реально доступной операционной
системе также требует некоторого фокуса. Когда программа первый
раз получает управление, то DOS отводит ей всю доступную память,
включая верхнюю область памяти, содержащую нерезидентную часть
DOS (которая автоматически перезагружается, если она была модифицирована).
Для запуска другой программы из текущей или для того,
чтобы сделать программу подходящей для многопользовательсой системы,
необходимо урезать программу до требуемого размера. В пункте
[1.3.1] описано как это сделать с помощью функции 4AH прерывания
21H.
Эта же функция может быть использована для расширения отведенной
памяти. Поскольку программе отводится вся доступная память
при загрузке, то такое расширение невозможно при старте. Если Вы
попробуете сделать это, то будет установлен флаг переноса, в
регистре AX появится код ошибки 8, а в регистре BX будет возвращено
максимальное число доступных 16-байтных параграфов. Эта
информация как раз и нужна. Значит надо выдать запрос со слишком
большим значением в регистре BX ( скажем, F000H параграфов), а
затем выполните прерывание. Позаботьтесь о том, чтобы выполнить
эту функцию в самом начале программы, пока регистр ES еще имеет
начальное значение.
Высокий уровень.
Интерпретатор Бейсика использует только 64K (хотя операторы
PEEK и POKE позволяют доступ к памяти за пределами 64K). Доля
памяти доступная в настоящий момент возвращается функцией FRE.
Эта функция имеет фиктивный аргумент, который может быть числовым
или символьной строкой. BYTES = FRE(x) передает в BYTES число
свободных байтов. BYTES = FRE(x$) делает то же самое. Но строковый
аргумент вынуждает очистку области данных перед тем как возвратить
число байтов. Заметим, что если размер рабочей области
устанавливается с помощью оператора CLEAR, то количество памяти,
сообщаемое функцией FRE будет на от 2.5 до 4 килобайт меньше
из-за потребностей рабочей области интерпретатора.
Транслятор Бейсика не накладывает ограничение 64K на суммарный
объем кода и данных. Но сам компилятор ограничен тем количеством
памяти, которое он может использовать при компиляции. Если этого
пространства недостаточно, то уничтожьте все ненужные номера
строк при помощи ключа компиляции /N. Можно также использовать
более короткие имена переменных.
Средний уровень.
Прерывание 12H BIOS проверяет установку переключателей и возвращает
в AX количество килобайт памяти в системе. Эта величина
вычисляется из установки регистров микросхемы 8255 или, для AT,
микросхемы конфигурации/часов. Входных регистров нет. Имейте
ввиду, что установка переключателей может быть неверной, что
ограничивает достоверность такого подхода.
Для определения числа 16-байтных параграфов, доступных для
DOS, используйте функцию 4AH прерывания 21H. ES должен иметь то
же значение, что при старте задачи:
;---определение числа параграфов доступных для DOS
MOV AH,4AH ;указываем нужную функцию
MOV BX,0FFFFH ;требуем слишком большую память
INT 21H ;BX содержит число доступных параграфов
AT использует функцию 88H прерывания 15H для проверки наличия
расширенной памяти, которая ищет память вне адресного пространства
процессора в обычном режиме адресации. Говорят, что она ищет
память за отметкой 1 мегабайта. При этом на системной плате должно
быть от 512 до 640 килобайт памяти, чтобы эта функция работала.
Число килобайтных блоков расширенной памяти возвращается в
AX.
Низкий уровень.
Первый пример проверяет число банков памяти по 64K в первых
десяти 64-килобайтных сегментах памяти. Если Вы будете проверять
старшие 6 банков памяти, то имейте ввиду, что имеются видеобуфер,
начиная с B000:0000 (и, возможно, A000:0000) и ПЗУ, начиная с
F000:0000 (и, возможно, C000:0000).
;---проверка каждого банка памяти:
CLI ;запрет аппаратных прерываний
MOV AX,CS ;получаем значение кодового сегмента
AND AX,0FFFH ;сбрасываем старшие 4 бита
MOV ES,AX ;помещаем указатель в ES
MOV DI,0 ;DI считает число банков памяти
MOV CX,10 ;будем проверять 10 банков
MOV BL,'X' ;для проверки используем 'X'
NEXT:
MOV DL,ES:[0] ;сохраняем значение тестируемой ячейки
MOV ES:[0],BL ;помещаем 'X' в эту ячейку
MOV DH,ES:[0] ;читаем тестируемую ячейку
MOV ES:[0],DL ;восстанавливаем значение
CMP DH,'X' ;совпадает с тем, что писали?
JNE GO_AHEAD ;если нет, то банк отсутствует
INC DI ;увеличиваем число банков
GO_AHEAD:
MOV AX,ES ;готовим увеличение указателя
ADD AX,1000H ;указываем на следующие 64K
MOV ES,AX ;возвращаем указатель в ES
LOOP NEXT ;обрабатываем следующий банк
STI ;разрешаем аппаратные прерывания
Раздел 2. Управление прерываниями.
Прерывания это готовые процедуры, которые компьютер вызывает
для выполнения определенной задачи. Существуют аппаратные и программные
прерывания. Аппаратные прерывания инициируются аппаратурой,
либо с системной платы, либо с карты расширения. Они могут
быть вызваны сигналом микросхемы таймера, сигналом от принтера,
нажатием клавиши на клавиатуре и множеством других причин. Аппаратные
прерывания не координируются с работой программного обеспечения.
Когда вызывается прерывание, то процессор оставляет свою
работу, выполняет прерывание, а затем возвращается на прежнее
место. Для того чтобы иметь возможность вернуться точно в нужное
место программы, адрес этого места (CS:IP) запоминается на стеке,
вместе с регистром флагов. Затем в CS:IP загружается адрес программы
обработки прерывания и ей передается управление. Программы
обработки прерываний иногда называют драйверами прерываний. Они
всегда завершаются инструкцией IRET (возврат из прерывания),
которая завершает процесс, начатый прерыванием, возвращая старые
значения CS:IP и регистра флагов, тем самым давая программе возможность
продолжить выполнение из того же состояния.
С другой стороны, программные прерывания на самом деле ничего
не прерывают. На самом деле это обычные процедуры, которые вызываются
Вашими программами для выполнения рутинной работы, такой
как прием нажатия клавиши на клавиатуре или вывод на экран. Однако
эти подпрограммы содержатся не внутри Вашей программы, а в
операционной системе и механизм прерываний дает Вам возможность
обратиться к ним. Программные прерывания могут вызываться друг из
друга. Например, все прерывания обработки ввода с клавиатуры DOS
используют прерывания обработки ввода с клавиатуры BIOS для получения
символа из буфера клавиатуры. Отметим, что аппаратное прерываение
может получить управление при выполнении программного
прерывания. При этом не возникает конфликтов, так как каждая
подпрограмма обработки прерывания сохраняет значения всех используемых
ею регистров и затем восстанавливает их при выходе, тем
самым не оставляя следов того, что она занимала процессор.
Адреса программ прерываний называют векторами. Каждый вектор
имеет длину четыре байта. В первом слове хранится значение IP, а
во втором - CS. Младшие 1024 байт памяти содержат вектора прерываний,
таким образом имеется место для 256 векторов. Вместе взятые
они называются таблицей векторов. Вектор для прерывания 0
начинается с ячейки 0000:0000, прерывания 1 - с 0000:0004, 2 - с
0000:0008 и т.д. Если посмотреть на четыре байта, начиная с адреса
0000:0020, в которых содержится вектор прерывания 8H (прерывание
времени суток), то Вы обнаружите там A5FE00F0. Имея ввиду,
что младший байт слова расположен сначала и что порядок IP:CS,
это 4-байтное значение переводится в F000:FEA5. Это стартовый
адрес программы ПЗУ, выполняющей прерывание 8H. На рис. 1-2 показана
схема выполнения программой прерывания 21H.
1.2.1 Программирование контроллера прерываний 8259.
Для управления аппаратными прерываниями во всех типах IBM PC
используется микросхема программируемого контроллера прерываний
Intel 8259. Поскольку в ккаждый момент времени может поступить не
один запрос, микросхема имеет схему приоритетов. Имеется 8 уровней
приоритетов, кроме AT, у которого их 16, и обращения к соответствующим
уровням обозначаются сокращениями от IRQ0 до IRQ7 (от
IRQ0 до IRQ15), что означает запрос на прерывание. Максимальный
приоритет соответствует уровню 0. Добавочные 8 уровней для AT
обрабатываются второй микросхемой 8259; этот второй набор уровней
имеет приоритет между IRQ2 и IRQ3. Запросы на прерывание 0-7
соответствуют векторам прерываний от 8H до 0FH; для AT запросы на
прерывания 8-15 обслуживаются векторами от 70H до 77H. Ниже приведены
назначения этих прерываний:
Аппаратные прерывания в порядке приоритета.
IRQ 0 таймер
1 клавиатура
2 канал ввода/вывода
8 часы реального времени (только AT)
9 программно переводятся в IRQ2 (только AT)
10 резерв
11 резерв
12 резерв
13 мат. сопроцессор (только AT)
14 контроллер фиксированного диска (только AT)
15 резерв
3 COM1 (COM2 для AT)
4 COM2 (модем для PCjr, COM1 для AT)
5 фиксированный диск (LPT2 для AT)
6 контроллер дискет
7 LPT1
Прерыванию времени суток [2.1.0] дан максимальный приоритет,
поскольку если оно будет постоянно теряться, то будут неверными
показания системных часов. Прерывание от клавиатуры [3.1.0] вызывается
при нажатии или отпускании клавиши; оно вызывает цепь
событий, которая обычно заканчивается тем, что код клавиши помещается
в буфер клавиатуры (откуда он затем может быть получен
программными прерываниями).
Микросхема 8259 имеет три однобайтных регистра, которые управляют
восемью линиями аппаратных прерываний. Регистр запроса на
прерывание (IRR) устанавливает соответствующий бит, когда линия
прерывания сигнализирует о запросе. Затем микросхема автоматически
проверяет не обрабатывается ли другое прерывание. При этом она
запрашивает информацию регистра обслуживания (ISR). Дополнительная
цепь отвечает за схему приоритетов. Наконец, перед вызовом
прерывания, проверяется регистр маски прерываний (IMR), чтобы
узнать разрешено ли в данный момент прерывание данного уровня.
Как правило программисты обращаются только к регистру маски прерываний
через порт 21H [1.2.2] и командному регистру прерываний
через порт 20H [1.2.3].
1.2.2 Запрет/разрешение отдельных аппаратных прерываний.
Программы на аасемблере могут запретить аппаратные прерывания,
перечисленные в [1.2.1]. Это маскируемые прерывания; другие аппаратные
прерывания, возникающие при некоторых ошибках (таких как
деление на ноль) не могут быть маскированы. Имеются две причины
для запрета аппаратных прерываний. В первом случае все прерывания
блокируются с тем чтобы критическая часть кода была выполнена
целиком, прежде чем машина произведет какое-либо другое действие.
Например, прерывания запрещают при изменении вектора аппаратного
прерывания, избегая выполнения прерывания когда вектор изменен
только наполовину.
Во втором случае маскируются только определенные аппаратные
прерывания. Это делается когда некоторые определенные прерывания
могут взаимодействовать с операциями, критичными к временам.
Например, точно рассчитанная по времени процедура ввода/вывода не
может себе позволить быть прерванной длительным дисковым прерыванием.
Низкий уровень.
Выполнение прерываний зависит от значения флага прерывания
(бит 9) в регистре флагов. Когда этот бит равен 0, то разрешены
все прерывания, которые разрешает маска. Когда он равен 1, то все
аппаратные прерывания запрещены. Чтобы запретить прерывания,
установив этот флаг в 1, используется инструкция CLI. Для очистки
этого флага и восстановления прерываний - инструкция STI. Избегайте
отключения прерываний на длительный период. Прерывание
времени суток происходит 18.2 раза в секунду и если к этому прерыванию
был более чем один запрос в то время, когда аппаратные
прерывания были запрещены, то лишние запросы будут отброшены и
системное время будет определяться неправильно.
Имейте ввиду, что машина автоматически запрещает аппаратные
прерывания при вызове программных прерываний и автоматически
разрешает их при возврате. Когда Вы пишете свои программные прерывания,
то Вы можете начать программу с инструкции STI, если Вы
можете допустить аппаратные прерывания. Отметим также, что если
за инструкцией CLI не следует STI, то это приведет к остановке
машины, так как ввод с клавиатуры будет заморожен.
Для маскирования определенных аппаратных прерываний нужно
просто послать требуемую цепочку битов в порт с адресом 21H,
который соответствует регистру маски прерываний (IMR). Регистр
маски на второй микросхеме 8259 для AT (IRQ8-15) имеет адрес
порта A1H. Установите те биты регистра, которые соответствуют
номерам прерываний, которые Вы хотите маскировать. Этот регистр
можно только записывать. Нижеприведенный пример блокирует дисковое
прерывание. Не забудьте очистить регистр в конце программы,
иначе обращение к дискам будет запрещено и после завершения программы.
;---маскирование 6-го бита регистра маски прерываний
MOV AL,01000000B ;маскируем бит 6
OUT 21H,AL ;посылаем в регистр маски прерываний
MOV AL,0 ;
OUT 21H,AL ;очищаем IMR в конце программы
1.2.3 Написание собственного прерывания.
Имеется несколько причин для написания собственного прерывания.
Во-первых, большинство из готовых прерываний, обеспечиваемых
операционной системой, ничто иное, как обычные процедуры, доступные
для всех программ, и Вы можете пожелать добавить свое в эту
библиотеку. Например, многие Ваши программы могут использовать
процедуру, выводящую строки на экран вертикально. Вместо того,
чтобы включать ее в каждую программу в качестве процедуры Вы
можете установить ее как прерывание, написав программу, которая
останется резидентной в памяти после завершения [1.3.4]. Тогда Вы
можете использовать INT 80H вместо WRITE_VERTICALLY (имейте ввиду,
что вызов прерывания несколько медленней, чем вызов процедуры).
Второй причиной написания прерывания может быть использование
какого-либо отдельного аппаратного прерывания. Это прерывание
автоматически вызывается при возникновении определенных условий.
В некоторых случаях BIOS инициализирует вектор этого прерывания
так, что он указывает на процедуру, которая вообще ничего не
делает (она содержит один оператор IRET). Вы можете написать свою
процедуру и изменить вектор прерываний, чтобы он указывал на нее.
Тогда при возникновении аппаратного прерывания будет выполняться
Ваша процедура. Одна из таких процедур это прерывание времени
суток [2.1.0], которое автоматически вызывается 18.2 раза в секунду.
Обычно это прерывание только обновляет показание часов, но
Вы можете добавить к нему любой код, который Вы пожелаете. Если
Ваш код проверяет показания часов и вступает в игру в определенные
моменты времени, то возможны операции в реальном времени.
Другие возможности - это написание процедур обработки Ctrl-Break
[3.2.8], PrtSC [3.2.9] и возникновения ошибочных ситуаций
[7.2.5]. Прерывания принтера [6.3.1] и коммуникационные [7.1.8]
позволяют компьютеру быстро переключаться между операциями ввода/вывода
и другой обработкой.
Наконец, Вы можете захотеть написать прерывание, которое полностью
заменит одну из процедур операционной системы, приспособленное
к Вашим программным нуждам. В [1.2.4] показано как написать
прерывание внутри прерывания, которое позволяет Вам модифицировать
существующие процедуры.
Средний уровень.
Функция 25H прерывания 21H устанавливает вектор прерывания на
указанный адрес. Адреса имеют размер два слова. Старшее слово
содержит значение сегмента (CS), младшее содержит смещение (IP).
Чтобы установить вектор, указывающим на одну из Ваших процедур,
нужно поместить сегмент процедуры в DS, а смещение в DX (следуя
порядку нижеприведенного примера). Затем поместите номер прерывания
в AL и вызовите функцию. Любая процедура прерывания должна
завершаться не обычной инструкцией RET, а IRET. (IRET выталкивает
из стека три слова, включая регистр флагов, в то время как RET
помещает на стек только два. Если Вы попытаетесь тестировать
такую процедуру как обычную процедуру, но кончающуюся IRET, то Вы
исчерпаете стек.) Отметим, что функция 25H автоматически запрещает
аппаратные прерывания в процессе изменения вектора, поэтому
не существует опасности, что посреди дороги произойдет аппаратное
прерывание, использующее данный вектор.
;---установка прерывания
PUSH DS ;сохраняем DS
MOV DX,OFFSET ROUT ;смещение для процедуры в DX
MOV AX,SEG ROUT ;сегмент процедуры
MOV DS,AX ;помещаем в DS
MOV AH,25H ;функция установки вектора
MOV AL,60H ;номер вектора
INT 21H ;меняем прерывание
POP DS ;восстанавливаем DS
;---процедура прерывания
ROUT PROC FAR
PUSH AX ;сохраняем все изменяемые регистры
POP AX ;восстанавливаем регистры
MOV AL,20H ;эти две строки надо использовать
OUT 20H,AL ;только для аппаратных прерываний
IRET
ROUT ENDP
В конце кода каждого из Ваших аппаратных прерываний Вы должны
включить следующие 2 строчки кода:
MOV AL,20H
OUT 20H,AL
Это просто совпадение, что числа (20H) одни и те же в обеих
строках. Если аппаратное прерывание не заканчивается этими строками,
то микросхема 8259 не очистит информацию регистра обслуживания,
с тем чтобы была разрешена обработка прерываний с более
низкими уровнями, чем только что обработанное. Отсутствие этих
строк легко может привести к краху программы, так как прерывания
от клавиатуры скорее всего окажутся замороженными и даже
Ctrl-Alt-Del окажется бесполезным. Отметим, что эта добавка не
нужна для тех векторов прерываний, которые являются расширениями
существующих прерываний, таким как прерывание 1CH, которое добавляет
код к прерыванию времени суток [2.1.7].
Когда программа завершается, должны быть восстановлены оригинальные
вектора прерываний. В противном случае последующая программа
может вызвать данное прерывание и передать управление на то
место в памяти, в котором Вашей процедуры уже нет. Функция 35
прерывания 21H возвращает текущее значение вектора прерывания,
помещая значение сегмента в ES, а смещение в BX. Перед установкой
своего прерывания получите текущее значение вектора, используя
эту функцию, сохраните эти значения, и затем восстановите их с
помощью функции 25H (как выше) перед завершением своей программы.
Например:
;---в сегменте данных:
KEEP_CS DW 0 ;хранит сегмент заменяемого прерывания
KEEP_IP DW 0 ;хранит смещение прерывания
;---в начале программы
MOV AH,25H ;функция получения вектора
MOV AL,1CH ;номер вектора
INT 21H ;теперь сегмент в ES, смещение в BX
MOV KEEP_IP,BX ;запоминаем смещение
MOV KEEP_CS,ES ;запоминаем сегмент
; ---в конце программы
CLI
PUSH DS ;DS будет разрушен
MOV DX,KEEP_IP ;подготовка к восстановлению
MOV AX,KEEP_CS ;
MOV DS,AX ;подготовка к восстановлению
MOV AH,25H ;функция установки вектора
MOV AL,1CH ;номер вектора
INT 21H ;восстанавливаем вектор
POP DS ;восстанавливаем DS
STI
Имеется пара ловушек, которых следует избегать при написании
прерывания. Если новая процеду
...Поділитися у соцмережах