Программирование assembler 6502 nes/famicom/dendy векторы прерывания, процедуры и их вызов

от автора

Векторы прерывания в формате программирование на ассемблере 6502, можно представить как всем хорошо известный патерн event-observer в высокоуровневых языках программирования. Конечно же можно реализовать данный патерн и на ассемблере но я его привел для большего понимания работы вектора прерывания.

Если помните раннее я уже упоминал про память в 6 байт (3 слова, по 16 бит), которые выделены для секции VECTOR данный сегмент содержит всего 3 адреса процедур

.segment "VECTORS" .addr nmi_isr, reset, irq_isr 

Когда ассемблер соберет код в бинарный файл заместо меток будет установлен соответствующий адрес данных процедур, которые обработают определенное прерывания. Всего их 3 в Famicom

  1. NMI — Not Masked Interrupt — событие срабатывающие при генерации каждого кадра то есть 60 раз в секунду. Тут будет отрабатывать код для отрисовки кадра игры.

  2. RESET — Событие перезагрузки — тут мы будем инициализировать программу, исходя из названия данное прерывание срабатывает при перезагрузки/загрузки процессора

  3.  IRQ — Interrupt request — прерывание которое может быть запущенно по запросу какого либо оборудования

Я в своей игре пока не использую IRQ по этому процедура выглядит довольно просто

.proc irq_isr   RTI .endproc

RTI — return from interrupt возврат в прерывание, это довольно важное замечание забегая вперед скажу что в остальных случаях объявление .proc будет выполнять инструкцию RTS — Return from subroutine что буквально вернуть в подпрограмму.

Мы плавно подошли к понятию .proc (procedure),  сам по себе  .proc определяет некую область видимость где могут быть использованы и определенны одноименные метки, но в контексте процедуры возможен только переход на метки данной процедуры. К примеру:

.proc foo   LDA var   CMP #$01   BEQ return   LDA var2   STA var3 return:   RTS .endproc   .proc bar   LDA var   CMP #$02   BEQ return   LDA var2   STA var3 return:   RTS .endproc   .proc main   JSR foo   JSR bar .endproc

Но не только саброуты (процедуры) они еще позволяют структурировать наш код в более понятные секции как функции/процедуры/методы в других языках. И еще один огромный плюс, конструкции ветвления JMP, BEQ, BNE, BCC, BCS могут перейти только на интервал -128-+128 строк, то есть в пределах адресации лимитированные 1 байтом (максимальное число 256) а вот процедуры по факту не имеют такого ограничения.

Выше в подпрограмме я привел пример как вызвать процедуру, с помощью инструкции JSR — jump to SubRoutine с помощью нее мы переходим в подпрограмму, выполняем какие то действия и в окончание в подпрограмме которую мы вызвали происходит вызов инструкции RTS, которая возвращает нас обратно в процедуру которая до этого вызвала эту подпрограмму, и родительская подпрограмма продолжает выполняться дальше.

Ассемблер ca65 и многие другие ассемблеры позволяют выполнять инструкции .include «filename.asm» которая включает файлы в главный файл игры. Интересно что в каждом файле мы можем определить нужные нам секции, которые определены в ini файлы конфигурации линкера который определяет в какой диапазон памяти положить ту или иную секцию кода, но это уже разговор для следующих статей.

Полезные ссылки:


ссылка на оригинал статьи https://habr.com/ru/post/716254/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *