Optron
#35
25 апреля 2000 |
|
Ликбез - Прерывания в ZX Spectrum.
Ассемблер - взгляд издалека Продолжение. Начало в || 20, 21, 24, 25, 28-30, 32, 33 {}Инфарх, 2000 Привет, энтузиасты! Что, небось заскуча- ли на каникулах? Ничего, сейчас продолжим. На этот раз мы с вами поговорим о работе с прерываниями. Для начала уясним, что это такое. Итак... Прерывания Вы, может, и не подозреваете, что 50 раз в секунду процессор отвлекается от обра- ботки вашей программы и занимается неиз- вестно чем... Например, опрашивает клавиа- туру, изменяет значение системной перемен- ной FRAMES и т.д. Причём, делает это так, что вы об этом и не догадываетесь. В эти моменты происходит следующее: процессор обращается к подпрограме по адресу 56, как будто выполняет команду RST 56 или CALL 56. Отличие в том, что переход осу- ществляется не программно, а аппаратно. Завершив выполнение вызванной процедуры, процессор продолжает выполнять основную программу. На первый взгляд может показаться, что от такой "фишки" проку никакого, ведь программно в ПЗУ ничего не изменишь. К счастью, программист имеет возможность по- менять адрес, по которому расположена про- цедура обработки прерываний. Для этого ис- пользуется упомянутый ранее регистр I. Прежде всего, надо запомнить, что имеет- ся три режима обработки прерываний. Они обозначаются соответственно цифрами от 0 до 2. Стандартный режим - 1. Именно его эксплуатирует операционная систама. Нуле- вой режим нам не особенно интересен: на практике он ничем не отличается от перво- го. Заметьте, именно на практике! Разли- чия, конечно, есть, да только в Спектруме они не реализованы. Таким образом, самым интересным для нас является режим 2. Для начала пару слов о том, как он рабо- тает и что в этот момент в компьютере тво- рится. Когда приходит сигнал прерывания, процессор, для начала, определяет адрес указателя на процедуру обработки прерыва- ний. Оный состоит из двух байт: младшего, считанного с шины данных (его также имену- ют "вектор прерываний"), и старшего, счи- танного с регистра I. Полученное значение помещается на шину адреса, а предыдущее её содержимое сохраняется на стеке. Всё это, в сущности, является вариантом вызова подпрограммы. "Но что означает этот термин - "вектор прерываний"?" - спросите вы. Дело в том, что термин этот связан с работой компьюте- ров, в которых предусмотрена возможность поступления нескольких запросов на преры- вание ОДНОВРЕМЕННО. Естественно, в этой ситуации необходимо определиться, какое из прерываний имеет приоритет. А это значит, что запрос на прерывание следует рассмат- ривать как "вектор", который, как и всякий порядочный вектор, характеризется, как ми- нимум, двумя значениями (в данной ситуации - источником и приоритетом). При поступле- нии запроса на прерывание оно обрабатыва- ется или игнорируется в зависимости от приоритета над выполняемым в данный момент прерыванием. Ну, а для Спектрума, хоть в нём и ис- пользуется только одно прерывание, термин этот, тем не менее, сохранён. Вот и вся недолга. Как правило, значение вектора прерываний у Speccy равно 255, поэтому для определе- ния адреса указателя достаточно содержимое регистра I умножить на 256 и прибавить 255. Итак, попробуем вообразить те дейс- твия, которые необходимо произвести для применения собственной процедуры обработки прерывания: 1) Запретить прерывания. Это необходимо во избежание запуска новой процедуры пре- рывания во время работы текущей, что чре- вато... 2) Записать по адресу, рассчитанному за- ранее, указатель на процедуру обработки прерываний, а именно её адрес. 3) Задать в регистре I старший байт ад- реса указателя на процедуру обработки. 4) Установить второй режим обработки прерываний. 5) Вновь разрешить прерывания. Естественно, процедура обработки преры- ваний на данный момент уже должна нахо- диться в памяти. Вот вкратце и всё. Теперь - пару слов о средствах реализации. Точнее, о командах. Итак: DI запрещение прерываний EI разрешение прерываний IM 0 IM 1 IM 2 Установка одного из трёх режимов прерываний Теперь у вас есть и команды. Однако пе- ред установкой своей процедуры обработки подумайте о том, должна ли она отключаться и возвращать управление стандартной проце- дуре. Для отключения же необходимо: 1) Запретить прерывания. 2) Восстановить значение I, записав в него 63. 3) Назначить командой IM 1 первый режим прерываний. 4) Разрешить прерывания. Но и это ещё не всё. Необходимо помнить, что некоторые внешние устройства могут из- менять значение вектора прерываний. Кроме того, если ваш Speccy собран на коленях "кривыми ручками" по заляпанной пивом схе- ме, вектор прерывания может скакать самым непредсказуемым образом. Естественно, в таком случае вероятность вызова процедуры обработки равняется 1/256. Во избежание глюков и головной боли программисты прибе- гают к следующему приёму: вместо записи двух байт по определённому адресу выстраи- вается таблица размером не менее 257 байт с таким расчётом, чтобы в любом случае считывался один адрес. Естественно, для этого все элементы таблицы должны быть одинаковы. Наиболее удачным значением для заполне- ния этой таблицы является 255. Не пугай- тесь, что адрес процедуры будет равен #FFFF. Этого одного байта как раз хватит для размещения кода 24 (команда JR). За ней последует адрес #0000, по которому в ПЗУ находится значение #F3. Таким образом получается JR 65524. По этому адресу уже можно разместить комаду JP с самым произ- вольным адресом перехода. Рассмотрим пример установки своей про- цедуры обработки прерываний: LD A,24 ;код команды JR LD (65535),A LD A,195 ;код команды JP LD (65524),A LD HL,ISR ;адрес обработчика LD (65525),HL LD HL,#FE00 LD DE,#FE01 LD BC,#0100 LD (HL),#FF LD A,H LDIR DI LD I,A IM 2 EI Вот мы и подключили процедуру обработки прерываний. Рассмотрим теперь обратный процесс, а именно возврат к режиму IM 1. DI LD A,63 LD I,A IM 1 EI И напоследок - пример. Допустим, вы хо- тите воспроизводить музыку во время работы вашей программы. Если вы используете мело- дию, откомпилированную в одном из музы- кальных редакторов и оснащённую стан- дартным плеером, проблем у вас не возник- нет. Для проигрывания необходимо каждые 1/50 секудны вызывать плеер, а значит, частота прерываний вам идеально подходит. Перед тем, как начать воспроизведение, не- обходимо проинициализировать плеер, сделав CALL по сответствующему адресу. Адрес ини- циализации, равно как и проигрывания, за- висит от конкретного редактора и условий компиляции. Однако часто бывает, что ини- циализация расположена в самом начале ме- лодии, а проигрывание ноты ещё на шесть байт дальше. Если допустить, что мелодия компилирована под адрес #C000, то инициа- лизация будет расположена по адресу #C000, а воспроизведение ноты - по адресу #C006. Теперь подкорректируем наши примеры. В процедуру установки второго режима преры- ваний добавьте CALL #C000 для инициализа- ции. Это следует проделать и с процедурой восстановления прежнего режима прерываний. Для чего? Чтобы после того, как вы отклю- чили музыку, AY не продолжал тянуть пос- леднюю ноту. Инициализация позволит вам быстро "заткнуть глотку" динамику. А теперь посмотрм на саму процедуру: ISR DI PUSH AF ;сохраняем все регистры PUSH BC ;для нормального возврата PUSH DE ;в основную программу PUSH HL CALL #C006;вызываем плеер POP HL ;восстанавливаем POP DE ;сохраненные значения POP BC POP AF EI ;разрешение прерываний RET ;и возврат Если вы всё сделали правильно и опреде- лили адреса инициализации и проигрывания, музыка должна зазвучать. Упомянём ещё одну команду для облегчения жизни - HALT. Когда процессор набредает на неё, он приостанавливает работу и ждёт сигнала прерывания. После его поступления управление передаётся процедуре обработки прерывания. А после её завершения основная программа продолжает свою работу с коман- ды, следующей за HALT. Это позволяет ис- пользовать HALT для синхронизации вашей программы с прерываниями. Ну, вроде всё пока с теорией. Осталось только, как водится, изложить кое-что о флагах и вариантах команд. Взгляните: ╔═══════════╤═══════════════╗ ║ Мнемоника │ Флаги ║ ║ операции ├───────────────╢ ║ │ C Z P/V S N H ║ ╟───────────┼───────────────╢ ║ DI │ . . . . . . ║ ║ EI │ . . . . . . ║ ║ IM 0 │ . . . . . . ║ ║ IM 1 │ . . . . . . ║ ║ IM 2 │ . . . . . . ║ ║ LD A,I │ . x x x 0 0 ║ ║ LD I,A │ . . . . . . ║ ║ HALT │ . . . . . . ║ ╚═══════════╧═══════════════╝ Вот и все флаги. Теперь можете смело приступать к озвучиванию своих программ. Не забывайте только, что некоторые плееры имеют привычку разрешать прерывания. Также непосредственно после перехода на процеду- ру обработки прерываня по HALT прерывания оказываются запрещёнными. Продолжение следует... ──══════════──
Другие статьи номера:
Похожие статьи:
В этот день... 21 ноября