energy.scene.pl

Popularny magazyn na ośmiobitowe Atari

Wybierz muzykę:

Energy 1: 1 2 3 4 5
Energy 2: 1 2 3 4 5 6 7 8 9 10 11 12
Print this page
Znaczenie znaczników

Fox
autor: fox

W poniższym tekście zajmę się opisem rejestru znaczników (wszyscy koderzy wiedzą, o co chodzi).

W tym miejscu wszyscy nie-koderzy na pewno już skończyli lekturę tego artykułu, natomiast koderzy co najmniej uśmiechnęli się pod nosem: "Co on może nowego napisać o znacznikach? Bo przecież w każdym podręczniku czy kursie asemblera już wszystkie znaczniki zostały opisane."

To błąd! Przeczytaj ten artykuł, a gwarantuję Ci, że dowiesz się czegoś ciekawego.


Umówmy się, że rejestr znaczników oznaczamy literką F. Piwo dla tego, kto mi wyjaśni, jaki sens ma oznaczenie P, bo z takim też się spotkałem.

 

Innym fenomenem jest nazywanie tego rejestru rejestrem FLAGOWYM. (to pewnie z angielskiego "Flag register")

Rejestr F, jak wszyscy wiemy, wygląda tak:

 N V * B D I Z C

Znacznikami N, Z i C nie będę się zajmował, bo z nich to chyba każdy umie korzystać.


b6 - oVerflow - znacznik przepełnienia (nadmiaru).

To jest b. ciekawy znacznik, więc zatrzymamy się przy nim dłużej.

Gdzieś czytałem, że bit V zawiera 9. bit wyniku, jeśli nastąpiło przeniesienie z b8, którym jest znacznik C. Śmieszne, nie?


Ale tak naprawdę na wartość znacznika V wpływa tylko kilka rozkazów:


BIT - znacznik V jest kopiowany z b6 bajtu pobranego z pamięci


ADC- z różnych źródeł wiadomo, że zostaje on ustawiony, jeśli nastąpi przeniesienie z b6 do b7 i jest wykorzystywany przy liczbach ze znakiem.

Ja po kilku próbach znalazłem prostsze wytłumaczenie:

V=1 wtedy i tylko wtedy, gdy b7 składników są jednakowe, a b7 wyniku jest od nich różny. Proste, nie?


SBC - tutaj równie skomplikowana sprawa, jak z dodawaniem: V=1 wtedy i tylko wtedy, gdy b7 akumulatora i pamięci są różne, a w wyniku odejmowania zmienił się b7 akumulatora.


CLV - kasuje znacznik V. Ale po co? Ogłaszam konkurs! Jeśli ktoś w jakimkolwiek programie użył rozkazu CLV i naprawdę był on tam potrzebny, to niech da mi znać. Dostanie całego Snickersa!!!


Dodatkowo znacznik V zmieniają PLP i RTI, ale one po prostu zmieniają cały rejestr znaczników, więc nie ma w tym nic nadzwyczajnego.


b5 - * - ten bit jest nieużywany. Wszędzie można spotkać właśnie taką informację, która jest niepełna. Pełna informacja jest taka: tego bitu nie ma, bo zawsze jest równy 1. Można się o tym łatwo przekonać:

 LDA #0
 PHA
 PLP
 PHP
 PLA
 BRK

b4 - Break - uwaga! To następny znacznik, którego NIE MA! Chodzi o to, że tak jak b5 jest zawsze ustawiony.

 

Mądry koder spyta, dlaczego się nazywa B, skoro go nie ma?

 

Odpowiedź jest prosta:

 

Rozkaz BRK jest traktowany jako wymuszenie przerwania IRQ, ale nieco różni się od innych przerwań maskowalnych:

 

- działa nawet jeśli znacznik I jest ustawiony

- ponieważ wykorzystuje standardową procedurę IRQ wskazywaną przez wektor $FFFE, to musi być jakiś sposób wykrycia, że chodzi o przerwanie BRK.

 

Jak wiadomo, przy wywołaniu przerwania procesor wrzuca na stos adres powrotu oraz rejestr znaczników.

Przerwanie BRK można rozpoznać po tym, że na stosie jest zapisany rejestr znaczników ze skasowanym b4, czyli właśnie znacznikiem B.

