Инструменты пользователя

Инструменты сайта


msx:basic_dialogue_programming_language:104

Первая страницаПредыдущая страницаНазад к обзоруСледующая страницаПоследняя страница

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│ │                                       │
│ └───────────────────────────┘ │                                       │
└───────────────────────────────┴───────────────────────────────────────┘

Пример 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.


1040-01.bas
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+РУС прекращает работу этой программы.

Пример 2. При нажатии функциональной клавиши F4 печатается слово «Миша».
1040-02.bas
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"        :' К о н е ц  ;

Пример 3. Команда RUN приводит к появлению на экране слова «Миша».
1040-03.bas
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"        :' К о н е ц    ;

Пример 4. Программа позволяет на слух оценивать частоту обращений к ловушкам по маскируемым прерываниям. Во время очередного прерывания по таймеру издается звонок–сигнал. Таким образом ловушка «прозванивается».
1040-04.asm
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                  ;

Пример 5. Перемещение спрайта по прерываниям
1040-05.asm
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

Первая страницаПредыдущая страницаНазад к обзоруСледующая страницаПоследняя страница

msx/basic_dialogue_programming_language/104.txt · Последние изменения: 2023-02-19 16:26 — GreyWolf