Nie było to rozgłaszane, ale nie jest tajemnicą, że piszę diagnostykę i firmware dla pasiowej karty turbo. Przez te kilka tygodni zdążyłem się przekonać, że 65c816 w pełnej przestrzeni adresowej jest diabelnie trudnym procesorem do oprogramowania w asemblerze. Główną trudność stanowi jego kontekstowość, o której trzeba pamiętać pisząc każdy fragment kodu:
w zależności od stanu procesora rozkazy natychmiastowe mogą łykać 8 lub 16 bitów operandu,
w zależności od okoliczności ten sam adres logiczny może wskazywać na rózne adresy fizyczne, np. lda $00 to adresowanie zerostronicowe (direct) więc adres fizyczny to D + $00, lub adresowanie absolutne, które adresuje pamięć w banku danych (niekoniecznie tożsamym z bankiem zerowym) oraz adresowanie długie, które to dopiero zaadresuje komórkę o fizycznym adresie $000000.
"strona zerowa" jest ruchoma i indeksowanie 16-bitowe może trafić gdzie indziej niż to wynika z kodu, bo $00,X nie wskazuje na adres X, tylko D + X.
równocześnie można operować na trzech różnych bankach: zerowym, banku danych, banku programu, przez co takie sta *+4 nie zawsze trafia w operand następnego rozkazu.
O co zatem mi chodzi? O to, że składnia asemblera 6502 ma się nijak do programowania 65c816 i straciłem sumarycznie wiele godzin z powodu błędów wynikłych z nawyku programowania 6502. O wiele za dużo, szczególnie, że w części z nich z pewnocią mógłby pomóc asembler. Założyłem ten wątek, bo nie jestem 100% pewny jakie rozwiązanie byłoby najlepsze i może ktoś będzie miał jakieś fajne pomysły i spostrzeżenia.
Skrajnym rozwiązaniem byłoby zaproponowanie składni niekompatybilnej z dotychczasową, ale wadą byłaby konieczność nauki asemblera od nowa. Rozwiązaniem pośrednim i najprostszym mógłby być jakiś tryb "strict" istniejącej składni. Najważniejsze co byłoby niezbędne w tym trybie to wyłączenie optymalizacji długości operandu oraz obligatoryjne specyfikowanie długości. Byłoby więcej pisania, ale to zdecydowanie mniejsze zło od głupich pomyłek, bo przecież każdy z tych rozkazów robi coś innego:
0000 A5 00 lda.b 0
0002 AD 00 00 lda.w 0
0005 AF 00 00 00 lda.l 0
0009 A9 00 lda.b #0
000B A9 00 00 lda.w #0
i przy braku specyfikacji długości w zależności od tego jaki operand wpadnie to wygeneruje się inny rozkaz.
Następna rzecz, której brakuje mi w madsie, to możliwość nadawania adresu asemblacji poza bankiem zerowym. ORG przyjmuje tylko adres z przedziału $0000 do $ffff i napisanie kodu dedykowanego bankowi np $f0 nastręcza niemałych trudności (kilka godzin szukałem błędu, którym był skok jsl, który trafiał do banku zerowego).
To nie rozwiązuje wszystkich problemów, ale przynajmniej te najważniejsze.
Ogólnie spostrzeżenia mam takie, że karta turbo z 65c816 i 16 MB RAMu to już nie atari ;)
Jak widać programuje się to zupełnie inaczej i daje zupełnie inne możliwości. Pamięć atari w banku zerowym może być traktowana coś a la pamięć CHIP w amigach, i opłaca się go używać tylko do pamięci ekranu a kod i dane można trzymać wyżej, ale to wymaga szerokiej infrastruktury w postaci formatu plików wykonywalnych dedykowanych wysokim bankom i systemu operacyjnego, który to wszystko obsłuży.
No i dość dobrze pasowałby tu kompilator wysokiego poziomu, bo 816 ma tryby adresowania wspierające pracę z kompilatorami (np., adresowanie względem wskaźnika stosu) i jak ma się tak dużo pamięci, to nie trzeba optymalizować na rozmiar.