Errata z 2009: przerwania zapisują na stos skasowany "znacznik B", z wyjątkiem BRK, które zapisuje "znacznik" ustawiony. Poza tym w 6502 jest błąd polegający na tym, że jeśli NMI wystąpi w trakcie obsługi BRK, zostanie wykonany skok pod wektor NMI ($FFFA), ale z ustawionym "znacznikiem" B - pisałem o tym w magazynie dyskowym Syzygy.

 

Okazuje się, że tylko wybrani o tym wiedzą. Np. proszę się przyjrzeć programowi Bug Hunter pana JBW. Jest tam możliwość zmiany znacznika B. Parodia. Ale ma to swoją zaletę, bo można sprawdzić, które rozkazy są symulowane, a które naprawdę wykonywane.

 

Wystarczy skasować znacznik B i uruchomić wybrany rozkaz. Jeżeli B pozostanie skasowany, to znaczy, że rozkaz w rzeczywistości nie został wykonany.

 

Skoro już poruszyłem temat rozkazu BRK, to dodam tylko, że jest to rozkaz dwubajtowy, tzn. jeśli mamy BRK pod adresem $600, to powrót z przerwania spowoduje wykonanie rozkazu spod $602, a nie $601.


b3 - Decimal - znacznik trybu dziesiętnego procesora (BCD)

 

W trybie dziesiętnym procesor inaczej wykonuje rozkazy ADC i SBC. Nie będę tu opisywał dokładnie operacji przeprowadzanych dodatkowo przy działaniach dziesiętnych, bo to chyba nie jest nikomu potrzebne. Np. rozkaz ADC po swoim normalnym wykonaniu dodaje jeszcze 6 i/lub $60.

 

Czy to ma jakieś zastosowanie? TAK! Dosłownie przed chwilą to wymyśliłem!

 

Popatrzmy, w jaki sposób zamienia się cyfrę hex na ASCII. Można to zrobić np. tak:

 CMP #10
 ORA #'0'
 BCC *+4
 ADC #6 +

Pewnie myślicie, że nie można tego skrócić? To patrzcie na to:

 CMP #10
 SED
 ADC #'0'
 CLD

To działa! A jest krótsze o dwa bajty! Co prawda czasami jest wolniejsze o cykl, ale jeśli zależy Ci na szybkości, to pewnie widzisz, że ta metoda może być szybsza przy wyświetlaniu całych bajtów (jeśli ustawiony jest D, to konwersja sprowadza się do CMP i ADC).

 

Oczywiście jeśli chcesz mieć kod ANTIC'a zamiast ASCII, to wystarczy zamienić '0' na $10.


b2 - Interrupts - znacznik zabronienia przerwań maskowalnych (IRQ). Jeśli jest ustawiony, to procesor nie obsługuje przerwań maskowalnych. Nie oznacza to, że przerwania te są zupełnie ignorowane! Jeżeli np. wciśniemy klawisz w chwili, gdy I jest ustawiony, ale przerwanie klawiatury dozwolone, to przerwanie zostanie wykonane po skasowaniu I.

Jakie to ma zastosowanie praktyczne? Najczęściej używamy IRQ tylko dla przerwania klawiatury. Wtedy całe IRQ może wyglądać tak:

 PHA
 LDA #0
 STA $D20E
 LDA #$40
 STA $D20E
 LDA $D209
 STA KEY
 LDA #14
 STA SRT
 PLA
 RTI

I znowu pytanie: czy można to skrócić? Oczywiście. Zazwyczaj jeszcze robi się obsługę powtarzania klawiszy na VBL-ku. Wystarczy więc wykonywać IRQ tylko w czasie VBL. Robi się to w ten sposób:

 CLI
 SEI

Teraz nie musimy przechowywać akumulatora na czas IRQ (odpada PHA/PLA), bo dokładnie wiemy, kiedy przerwanie się wykona. Ponadto IRQ nie miesza nic w czasie wyświetlania ekranu. To akurat nie jest mój pomysł, bo podpatrzyłem go w BEHIND JAGGI LINES (ZA-JE-BISTA gierka z '84 roku!).


To już koniec opisu znaczników. Mam nadzieję, że dowiedziałeś się czegoś nowego. B.



Poprzednia strona: "Słodka szestnastka"
Następna strona: Śmieszne