Глава 3
Команды и алгоритмы
тельно треть этих программ написана в формате.COM (COMMAND.COM, FORMAT.COM; SYS.COM и др.), а две трети - в формате.EXE (FC.EXE, PRINT.EXE, XCOPY.EXE и т.д.). Ниже мы рассмотрим правила составления и особенности исполнения как.ЕХЕ-, так и.СОМ-программ.
Другой критерий классификации программ определяет способ взаимодействия прикладной программы с другими программам и самой DOS. По этому критерию программы делятся на два вида: транзитные и резидентные. Ход выполнения транзитной программы (а к транзитным относится подавляющее большинство приложений DOS) выглядит следующим образом. Пользователь запускает программу, вводя с клавиатуры ее имя, завершаемое нажатием клавиши Enter. Соответствующие программы-компоненты DOS отыскивают на диске файл с указанным именем, загружают его в память и передают управление на входную точку этой программы. Далее программа выполняется, фактически монополизируя ресурсы компьютера. Пока она на завершилась, пользователь не имеет доступа к DOS и, соответственно, лишен возможности запустить другую программу или выполнить какую-либо команду DOS. Ввод с клавиатуры возможен только в ответ на запрос текущей программы, если в ней предусмотрено обращение к клавиатуре за получением каких-либо данных.
Совсем по-другому функционирует резидентная программа. Пользователь запускает се точно так же, как и транзитную, вводя с клавиатуры ее имя. Программы DOS загружают программный файл в память и передают упраштенис на точку входа. Однако дальше вычислительный процесс развивается по-иному. Программа выполняет только свой начальный, инициализирующий фрагмент, после чего вызывает специальную функцию DOS (с номером 31h). Эта функция завершает программу и возвращает управление в DOS, но не освобождает память от завершившейся программы, а остаатяет эту программу в памяти, делая се резидентной. Программа остается в памяти и, можно сказать, ничего не делает. Поскольку управление передано DOS, пользователь может вводить с клавиатуры любые команды и, в частности, запускать другие транзитные (или резидентные) программы. Когда будет активизирована находящаяся в памяти резидентная программа' Как правило, резидентные программы включают в себя обработчики аппаратных или программных прерываний. Если, например, в резидентной программе имеется обработчик прерываний от системного таймера, который, как известно, выдает сигналы прерываний приблизительно 18 раз в секунду, то каждое такое прерывание будет предавать управление резидентной программе, которая может, например, периодически выводить на экран текущее время или какую-то иную информацию. Работа резидентной программы будет протекать независимо от других программ и параллельно с ними. Другим классическим примером резидентной программы является русификатор клавиатуры, который получает управление при нажатии любой клавиши, независимо от того, какая программа сейчас выполняется. Задача русификатора — определить по имеющемуся в нем флагу, на каком языке работает пользователь, и в необходимых случаях сформировать соответствующий нажатой клавише код ASCII русской буквы.
|
Следует заметить, что необходимость в резидентных программах возникла лишь потому, что MS-DOS является существенно однозадачной системой. В многозадачной операционной системе Windows понятие резидентной программы в принципе отсутствует.
|
Разумеется, своими особенностями составления и функционирования обладают и обработчики прерываний — чрезвычайно важный класс программ, обслуживающих многочисленные внешние устройства компьютера — клавиатуру, мышь, магнитные диски и проч., а также нестандартную аппаратуру, если компьютер используется для управления научной установкой или технологическим процессом.
Рассмотрим основные правила составления и функционирования перечисленных типов программ, чтобы в дальнейшем можно было использовать их в примерах, иллюстрирующих те или иные средства языка ассемблера.
Программа типа.ЕХЕ
Характерные особенности программ типа.ЕХЕ подробно рассматри-тись в предыдущих главах. Приведем еще несколько обобщающих сооб-сений. Структура типичной программы на языке ассемблера выглядит тедующим образом.
.586 code segment use 16 assume CS:code, main proc mov AX,data mov DS,AX mov AX,4COOh hit 2 111 main endp code ends data segment use!6 data ends stk segment stack db 256 dup(O) stk ends end main |
разрешение трансляции всех;команд (386-486-Pentium);Начало сегмента команд; 16-разрядное приложение DS:data
; Начало главной процедуры Инициализация;сегментного регистра DS;Текст главной процедуры;Вызов функции DOS;завершения программы;Конец главной процедуры;Конец сегмента команд;Начато сегмента данных;Опрсдсления данных;Конец сегмента данных; Начало сегмента стека;Стек
;Консц сегмента стека;Консц программы и точка входа
Программа начинается с директивы ассемблера.586, разрешающей Использовать в тексте программы весь набор команд процессора Pentium (кроме привилегированных). Если программа будет использовать только базовый набор команд МП 86, указание этой директивы не обязательно.
|
Глава 3
Команды и алгоритмы
С другой стороны, ее указание не обязывает нас обязательно использовать команды Pentium. Если в программе предполагается использовать лишь дополнительные команды процессоров 486 или 386, то вместо.586 можно написать.486 или,386.
Указание любого номера 32-разрядного процессора приведет к тому, что по умолчанию программа будет транслироваться, как 32-разрядное приложение, в то время как нам нужно создать обычное 16-разрядное приложение. Для того, чтобы все адреса в программе рассматривались, как 16-битовые, необходимо придать сегментам команд и данных описатели use 16. Для сегмента стека этот описатель не нужен, так как в стеке
нет поименованных ячеек.
Программа состоит из трех сегментов — команд, данных и стека. Имена сегментов выбраны произвольно. Собственно программа обычно состоит из процедур. Деление на процедуры не обязательно, но повышает ее наглядность и облегчает передачу управления на подпрограммы. В рассматриваемом примере сегмент команд содержит единственную процедуру main, открываемую оператором ргос (от procedure, процедура) и закрываемую оператором endp (end procedure, конец процедуры). Перед обоими операторами указывается имя процедуры, которое в дальнейшем может использоваться в качестве относительного адреса процедуры (в сущности, относительного адреса первого выполнимого предложения этой процедуры). У нас это имя выступает в качестве параметра завершающей программу директивы end. Имена процедур, так же, как и имена сегментов, выбираются произвольно.
Если программа имеет сегмент данных с какими-либо данными, то для того, чтобы к этим данным можно было обратиться, необходимо занести сегментный адрес сегмента данных в один из сегментных регистров. Обычно в качестве такого регистра выбирают DS. Таким образом, предложения, с которых начался текст главной процедуры
mov AX,data Инициализация
mov DS,AX;сегментного регистра DS;
где data — имя, данное сегменту данных, практически являются обязательными для любой программы.
Точно также обязательными являются и завершающие предложения
mov AX,4COOh lut 21h |
;Вызов функции DOS;завершения программы
в которых вызывается функция DOS с номером 4Ch, Эта функция, как уже отмечалось, завершает программу, освобождает занимаемую ею память и передает управление командному процессору COMMAND.COM. Еще два замечания следует сделать относительно процедуры трансляции и компоновки программы, Если сегмент данных расположить после сегмента команд, как это сделано в нашем примере, то у транслятора возникнут сложности при обработке встречающихся в программных пред-
ложениях имен полей данных, так как эти имена еще неизвестны транслятору. Для того, чтобы такие, как говорят, «ссылки вперед» могли правильно обрабатываться, следует в команде вызова транслятора TASM заказать два прохода. Это делается указанием ключа /т.2.
С другой неприятностью мы столкнемся, если попытаемся включить в программу операции с 32-разрядными операндами (даже и с командами МП 86). Компоновщик TASM по умолчанию запрещает такого рода операции. Чтобы преодолеть этот запрет, следует в команде вызова компоновщика указать ключ /3.
Таким образом, приведенный в гл. 1 командный файл должен выглядеть (для подготовки программы P.ASM) следующим образом:
tasm /z /zi /n /nil p,p,P tlink /x /v /3 p,p
Включение указанных описателей и ключей не обязывает нас использовать новые команды или 32-разрядные операнды, так что приведенные выше тексты командного файла и самой программы можно использовать как образец для подготовки всех приведенных в этой книге программных примеров, даже если они используют только средства МП 86. В дальнейших примерах программ, в основном посвященных системе команд МП 86, эти описатели будут опускаться.
Приведем в качестве еще одного примера простую законченную про-
. грамму типа.ЕХЕ, которая выясняет букву-обозначение текущего диска
!.и выводит ее на экран с поясняющей надписью.
;Пример 3-1. Получение текущего диска;Опишем сегмент команд assume CS:codc,DS:data code segment main ргос
AX,data;Настроим DS DS,AX;на сегмент данных mov AH,19h;Функция DOS получения int 2 Hi;текущсго диска add disk,AL Преобразуем номер в код ;ASCII mov AH,09h;Функция DOS вывода на; экран DX,offset rnsg;Адрес строки 21h; Вызов DOS АН,0 Hi;Функция DOS ввода символа 21h;Вызов DOS AX,4C001i;Функция DOS завершения 21h; программы |
mov
mov hit mov int mov int code ends |
mov
Глава з |
;Опишем сегмент данных
data segment use 16
;Выводимый на экран текст Продолжение текста |
msg db "Текущий диск "
disk db "A:",13,10,T
data ends
;Опишем сегмент стека
stk segment stack
:Стек |
db 256 dup (0) stk ends
end main
Рассмотрим текст приведенного примера. После настройки сегментного регистра DS на сегмент данных, вызывается функция DOS с номером 19h, которая позволяет получить код текущего диска. У этой функции нет никаких параметров, а результат своей работы она возвращает в регистре AL в виде условного кода. О обозначает диск А:, 1 диск В:, 2 диск С: и т.д. Если, например, пользователь работает на диске F, то функция I9h вернет в AL код 5.
Для преобразования кода диска в его буквенное обозначение, мы воспользовались широко распространенным приемом. В полях данных определена символьная строка, которая будет выводиться на экран. Для удобства работы она разделена на две части, каждая из которых имеет свое имя. Началу строки присвоено имя msg, а той ее части, которая начинается с обозначения диска А:, имя disk (разумеется, имена выбраны произвольно). Если посмотреть на таблицу кодов ASCII (рис. 3.1), то можно заметить, что код каждой следующей буквы ачфавита на 1 больше предыдущей. Таким образом, если к коду латинской буквы A (41h) прибавить 1, получится код буквы В, а если прибавить, например, 5, получится код буквы F. Именно эта операция и выполняется в предложении
add disk,AL;Преобразусм номер в код ASCII
где к байту с адресом disk прибавляется код, возвращенный функцией DOS.
Выполнив модификацию строки, мы выводим се на экран уже знакомой нам функцией DOS 09h. Она выводит все символы строки, пока не встретится с символом S, которым наша строка и завершается. Перед знаком S в строке имеются два числа: 13 и 10. При выводе текстовой строки на экран любой функцией DOS код 13 трактуется DOS, как команда вернуть курсор в начало строки («возврат каретки»), а код 10 —• как команда на перевод строки. Два эти кода переводят курсор в начало следующей строки экрана. В данном случае, когда на экран ничего больше не выводится, можно было обойтись и без этих кодов, которые включены лишь в познавательных целях.
Между прочим, правильная работа программы основана на том предположении (безусловно правильном), что ассемблер расположит наши данные в памяти в точности в том же порядке, как они описаны в программе. Именно это обстоятельство и позволяет дробить единую строку на
анды и алгоритмы |
АО ВО СО DO ЕО FO |
00 01 02 03 04 05 06 07 08 09 OAOBOCODOEOF
0123456789:;< = >? 0ABCDEFGHIJKLMNO PQRSTUUWX¥Z[4]^_ abcdefghijklnno pqrstuvu х у 2: { I > ~ л
АБВГДЕЖЗИЙКЛМНОП РСТУФХЦЧЫЩЪЫЬЭЮЯ абагдемзий клмноп
h |
_ л _ I? - II
II |
лт |
I I |
Т
т « I t J |
И Р с т
И Ф х цчыщъыьэ w я
«"-=-% ° • • -S № От
Рис. 3.1. Таблица кодов символов.
части, не опасаясь, что в память они попадут в разные места, что привело бы, разумеется, к непредсказуемому результату.
После вывода на экран сообщения о текущем диске в программе вызывается функция DOS с номером Olh. Эта функция вводит с клавиатуры один символ. Если символов нет (мы после запуска программы не нажимали на клавиши), функция Olh ждет нажатия фактически любой клавиши (более точно — любой алфавитно-цифровой или функциональной клавиши). Такой весьма распространенный прием позволяет остановить выполнение программы до нажатия клавиши, что даст возможность программисту посмотреть, что вывела программа на экран, и оценить правильность ее работы.
Наконец, последнее действие носит, как уже отмечалось, сакраментальный характер. Вызовом функции DOS 4Ch программа завершается с передачей управления DOS.
Взглянем еще раз на текст программы 3-1. Если не считать первых предложений инициализации регистра DS, то в программе имеется лишь одна строка, носящая, можно сказать, вычислительный характер — это прибавление полученного кода диска к содержимому байта памяти. Все остальные строки служат для вызова тех или иных функций DOS — получения информации о текущем диске, вывода строки на экран, остановки программы и, наконец, се завершения. Это подтверждает высказанное выше утверждение о важности изучения системных средств и широком использовании их в программах на языке ассемблера. Разумеется, в программе могут быть и сколь угодно сложные и протяженные участки обра-
Глава 3
Команды и алгоритмы
ботки данных и других вычислений, но такие операции, как ввод с клавиатуры, вывод на экран, работа с файлами, получение, как в нашем примере, системной информации и многое другое выполняется исключительно с помощью вызова тех или иных функций DOS (или BIOS). Программу на языке ассемблера просто невозможно написать без использования системных средств.
Структура и образ памяти программы.СОМ
Как уже отмечалось, программа типа.СОМ отличается от программы типа.ЕХЕ тем, что содержит лишь один сегмент, включающий все компоненты программы: PSP, программный код (т.е. оттранслированные в машинные коды программные строки), данные и стек. Структура типичной программы типа.СОМ на языке ассемблера выглядит следующим образом:
code segment;
assume CS:text,DS:text
org lOOh;Мссто для PSP main proc
;Текст программы main endp
;Определения данных code ends
end main.
Программа содержит единственный сегмент code. В операторе ASSUME указано, что сегментные регистры CS и DS будут указывать на этот единственный сегмент. Оператор ORG lOOli резервирует 256 байт для PSP. Заполнять PSP будет по-прежнему система, но место под него в начале сегмента должен отвести программист. В программе нет необходимости инициализировать сегментный регистр DS, поскольку его, как и остальные сегментные регистры, инициализирует система. Данные можно разместить после программной процедуры (как это показано в приведенном примере), или внутри нее, или даже перед ней. Следует только иметь в виду, что при загрузке программы типа.СОМ регистр IP всегда инициализируется числом lOOh, поэтому сразу вслед за оператором ORG lOOli должна стоять первая выполнимая команда программы. Если данные желательно расположить в начале программы, перед ними следует поместить оператор перехода на фактическую точку входа, например jmp entry.
Образ памяти программы типа.СОМ показан на рис. 3.2. После загрузки программы все сегментные регистры указывают на начало единственного сегмента, т.е. фактически на начало PSP. Указатель стека автоматически инициализируется числом FFFEh. Таким образом, независимо от фактического размера программы, ей выделяется 64 Кбайт адресного пространства, всю нижнюю часть которого занимает стек. Поскольку1 верхняя граница стека не определена и зависит от интенсивности и способа использования стека программой, следует опасаться затирания стеком ниж-
ней части программы. Впрочем, такая опасность существует и в программах типа.ЕХЕ, так как в реальном режиме нет никаких механизмов защиты, и при сохранении в стеке большего объема данных, чем может так поместиться, данные начнут затирать поля того сегмента, который расположен над стеком, в наших примерах — сегмента данных.
CS.DS, ES, SS —>
Префикс программы (PSP) 256 байт
• = 010011
Программа и данные
Стек
<— SP = FFFEh
Рис. 3.2. Образ памяти программы.СОМ
Программы типа.СОМ отличаются от.ЕХЕ-программ не только отсутствием сегментов данных и стека. В гл. 2 было показано, что при выравнивании сегментов на байт, что делается с помощью описателя byte
data segment byte
системные программы располагают сегменты загружаемой программы с некоторым перекрытием, что позволяет избежать пустых промежутков между сегментами в памяти, возникающих из-за того, что размеры сегментов могут быть не кратны величине параграфа — 16 байт. Такое расположение сегментов требует изменения значений ссылок на адреса ячеек памяти. В состав программного файла с расширением.ЕХЕ входит таблица с перечнем байтов программы, содержимое которых может подвергнуться изменению в процессе загрузки программы в память. Поэтому, кстати, размер файла с расширением.ЕХЕ может превышать истинный размер программы в памяти.
Программа типа.СОМ состоит из единственного сегмента, и проблема настройки ссылок не возникает. Файл с расширением.СОМ почти в точности отражает содержимое памяти после загрузки программы. Отличие заключается только в том, что в программном файле отсутствует префикс программы PSP, который система вставляет в программу в процессе ее загрузки. Таким образом, файл с расширением.СОМ обычно оказывается на 256 байт короче своего образа в памяти.
Если оттранслировать и скомпоновать программ}', написанную в формате.СОМ, обычным образом, образуется программный файл с расширением.ЕХЕ. Этот файл можно запустить на выполнение, однако.рабо-тать он будет неверно. Дело в том, что система, загружая файл типа.ЕХЕ в память, пристраивает перед загруженной программой префикс и настраивает на него регистры DS и ES. В результате значение DS окажется на 10h меньше, чем сегментный адрес сегмента с командами и данными,
. -Т" _Liaaa_j Команды и алгоритмы |
что приведет к неправильной адресации при обращении к полям данных. Программ)1, написанную в формате.СОМ, можно запускать только в виде файла с расширением.СОМ, для которого в DOS предусмотрен свой алгоритм загрузки и запуска. Для того, чтобы компоновщик создал файл с расширением.СОМ, в строке запуска компоновщика необходимо предусмотреть ключ /t (при использовании компоновщика TLINK.EXE):
tlink /х /v /3 /t p,p
Для того, чтобы избежать ошибок при подготовке программ, целесообразно подготовить два командных файла для трансляции и компоновки программных примеров — один для программ типа.ЕХЕ, и другой для программ типа.СОМ. Разумеется, файлам надо назначить различающиеся имена.
Рассмотрим пример законченной программы типа.СОМ, которая выводит на экран строку текста.
; Место под PSP;Функция вывода на экран |
;Пример 3-2. Простая.СОМ-программа assume CS:code,DS:code code segment
org 256 main proc
mov mov lilt mov int main endp, I msg db 16,16,16,'Программа типа.COM', 17,17,17,'$' code ends end main В начале программы отведено 256 байт под PSP; в программе отсутствует инициализация регистра DS; поле данных размещено в программном сегменте непосредственно после последней команды. Для разнообразия в строку, выводимую на экран, включены коды 16 и 17, которые отображаются на экране в виде залитых треугольников (рис. 3.3). Как видно из этого рисунка, программа имела имя Р. СОМ и запускалась из каталога F:\CURRENT. Рассмотрим важный в принципиальном плане вопрос о месте размещения данных в.СОМ-программе. В нашем примере данные описаны в конце программного сегмента вслед за процедурой main, которая, как и в |
AH,09h
DX,offsct msg
21h
;Функция завершения; про граммы |
AX,4COOh
F:\CURREHT>p.com ^»Программа типа.СОИ 444 |
Рис. 3.3. Вывод программы 3-2. |
21h
предыдущих примерах, введена скорее для порядка, чем по необходимости. С таким же успехом можно было предложение с именем msg поместить после вызова int21h, внутри процедуры main. Третий возможный вариант, с которым мы еще столкнемся в примерах резидентных программ, приведен ниже.
assume CS:code,DS:code code segment
; Место под PSP
org main proc
jmp start;Первая выполнимая команда
msg db 16,16,16,"Программа типа.COM', 17,17,17,'$'
start: mov AH,09h;Функция вывода на экран
mov DX.offset msg
int 21h
;Продолжение программы
Таким образом, данные могут быть размещены как после программы, так И среди выполнимых предложений программы. Важно только соблюсти обязательное условие: ни при каких обстоятельствах на данные не должно быть передано управление. В первом случае (пример 3-2) данные помещены за вызовом функции DOS, завершающей программу. Ясно, что после выполнения этой функции упраштение уже не вернется в нашу программу, а будет передано командному процессору, поэтому размещение здесь данных вполне возможно. В последнем фрагменте данные описаны, можно сказать, в середине программы. Однако перед ними стоит команда безусловного перехода jmp, которая приводит при выполнении программы к обходу данных.
А вот чего нельзя было сделать, так это разместить данные после закрытия сегмента, как это сделано в приведенном ниже (неправильном!) фрагменте:
main cndp;Конец процедуры
code ends;Конец сегмента
msg db 16,16,16,'Программа типа.СОМ', 17,17,17,'$' end main
Это второе обязательное условие: из чего бы ни состояла программа, все ее компоненты должны входить в те или иные сегменты. Вне сегментов допускаются только нетранслируемые директивы ассемблера типа.586 или assume.
Наконец, третье условие, о котором уже говорилось, относится только к программам типа.COM. DOS, загрузив программу в память, инициализирует указатель команд числом lOOh, т.е. адресом первой команды вслед за оператором org lOOh. Поэтому главная процедура.СОМ-програм-мы (если в ней имеется несколько процедур) обязательно должна быть первой, причем первое предложение этой • процедуры должно быть выполнимой командой (например, командой jmp, как это показано выше).
Глава 3
Команды и алгоритмы
Обработчики аппаратных прерываний
Обработчики прерываний являются важнейшей составной частью многих программных продуктов. Как было показано в гл. 1, прерывания разделяются на внутренние, возникающие в самом микропроцессоре в случае определенных сбоев (попытка деления на 0, несуществующая команда), внешние, приходящие из периферийного оборудования (клавиатура, мышь, диски, нестандартные устройства, подключенные к компьютеру) и программные, являющиеся реакцией процессора на команду int с тем или иным номером. В прикладных программах приходится обрабатывать, главным образом, внешние и программные прерывания. Общие принципы обслуживания тех и других прерываний одинаковы, однако условия функционирования обработчиков аппаратных прерываний имеют значительную специфику, связанную, главным образом, с тем, что прерывания от аппаратуры приходят в произвольные моменты времени и могут прервать текущую программу в любой ее точке. Обработчик прерывания должен быть написан таким образом, чтобы его выполнение ни в какой степени не отразилось на правильном функционировании текущей (прерываемой) программы.
Инициализация обработчика прерываний |
Прерывание 1 Прерывание 2 |
Рассмотрим схематически структуру и функционирование программного комплекса, включающего собственный обработчик какого-либо аппаратного прерывания (рис. 3.4).
Дальнейший ход программы
Обработчик прерываний
Рис. 3.4. Функционирование программного комплекса с обработчиком прерываний.
Обработчик прерываний может входить в состав программы в виде процедуры, или просто являться частью программы, начинающейся с некоторой метки (входной точки обработчика) и завершающейся командой выхода из прерывания irct. Пока мы не будем рассматривать более
сложный случай, когда обработчик представляет собой самостоятельную резидентную программу.
Программа, начиная свою работу, прежде всего должна выполнить инициализирующие действия по установке обработчика прерываний. В простейшем случае эти действия заключаются в занесении в соответствующий вектор полного адреса (сегмента и смещения) обработчика. Поскольку обработчик входит в состав программы, его относительный адрес известен; это имя его процедуры или метка входной точки. Что же касается сегментного адреса, то обработчик может входить в сегмент основной части программы, если она невелика по объему и занимает один сегмент, но может образовывать и самостоятельный сегмент. В любом случае в качестве сегментного адреса можно использовать имя соответствующего сегмента.
Часто инициализация обработчика, помимо установки вектора, предполагает и другие действия: сохранение исходного содержимого вектора прерывания, размаскирование соответствующего уровня прерываний в контроллере прерываний, посылка в устройство команды разрешения прерываний и проч.
Установив обработчик, программа может приступить к дальнейшей работе. В случае прихода прерывания, процессор сохраняет в стеке флаги и текущий адрес программы, извлекает из вектора адрес обработчика и передает управление на его входную точку. Все время, пока выполняется программа обработчика, основная программа, естественно, стоит. Завершающая обработчик команда iret извлекает из стека сохраненные там данные и возвращает управление в прерванную программу, которая может продолжить свою работу. Последующие прерывания обслуживаются точно так же.
Функции обработчика прерываний зависят от решаемой задачи и назначения того устройства, от которого поступают сигналы прерываний. В случае прерываний от клавиатуры задача обработчика прерываний — принять и сохранить код нажатой клавиши. Прерывания от мыши свидетельствуют о ее перемещении, что требует обновления положения курсора на экране. Если обслуживаемым устройством является физическая установка, то сигнал прерывания может говорить о том, что в установке накоплен определенный объем данных, которые надо перенести из памяти ус-, тановки в память компьютера. В любом случае обработчик прерываний должен быть программой несложной, для выполнения которой не требуется много машинного времени.
Рассмотрим структуру программы с обработкой аппаратных прерыва-шй. Наиболее удобным аппаратным прерыванием, которое можно ис-юльзовать в исследовательских целях, является прерывание от систем йота и мера, которое генерируется 18.2 раза в секунду и служит источни-)м сигналов для хода системных часов, отсчитывающих время, истекшее юсле включения машины. Замена системного обработчика на приклад-сой не приводит к каким-либо неприятностям, кроме, возможно, оста-совки на некоторое время системных часов.