[<>]
~~TOC wide~~
{{anchor:n104}}
====== 1.4. Использование ловушек ======
\\
... И тут Пух все понял. Они с Пятачком попались
\\ в Хитрую Ловушку для Пухов, которую в отместку
\\ им вырыл Слонопотам!...
—//Отрывок из неопубликованной главы повести
\\ А.Милн "Винни–Пух и все–все–все"//
Вы, конечно,помните, что программы, выполняющие всю "черную" работу,"зашиты" в ROM, поэтому изменить их //невозможно//. Однако,в некоторых важных подпрограммах ROM предусмотрены своеобразные "перехваты" — //ловушки// ("hooks").
Вызов подпрограммы–ловушки организуется в ROM следующим образом:
PUSH HL ; Сохранение содержимого
PUSH DE ; регистров микропроцессора
PUSH BC ; в стеке
PUSH AF ;
CALL а д р е с ; Вызов подпрограммы-ловушки по заданному адресу
POP AF ; Восстановление значения
POP BC ; регистров микропроцессора
POP DE ; для дальнейших операций
POP HL ;
При включении компьютера подпрограмма–ловушка содержит только команду возврата (RET). Вы //можете// заменить эту команду на команду перехода (JP) к подпрограмме, которая написана Вами на машинном языке.
В этом случае о ловушке говорят, что она //обрабатывается//.
Таким образом, Вы можете косвенно изменять ROM и вводить //новые// операторы! Приведенный ниже рисунок показывает, что означает термин "обработать" ловушку.
┌───────────────────────────────┬───────────────────────────────────────┐
│ ┌───────────────────────────┐ │ │
│ │Предыдущая подпрограмма ROM│ │ │
│ └──────────┬────────────────┘ │ ┌──────────────────┐ │
│ └──────────────────│──▶ Необрабатываемая │ │
│ ┌──────────────────│──┤ ловушка │ │
│ ┌──────────▼────────────────┐ │ └──────────────────┘ │
│ │ Следующая подпрограмма ROM│ │ │
│ └───────────────────────────┘ │ │
│ ┌───────────────────────────┐ │ │
│ │Предыдущая подпрограмма ROM│ │ ┌──────────────┐ │
│ └──────────┬────────────────┘ │ ┌────────────────┐ │ Ваша │ │
│ └──────────────────│──▶ Обрабатываемая │──▶ подпрограмма │ │
│ │ │ ловушка │ │ обработки │ │
│ │ └────────────────┘ └───────┬──────┘ │
│ ┌──────────────────│──────────────────────────────┘ │
│ ┌──────────▼────────────────┐ │ │
│ │ Следующая подпрограмма ROM│ │ │
│ └───────────────────────────┘ │ │
└───────────────────────────────┴───────────────────────────────────────┘
{{anchor:e1040-01}}
__//Пример 1.//__ //Отмена// действия клавиши STOP.
При //выполнении программы// на языке [[msx:basic:|]] клавиатура постоянно опрашивается (сканируется). Нажатие клавиши порождает код, который записывается в буфер клавиатуры (начинающийся с адреса &HF55E в рабочей области). До этого код нажатой клавиши временно записывается в слово NEWKEY, начинающееся с адреса &HFBE5.
Регистр А микропроцессора необходимо загрузить значением
8·NS+NC
,
где:
* ''NS'' — номер строки матрицы клавиатуры;
* ''NC'' — номер столбца матрицы клавиатуры.
Поэтому поместим в регистр A значение
8·7+4=60=&H3C .
▲ ▲
Номер с т р о к и матрицы ─┘ └─ Номер с т о л б ц а матрицы
клавиатуры,содержащей клавишу клавиатуры,содержащей клавишу
"STOP" "STOP"
Затем осуществим переход на ловушку с именем KEYKOD, расположенную по адресу &HFDCC .
Обычно ловушка занимает 5 байтов памяти, содержащих только команду ассемблера RET (ее код &HC9). Введем вместо нее переход на подпрограмму //обработки ловушки//. Эта подпрограмма будет действовать только при нажатии клавиши STOP.
\\ {{.examples:1040-01.bas|}} \\ [[+tab|wmsxbpge>1040-01.bas]]
10 CLEAR 200,&HD000 'Зарезервируем область для хранения подпрограммы
' обработки ловушки
20 POKE &HFDCC,&HC3 'Запишем команду перехода на ловушку с именем
30 POKE &HFDCD,&H00 ' KEYCOD : ┌───────────┐
40 POKE &HFDCE,&HD0 ' C3,00,D0 │ JP D000 │
50 AD=&HD000 └───────────┘
60 READ A$:IF A$="Z" THEN END
70 POKE AD,VAL("&H"+A$)
80 AD=AD+1:GOTO 60
100 'П о д п р о г р а м м а о б р а б о т к и л о в у ш к и
120 DATA FE,3C :' CP 3C ;Сравниваем константу 3Ch с
;содержимым регистра A
130 DATA C0 :' RET NZ ; "нет" ──▶ выход
140 DATA 3E,FD :' LD A,FD ; A=FD
150 DATA 32,EB,FB :' LD (FBEBh),A ; A ──▶ FBEB
160 DATA 3E,3C :' LD A,3C ; A=3C
170 DATA C9 :' RET ; Выход
180 DATA "Z" :'
Выполните эту программу: обратите внимание на тот факт,что нажатие клавиши STOP производит такой же эффект, как и нажатие клавиш CTRL + STOP в //командном// режиме.
Подпрограмма обработки ловушки посылает значение
&H11111101=&HFD
по адресу &HFBEB (шестая строка матрицы клавиатуры),имитируя тем самым нажатие клавиши CTRL. При этом нажатие клавиши STOP будет прочитано как одновременное нажатие клавиш CTRL и STOP,что будет обработано в [[msx:basic:|]] уже по обычным правилам.
Удалите вышеприведенную программу и введите новую программу:
10 POKE &HFBB0,1
20 ON STOP GOSUB 100:STOP ON
30 PRINT A:A=A+1:GOTO 30
100 RETURN
Нажатие клавиши STOP теперь не приводит к прекращению программы и выводу на экран курсора. Поскольку клавиша STOP превращена в CTRL + STOP, то клавиша STOP "перестает работать".
Отметим, что нажатие сложной комбинации клавиш CTRL + SHIFT + GRAPH + РУС прекращает работу этой программы.
{{anchor:e1040-02}}
__//Пример 2//__. При нажатии функциональной клавиши F4 печатается слово "Миша". \\ {{.examples:1040-02.bas|}} \\ [[+tab|wmsxbpge>1040-02.bas]]
10 CLEAR 200,&HD000
20 POKE &HFDCC,&HC3 ':\
30 POKE &HFDCD,&H0 ': > JP D000
40 POKE &HFDCE,&HD0 ':/
50 AD=&HD000
60 READ A$:IF A$="Z" THEN END
70 POKE AD,VAL("&H"+A$)
80 AD=AD+1: GOTO 60
90 DATA FE,38 :' CP 38h ; A:=38h ?
100 DATA C0 :' RET NZ ; Символ ":=" означает "содержит"
110 DATA 3E,ED :' LD A,EDh ; A:=EDh ───▶"М"
120 DATA CD,A2,00 :' CALL 00A2 ;
130 DATA 3E,C9 :' LD A,C9h ; A:=C9h ───▶"и"
140 DATA CD,A2,00 :' CALL 00A2 ;
150 DATA 3E,DB :' LD A,DBh ; A:=DBh ───▶"ш"
160 DATA CD,A2,00 :' CALL 00A2 ;
170 DATA 3E,C1 :' LD A,C1h ; A:=C1h ───▶"а"
180 DATA CD,A2,00 :' CALL 00A2 ;
190 DATA 3E,40 :' LD A,40h ; A:=40h
200 DATA C9 :' RET ;
210 DATA "Z" :' К о н е ц ;
{{anchor:e1040-03}}
__//Пример 3//__. Команда RUN приводит к появлению на экране слова "Миша". \\ {{.examples:1040-03.bas|}} \\ [[+tab|wmsxbpge>1040-03.bas]]
10 CLEAR 200,&HD000
20 POKE &HFECB,&HC3 ':\
30 POKE &HFECC,&H0 ': > JP D000
40 POKE &HFECD,&HD0 ':/
50 AD=&HD000
60 READ A$:IF A$="Z" THEN END
70 POKE AD,VAL("&H"+A$)
80 AD=AD+1:GOTO 60
90 DATA 3E,ED :' LD A,EDh ; A:=EDh ───▶"М"
100 DATA CD,A2,00 :' CALL 00A2 ;
110 DATA 3E,C9 :' LD A,C9h ; A:=C9h ───▶"и"
120 DATA CD,A2,00 :' CALL 00A2 ;
130 DATA 3E,DB :' LD A,DBh ; A:=DBh ───▶"ш"
140 DATA CD,A2,00 :' CALL 00A2 ;
150 DATA 3E,C1 :' LD A,C1h ; A:=C1h ───▶"а"
160 DATA CD,A2,00 :' CALL 00A2 ;
170 DATA C9 :' RET ;
180 DATA "Z" :' К о н е ц ;
{{anchor:e1040-04}}
__//Пример 4//__.
Программа позволяет на слух оценивать частоту обращений к ловушкам по маскируемым прерываниям. Во время очередного прерывания по таймеру издается звонок–сигнал. Таким образом ловушка "прозванивается".
\\ {{.examples:1040-04.asm|}} \\ [[+tab|wmsxbpge>1040-04.asm]]
.Z80
LD HL,OBJ ; Организация псевдо-ROM
LD DE,04000H ; в 1-й странице слота 3-2
LD BC,80H ;
LDIR ;
LD HL,START ; Создание структуры страниц
LD DE,09000H ; должно происходить в "верхних"
LD BC,OBJ-START ; адресах
LDIR ;
JP 9000H ;
START: DI ;
LD A,0FCH ; 1-я страница - BASIC BIOS
OUT (0A8H),A ; 2-я страница из слота 3-2
LD A,0A8H ; 3-я страница из слота 3-2
LD (0FFFFH),A ; 4-я страница из слота 3-2
EI ;
LD HL,(4002H) ;
JP (HL) ; Переход на начало основной программы
OBJ: ;
.PHASE 4000H ;
DB 'AB' ; Идентификатор ПЗУ
DW NACH ; Адрес начала программы
DW 0 ; Зарезервированы 12 байтов
DW 0 ;
DW 0 ;
DW 0 ;
DW 0 ;
DW 0 ;
NACH: XOR A ;
CALL 00C3H ; Очистка экрана
CALL 00CCH ; Выключение функциальных клавиш
DI ;
IM 1 ; Установка 1-го режима прерываний:
LD A,0C3H ; - сохраняется программный счетчик в стеке;
LD (0FD9AH),A ; - переход по адресу 038H, где происходит
LD HL,WORK ; обращение к адресам 0FD9AH и 0FD9FH
LD (0FD9BH),HL ; с частотой 60 Гц.Любой из адресов можно
EI ; использовать для обработки прерываний
LABEL: JR LABEL ;
WORK: ;
LD A,7 ; Это и есть подпрограмма, генерирующая
OUT (0A0H),A ; звонок-сигнал!
LD A,10111110B ;
OUT (0A1H),A ;
LD A,8 ;
OUT (0A0H),A ;
LD A,10H ;
OUT (0A1H),A ;
LD A,11 ;
OUT (0A0H),A ;
LD A,100 ;
OUT (0A1H),A ;
LD A,12 ;
OUT (0A0H),A ;
LD A,0 ;
OUT (0A1H),A ;
LD A,13 ;
OUT (0A0H),A ;
LD A,1 ;
OUT (0A1H),A ;
RET ;
.DEPHASE ;
END ;
{{anchor:e1040-05}}
__//Пример 5//__. Перемещение спрайта по прерываниям
\\ {{.examples:1040-05.asm|}} \\ [[+tab|wmsxbpge>1040-05.asm]]
;Некоторые макроопределения:
DISK MACRO ;
LD BC,0100H ;
DSK:PUSH BC ;
CALL 0FD9FH ;
POP BC ;
LD A,B ; Гашение лампочки дисковода
OR C ; для YIS805/128 КУВТ 2
RET Z ;
DEC BC ;
JR DSK ;
ENDM ;
;
GASI MACRO ;
BCALL 041H ; В ы к л ю ч е н и е экрана
ENDM ;
;
GORI MACRO ;
BCALL 044H ; В к л ю ч е н и е экрана
ENDM ;
;
NETEND MACRO ;
RST 030H ;
DEFB 08FH ; Отключение от с е т и (только для MSX-2)
DEFW 04016H ;
ENDM ;
BCALL MACRO @X ;
RST 030H ;
DEFB 0 ; Межслотовые вызовы подпрограмм
DEFW @X ;
ENDM ;
CLS MACRO ;
XOR A ; Очистка экрана
BCALL 0C3H ;
ENDM ;
SCREEN2 MACRO ;
LD HL,01800H ;
LD (0F3C7H),HL ;
LD HL,02000H ;
LD (0F3C9H),HL ;
LD HL,0 ; Инициализация и установка
LD (0F3CBH),HL ; 2-го графического режима
LD HL,01B00H ;
LD (0F3CDH),HL ;
LD HL,03800H ;
LD (0F3CFH),HL ;
BCALL 072H ;
ENDM ;
COLOR MACRO ;
LD A,01H ;
LD HL,0F3E9H ;
LD (HL),A ;
INC HL ; Установка цвета
LD (HL),A ;
INC HL ;
LD (HL),A ;
BCALL 062H ;
ENDM ;
INITSPR MACRO ;
BCALL 069H ;
LD BC,06201H ; Инициализация и "разрешение"
BCALL 047H ; спрайтов размером 16 ╳ 16
ENDM ;
VIDEO MACRO ;
SNOW:DI ;
LD A,E ;
OUT (99H),A ; Заполнение области видеопамяти, начинающейся
LD A,D ; с DE длиною в BC из области, начинающейся с HL
OR 40H ;
OUT (99H),A ;
LD A,(HL) ;
OUT (98H),A ;
LD A,B ;
OR C ;
EI ;
RET Z ;
DEC BC ;
INC HL ;
INC DE ;
JR SNOW ;
ENDM ;
START: ;
CALL DISKETA ; Выполнение описанных макроопределений
NETEND ;
GASI ;
COLOR ;
SCREEN2 ;
INITSPR ;
CLS ;
LD HL,SGT ; Заполнение видеопамяти шаблонами спрайта
LD DE,03800H ;
LD BC,20H ;
CALL VRAM ;
LD HL,SAT ;
LD DE,01B00H ; Установка атрибутов спрайта
LD BC,04H ;
CALL VRAM ;
GORI ;
LD HL,HOOK ;
LD DE,0FD9FH ; Установка адреса обработки прерываний.
LD BC,5 ; Обслуживает подпрограмму обработки HOOK с
DI ; адресом 0FD9Fh
LDIR ;
EI ;
CIKL:NOP ;
LD HL,SAT ; Постоянное отображение спрайта на экран, но коор-
LD DE,01B00H ; динаты его меняются в подпрограмме обработки пре-
LD BC,4 ; рываний в зависимости от состояния матрицы клави-
CALL VRAM ; атуры.
... ; Здесь может находиться Ваша программа.
... ; Например, программа движения фона или движения
... ; других спрайтов.
... ;
JR CIKL ;
HOOK: RST 30H ;
DEFB 8BH ; Межслотовый вызов подпрограммы
DEFW STICK ; обработки прерываний
RET ;
STICK:LD A,8 ; Подпрограмма обработки прерываний
DI ;
CALL BUFF ; После обращения к BUFF
LD HL,SAT ; в регистре А - состояние ряда матрицы
PUSH AF ;
CP 0EFH ;
JR Z,LEFT ; В зависимости от нажатой клавиши ("стрелки")
POP AF ; меняется координата
PUSH AF ;
CP 0DFH ;
JR Z,SHIFT ;
POP AF ;
PUSH AF ;
CP 0BFH ;
JR Z,MAIN ;
POP AF ;
PUSH AF ;
CP 07FH ;
JR Z,RIGHT ;
END: POP AF ;
RET ;
SHIFT:DEC (HL) ; Клавиша "Стрелка вверх"
JR END ;
MAIN: INC (HL) ; Клавиша "Стрелка вниз"
JR END ;
LEFT: INC HL ; Клавиша "Стрелка влево"
DEC (HL) ;
JR END ;
RIGHT:INC HL ; Клавиша "Стрелка вправо"
INC (HL) ;
JR END ;
BUFF: LD C,A ; Подпрограмма возвращает состояние "сброшенных"
DI ; битов для определенного ряда матрицы клавиатуры
IN A,(0AAH) ;
AND 0F0H ;
ADD A,C ;
OUT (0AAH),A ;
EI ;
IN A,(0A9H) ;
RET ;
DISKETA: ;
DISK ;
SGT: DEFB 0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH
DEFB 0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH
DEFB 0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH
DEFB 0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH
SAT: DEFB 100,127,0,10
VRAM: VIDEO
----
[<>]
{{tag>msxbdpl}}