Для более глубокого понимания как происходит ветвление в программах написанных на ассемблере 6502 необходимо углубиться в флаги и понять какие команды влияют на тот или иной флаг. Это поможет избежать множество ошибок связанных с не очевидностью ветвления вашей программы.
Состояние статус флагов это один из шести архитектурных регистров процессора 6502:
-
Регистр аккумулятора A
-
Регистры X и Y
-
Статус регистр (статус флаги)
-
Указатель стека
-
Программный счетчик
С регистрами A, X, Y мы уже знакомы, мы их часто используем для операций с данными и записи в различные порты процессоров. Указатель стека — хранит в себе указатель на последнее/первое значение стека. Программный счетчик — всегда указывает на следующую команду которую нужно будет выбрать и выполнить, он 16 битный и после выполнения обновляется указатель на следующую команду. Более подробно рассмотрим в следующих статьях работу с этими регистрами.
Давайте рассмотрим более подробно флаги они в регистре расположены следующим образом NV**DIZC где:
-
N — Negative — этот флаг будет содержать 7-й бит результата если команда имеет результат
-
V — Overflow — флаг переполнения устанавливается если при сложение (ADC) или вычитание (SBC) результат знакового числа получился больше/меньше диапазона -127 — +127
-
D — Decimal — флаг указывающий на работу с десятичными цифрами в денди не используется
-
I — Interrupt disable — флаг указывающий на то что отключены все прерывания кроме NMI
-
Z — Zero — флаг указывающий что результат команды равен 0, часто используется в программе и ветвление с помощью BEQ (переход если равно 0) и BNE (переход если не равен 0)
-
C — Carry — флаг переноса устанавливается если результат больше 255 или меньше 0 с беззнаковыми числами, так же устанавливается если при сравнение CMP результат больше либо равно. Тоже часто используется BCC (если очищен) и BCS (если установлен)
-
* — не используемые биты
Собственно нас интересуют больше флаги C, Z так как они часто используются при разработке игр на денди, по этому более подробнее поговорим о них, остальные же флаги для сокращения объема статьи, пока рассматривать подробно не будем.
Флаг Z — zerro
Влияют следующие команды на этот флаг: LDA, LDX, LDY, AND, INX, INY, INC, DEX, DEY, DEC, CMP, EOR, ORA и многие другие, важно просто понимание что если результат выполнения 0 то флаг Z установлен к примеру
LDA #$00 ; установлен LDA #$01 ; не установлен LDX #$00 ; установлен так же и LDY DEX ; как только X станет 0 будет установлен, так же с DEC, DEY AND #%0000 ; если результат 0 то будет установлен, так же EOR, ORA LDA #$07 CMP #$07 ; если при сравнение с памятью значение равно то флаг будет установлен
Таким образом при установке данного флага будет выполняться переход с помощью BEQ если установлен и BNE если не установлен либо результат не равен 0.
Флаг C — carry
Команды которые влияют на данный флаг:
-
ADC — если после сложения больше 255
-
SBC — если меньше 0
-
CMP — если сравниваемое значение больше либо равно значению в аккумуляторе, альтернативное использование данного флага
-
ASL, LSR, ROL, ROR — содержит бит который был сдвинут.
На самом деле, перед ADC и SBC, я часто сбрасываю флаг переноса командой CLC для того что бы указатель переноса был 0 в таком случае ADC установит флаг переноса при достижения результат больше 255.
При программирование игры меня больше интересует использование этого флага для условий «больше либо равно» и соответственно «меньше», это такая альтернатива использования данного флага
LDA #$01 CMP #$02 ; флаг C установлен BCS greatOrEq ; больше либо равно BCC less ; значение в cmp меньше аккумулятора
В качестве заключения
Когда я начал изучать ассемблер 6502, я сделал большую ошибку не вникнув в работу флагов, по этому было довольно сложно понять почему после AND часто используют BEQ или же BNE переход.
Немного о планах
В ближайшем будущем я планирую написать статью о массивах байтов и как правильно их использовать и для чего надо в zeropage грузить и старший и младший байт указателя. Не так давно я разобрался как сделать коллизии фона, основанных на bitmap с загрузкой для каждого перерисованного экрана своей карты коллизий.
Полезные ссылки
-
https://youtu.be/DiMMnTW7NzM — видео/ааудио презентация статьи
-
Программирование assembler 6502 nes/famicom/dendy векторы прерывания, процедуры и их вызов
-
https://habr.com/ru/post/719636/ — вывод спрайтов и анимация
-
https://www.nesdev.org/wiki/Status_flags — статус флаги на nesdev
ссылка на оригинал статьи https://habr.com/ru/post/721168/
Добавить комментарий