Pomóżcie mi nauczyć się asemblera! Zdesperowany!

Sachy

Z moich, dość długich już, obserwacji wynika, że prawie na każde forum scenowe lub forum użytkowników danej platformy (prym tu wiodą Amigowcy - za którego też głównie się uważam, choć nie tylko) co jakiś czas wpływa taki dramatyczny apel ambitnego jegomościa, który pooglądał już trochę produkcji scenowych i bardzo chciałby sam popełnić jakieś podobne cudeńko. Gość już wie, że BASIC to zło, jak na komputer "ponad 8-bitowy", to może C, ale tak naprawdę to nie ma wyjścia i trzeba koniecznie "posiąść asemblera". A jak powszechnie wiadomo - asembler to ponoć najgorsza bestia do opanowania, nie ma znikąd pomocy i niech ktoś w końcu napisze jakiś ZROZUMIAŁY kurs wejścia na szczyt koderskiej listy przebojów.

Wybaczcie mój kpiący ton tego wstępu, ale mniej więcej co pół roku pojawia się tu i ówdzie taki właśnie wątek. Pomijam też kolejny fakt, że od razu zaczyna się w nim boczna dyskusja, że przecież wszystko też da się zrobić w C (w tym w kompilatorze CC65 na procesory rodziny 6502, itp.) lub jakimś super-zoptymalizowanym dialekcie BASICa i temat nauki kodowania w asemblerze zostaje przykryty dyskusją nad wyższością tego lub innego języka czy kompilatora. Czasem ktoś podzieli się kilkoma linkami do materiałów: kursów, samouczków, przykładowych kodów źródłowych albo tytułami książek, ale ogólnie dyskusja siada mniej więcej po wyczerpaniu argumentów o innych językach i kompilatorach. Do tego powszechna jest opinia, że "źli koderzy" zazdrośnie strzegą swojej wiedzy (z którą się urodzili zapewne), bo nadal liczą na jej komercyjne wykorzystanie - dlatego też nie podzielą się żadnym sensownym (prostym, zrozumiałym) przykładem, a o napisaniu ZROZUMIAŁEGO (podkreślam) kursu, to już w ogóle nie chcą słyszeć. Ogólnie sytuacja jest beznadziejna, świat jest zły i skoro koderzy nie pomagają, to dana platforma musi umrzeć z braku nowego softu. Następuje kilkudniowa cisza i klient aktywizuje się w wątku "jaka to gra", "jak wygląda twój komputerowy pokój", "jak wyglądałby świat, gdyby Commodore nie upadło", ewentualnie o wymianie kondensatorów, czy komentuje kolejny "crap" (wiadomo - nie napisane w asemblerze to musi być "crap", a że nikt nie chce pomóc, to będą powstawać wyłącznie takie "krapy" - platforma umrze).

No cóż, zmartwię niestety oczekujących na poprawę sytuacji ("zrozumiały dla ludzi" kurs, itp.) - nie będzie lepiej, niż jest aktualnie. Nie powstanie żaden oświecający wykład (mimo, że powstaje ich aktualnie kilka - żaden jednak "przełomowy" w pojęciu naszego tytułowego "Zdesperowanego"), żadna ZROZUMIAŁA książka, żaden przepis na sukces. Niechcianą prawdą jest to, że takie materiały już od dawna istnieją i to w sporej ilości. W czasach wujka Google - wszystko jest na wyciągnięcie ręki. Problem nie leży po stronie złych materiałów, tylko w sposobie korzystania z nich. Tak naprawdę, do żadnego języka programowania nie ma "boskich" materiałów rozwiązujących wszystkie problemy, a do wielu rzeczy trzeba dochodzić samemu. Są materiały pokazujące podstawowe ścieżki i sposoby; są przykładowe kody źródłowe (fakt - lepsze i gorsze, ale jest ich na tyle sporo, że można coś wyszukać), są kursy i samouczki. Są też miejsca (forum dyskusyjne o kodowaniu), gdzie można zadać pytanie i uzyskać wyczerpujące odpowiedzi. Jest jednak jeden warunek - do tych możliwości trzeba podejść poważnie. Trzeba niestety władować w naukę duże ilości własnego czasu i wysiłku, a zadając pytanie doświadczonym koderom - trzeba zadać je konkretnie i sensownie - tylko wtedy możemy liczyć na sensowną odpowiedź. Nie można pytać na poziomie ogólności "Jak poradzić sobie z brakiem wody w Afryce?", tylko zadać pytanie na odpowiednim poziomie szczegółowym, czyli "Czy aktualnie używam właściwego sposobu by wywiercić studnię w wiosce X?". Wielokrotnie widziałem, jak na konkretne pytanie "bogowie kodowania" odpowiadali bardzo szczegółowymi wyjaśnieniami, podsyłali fragmenty własnego kodu lub całe gotowe listingi. Zauważyłem nawet, że chętnie dzielą się swoją wiedzą i kodem ZA DARMO, o ile u pytającego zauważą pewną już wykonaną pracę (naukę, próby napisania czegoś samemu), a nie tylko prośbę typu "dajcie mi" albo "zróbcie to za mnie". Wielokrotnie widziałem pomoc w poprawianiu błędów w kodzie z problemami albo propozycję szerokiej pomocy (w tym i współkodowania). Kluczem był zawsze jednak stopień własnego zaangażowania pytającego, poparty widocznym, a wcześniej wykonanym, kawałkiem własnej pracy.

