Как стать автором
Обновить

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

Уровень сложностиПростой
Время на прочтение2 мин
Количество просмотров4.1K

Векторы прерывания в формате программирование на ассемблере 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 файлы конфигурации линкера который определяет в какой диапазон памяти положить ту или иную секцию кода, но это уже разговор для следующих статей.

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

Теги:
Хабы:
Если эта публикация вас вдохновила и вы хотите поддержать автора — не стесняйтесь нажать на кнопку
Всего голосов 8: ↑7 и ↓1+9
Комментарии17

Публикации

Истории

Ближайшие события

27 августа – 7 октября
Премия digital-кейсов «Проксима»
МоскваОнлайн
28 – 29 сентября
Конференция E-CODE
МоскваОнлайн
28 сентября – 5 октября
О! Хакатон
Онлайн
30 сентября – 1 октября
Конференция фронтенд-разработчиков FrontendConf 2024
МоскваОнлайн
3 – 18 октября
Kokoc Hackathon 2024
Онлайн
7 – 8 ноября
Конференция byteoilgas_conf 2024
МоскваОнлайн