Niestety, nie ma drogi na skróty (ów oczekiwany super-kurs). Jedyną sprawdzoną drogą jest mozolna praca poprzez czytanie wszystkich możliwych materiałów (i to nieraz wielokrotnie) oraz własnoręczne próby uruchamiania cudzych przykładów (i to wielu), modyfikacji ich, zrozumienia jak działają (i to rozgryzając każdy detal) - aż w końcu próby pisania własnych procedur. Nieraz trzeba pisać sobie własne narzędzia (choćby konwertery formatów, generatory tablic, itp.). Trzeba własnoręcznie oswoić się z potrzebnymi narzędziami - od samego asemblera, monitora pamięci czy debuggera, po packery danych, konwertery, edytory muzyki i graficzne. Nad wyraz przydatna jest też dobra znajomość jakiegoś innego języka programowania (nawet choćby lekceważonego BASICa), by pisać sobie narzędzia pomocnicze, do generowania danych potrzebnych do zrealizowania danego efektu lub wstępnego prototypowania. Trzeba też jeszcze wiedzieć, że sam asembler to nie wszystko. Znając perfekcyjnie procesor Z80 i ZX Spectrum - nie napiszemy automatycznie dema na Amstrada CPC czy GameBoy'a - trzeba zapoznać się z podstawami danej platformy, czyli jak powinien wyglądać Start-Up, przerwania, organizacja pamięci, organizacja ekranu, poeksperymentować z przykładami player'ów do muzyki, mocno wczytać się jak pracują układy specjalizowane danego sprzętu. Sam asembler jest tylko i wyłącznie narzędziem do "konfiguracji" danej platformy oraz do zapisu sposobu jej działania. Nadal trzeba wiedzieć i rozumieć jak działa nasz docelowy sprzęt oraz co i jak chcemy, żeby działało.

Sama znajomość asemblera i docelowego sprzętu to też nie wszystko - trzeba też wiedzieć (lub wymyślić) w jaki sposób na danym sprzęcie zrealizować zakładany algorytm (np. rysowania linii, scrolla, przeliczanie obrotu wektora czy stworzenie fajnej plazmy). Kurs obejmujący wszystkie te elementy trwałby latami, wymagałby niesamowicie wielkiej pracy do stworzenia, a i nadal byłby bardzo ograniczony - tylko do konkretnych przypadków zastosowań. Poniekąd dublowałby to, co już i tak jest w sieci - opisy konkretnych zagadnień, przykładowych procedur, itp. Taki kurs też nie miałby szans opisać "kreatywności kodera", która uruchamia się automatycznie u osoby zapoznanej z podstawami - językiem asemblera, specyfikacją sprzętu i ogólnymi algorytmami tworzenia efektów wizualnych. Taki zestaw narzędzi pozwala na realizację nieskończonej ilości pomysłów - a tego nie obejmie żaden kurs, czy nawet komercyjna książka. Aktualnie istniejące materiały dają przysłowiową wędkę, przykładowe źródłówki dają, powiedzmy, przynętę, by ktoś, kto włoży w to odpowiedni wysiłek, mógł "nałapać ryb do woli".

Niedawno na imprezie "RetroKomp 2014" w Gdańsku legendarny Polonus/QUARTET podzielił się pewną refleksją. Przeczytał gdzieś, że żeby człowiek osiągnął dość wysoki poziom w jakiejkolwiek trudniejszej dziedzinie - musi poświęcić około 10 000 (10 tysięcy!) godzin na jej zgłębianie. Polonus przyznał, że podsumował kiedyś siebie i w swoim czasie poświęcił ok. 16 000 godzin - dlatego miał takie osiągnięcia, jakie miał. Tak więc nie urodził się z tym - po prostu to wypracował. Miał talent, ale i 16 000 godzin "wysiedział" nad tematem i to w czasach, gdy wujek Google jeszcze pewnie nie był w planach swoich twórców.

No dobra (powie ktoś) - to jak zacząć tę zabawę na serio?

Według mnie - najlepiej poprzez "learning by doing", nieoczekiwanie za szybko efektów oraz niezrażanie się licznymi i codziennymi porażkami (zwiecha za wiechą, ale do przodu - doświadczenie rośnie :). Ciężka zabawa, ale nikt nie powiedział, że to zabawa dla każdego. Nagrodą dla wytrwałych jest naprawdę duża satysfakcja, kiedy "coś zadziała", oraz że jeśli raz już poznasz zasadę działania asemblera na któryś z popularnych procesorów, to będziesz w stanie (oczywiście po zapoznaniu się z charakterystyką kolejnej platformy) "w miarę łatwo" zacząć kodować na kolejne. Warto jednak w miarę zgłębić swoja ulubioną (podstawową) platformę, zanim wyruszy się na podbój kolejnych, bo dzięki analogii w technologii z tamtych czasów - wiele rzeczy działa podobnie, a niektóre procedury można łatwo przekodować lub wręcz przenieść między platformami.

Żeby nie być gołosłownym, podam własny przykład z ostatnich tygodni: pierwsze kroki w asemblerze stawiałem "za dziecka" na C64 i Atari 8-bit (proc: 6502). Niewiele tam wywalczyłem, szybko przyszła Amiga i wciągnąłem się w znakomity procesor MC680x0. Jakiś czas temu, przy okazji SV'2012, wydłubałem sobie kilka trainerów na Atari XL/XE (m.in. Stealth i Chuckie Egg, które zawsze chciałem ukończyć) i przypomniałem sobie stary asembler. Przydało mi się to jesienią 2014, kiedy to organizator Silly Venture 2k14 poprosił mnie o pomoc - stworzenie Invitation Intro na przenośną konsolkę Atari Lynx (obchodzącą 25-lecie powstania, a chodzącą na klonie procesora 6502). Zacząłem sam dłubać - w sumie z niewielkim skutkiem, ale miałem podstawy, by odezwać się do Sage'a - jedynego kodera, który wypuścił na tę platformę sensowne scenowe demo (http://www.pouet.net/prod.php?which=10009). Sage pomogł mi skonfigurować asembler/linker/make na Linuxie, wspomógł przykładami, odpowiedział na parę pytań - i zaczęliśmy działać. W kilka tygodni powstało SV2k14 Invitation, głównie oparte na kodzie Sage'a, ale też z kawałkami mojego kodu (http://www.pouet.net/prod.php?which=64409). Co więcej, od tej pory jestem w stanie samodzielnie kodować następne produkcje na Lynx'a. Zaprocentowała praca włożona kiedyś w poznawanie asemblera na C64, jak i późniejsze amigowskie doświadczenie w kodowaniu demek. Zadziałał też mechanizm "coś już wiem, coś już mam - pomóż pójść dalej" i to na tyle, że Sage w pełni zaangażował się w projekt i Invitation powstało na czas, kiedy było najbardziej potrzebne.

Ok, no to w końcu - jak...?

Cóż, u każdego pewnie inaczej, ale w miarę sprawdzona ścieżka może wyglądać mniej więcej tak:

  1. Zebrać możliwie wszystkie dostępne w necie materiały - książki, skany instrukcji, samouczki, tutoriale, artykuły w gazetach, kursy, przykładowe źródłówki - przejrzeć je najpierw pobieżnie i podzielić wg skali trudności, po czym zacząć zgłębiać - czytając nawet kilka razy (i nie ma problemu - najtrudniejsze fragmenty przeskakiwać - kiedyś staną się bardziej zrozumiałe i będzie można do nich powrócić). Stare magazyny dyskowe i papierowe prowadziły zazwyczaj bardzo dobre kursy asemblera, bo pisane przez nastoletnich sceniarzy - bez inżynierskiego zadęcia, czyli przystępnie i bez zbędnej szczegółowości.
  2. Pozbierać i uruchomić narzędzia - asemblery (i to kilka, wybrać najwygodniejszy dla siebie), packery/depackery, konwertery grafiki, monitory pamięci i dyskowe, emulatory (takie czasy), itp. "Pobawić się nimi", w sensie poznać jak najlepiej ich funkcjonalność, poczytać instrukcje, gdzie często znajdują się podstawowe i specjalnie dobrane przystępne przykłady.
  3. Koniecznie zapoznać się (a nawet zaprzyjaźnić) z jakimś debugger'em i ewentualnie cartridge'm typu freezer (Action Replay, itp.). Zacząć zaglądać do gier i demek z poziomu freezer'a - podmieniać wartości w rejestrach i pamięci, wyszukiwać wartości. Coś popsuć, zablokować, zawiesić, nabroić. Podmienić tekst scrolla (tak - jeśli jest to nauka i nie ma się na celu przywłaszczenie sobie autorstwa produkcji - to nie jest lamerstwo, tylko etap nauki). Podmienić tekst najpierw w pamięci, potem na dysku.
  4. Czytać możliwie wszystkie zebrane materiały - opis procesora, wszystkich instrukcji, trybów adresowania. Robić notatki, kolekcjonować najbardziej przydatne materiały. Pisać małe programiki, by zobaczyć, jak działa dana instrukcja, po czym śledzić wykonanie tego kodu pod debugger'em, zaglądając w pamięć, jak wygląda rozłożony kod i jak wyglądają efekty jego działania na układach specjalizowanych, jak i na pamięci.
  5. Ściągnąć jakieś kursy/przykłady robienia trainer'ów i przejść kilka z nich. Przyjemne to i pożyteczne - własnoręcznie zrobiona nieśmiertelność daje dużo satysfakcji, a do tego pokazuje, jak "patch'ować" kod w pamięci, by niczego nie zepsuć, jak w ogóle wygląda gra od strony procesora, uczy jak rozpoznać i oddzielić kod od danych, itp.
  6. Uruchamiać wszystkie możliwe przykłady, analizować je jak działają i koniecznie - modyfikować. Sprawdzać jaki efekt przyniesie dana modyfikacja, czytając równolegle opis custom chip'ów i posiadanych przez nie możliwości. Robić notatki z "własnych odkryć".
  7. Po zabawie z przykładowymi efektami - skupić się na przykładach "start-up'ów" i napisać na ich podstawie własny, który od tej pory będzie własnym środowiskiem do testowania swojego i przykładowego kodu testowego, ale i już do tworzenia własnych produkcji.
  8. Ściągnąć kilka, uruchomić i wybrać najlepiej nam pasujący player do muzyki, połączyć go z własnym start-up'em. Tu korzysta się z "gotowców" (music replayer, dostarczane zwykle wraz z edytorem muzycznym) i jest to ogólnie przyjęta praktyka. Zapoznać się z przerwaniami, które najczęściej są wykorzystywane do "podwieszenia player’a muzyki" i synchronizacji.
  9. Zapoznać się z językiem wysokiego poziomu (C, BASIC, Pascal, itd.), by generować sobie tablice wartości potrzebnych do efektów graficznych lub konwertować na format prosty do wykorzystania w naszym kodzie.
  10. Przeanalizować kod kilku prostych efektów, poznać jak wygląda tworzenie ekranu graficznego (najlepiej w kilku popularnych trybach), ustawianie kolorów, stawianie jednego punktu, czy rysowanie linii. Zobaczyć, jak wygląda korzystanie z wygenerowanych tablic sinusa/cosinusa. Stworzyć sobie (i dla siebie) pierwsze małe interko - byle jakie, ale z grająca muzyką, scrollem, jakąś statyczna grafiką i prostym efektem (typu skaczący bar lub sprite'y). Nie jest to robota bezsensowna, bo dzięki temu powstanie baza kodu pod przyszłe, poważniejsze i bardziej dopracowane produkcje.
  11. Oglądać dema, zastanawiać się "jak to jest zrobione" i próbować napisać własną wersję efektu. Jeśli jest to na razie za trudne - pytać na forum lub ściągnąć i przeanalizować gotowe przykłady (napisać jednak ostatecznie własną wersję).
  12. Czytać wybrane koderskie forum dyskusyjne, zaglądać w jego archiwum, czytać najciekawsze tematy.
  13. Jak najwięcej pisać własnych, nawet bardzo prostych efektów, eksperymentować z ich parametrami (czasem jakimś ustawieniem modulo można z jednego efektu zrobić kilka innych - nietuzinkowych, własnych).
  14. Zdobyć i przeglądać oficjalną literaturę na temat grafiki komputerowej (wzory na obroty, perspektywę, cieniowania, itd.) lub wyszukać tego typu opisy w sieci (jest tego dużo).
  15. Pojechać na jakieś party, znaleźć jakiegoś kodera, postawić mu piwo (niejedno!!! ;-) i wypytać o wszystko - jakich narzędzi używa, co omijać, jak napisać to, czy tamto...

...a potem zabrać się na poważnie za pisanie własnego compo-entry na kolejne party. :)

Innymi słowy: nie ma innej metody - trzeba "ubrudzić ręce".

Powodzenia.

Sachy / Wanted Team ^ Resistance ^ Lamers
(listopad 2014)