Tajemnice ATARI

FORTH


    W pierwszym odcinku prezentującym język FORTH poznaliśmy dwa podstawowe słowa: ":" oraz ";" (dwukropek i średnik). Znajomość ich działania będzie nam obecnie potrzebna, dlatego też radzę zajrzeć do poprzedniego numeru TA

    Nie będę przedstawiał języka FORTH w sposób chronologiczny. Zwolenników tej metody odsyłam do studiów na wydziale informatyki, gdzie pierwszy kontakt z językiem programowania zaczyna się od poznania błędów, a kończy na metodach poprawnego programowania. Postawmy przed sobą pierwsze praktyczne zadanie do rozwiązania w języku FORTH: Napisać słowo odczytujące aktualny stan zegara. Nazwijmy je "ZEGAR@". Aby rozwiązać ten problem, niezbędna będzie znajomość podstawowych operacji na liczbach.

   W języku FORTH standardowa liczba zajmuje dwa bajty. Jest to więc liczba całkowita z zakresu 0-65535. W tym momencie musimy wesprzeć ten wykład środkiem audiowizualnym, jakim jest komputer. Włączamy więc naszą ukochaną maszynkę i wczytujemy FORTH. Gotowe? Jeśli tak, to napiszmy na ekranie liczbę 3 i zatwierdźmy klawiszem RETURN. Pojawił się napis OK, czyli w porządku. Co jednak stało się z tą liczbą? Czy zginęła w bezkresnych obszarach pamięci naszego komputera? Napiszmy teraz "." (kropka), zatwierdzając jak poprzednio klawiszem RETURN. Napisana wcześniej liczba została wyświetlona na ekranie. Stąd wniosek, że przebywała ona jakiś czas w pamięci komputera. Czy było to ściśle określone miejsce? Napiszmy teraz kolejno trzy liczby:

1 RETURN
2 RETURN
3 RETURN

   W miejscu gdzie widnieje znaczek RETURN należy nacisnąć taki klawisz, nie należy tego przepisywać. Co stało się z tymi liczbami, czy liczba następna skasowała poprzedną? Ano sprawdźmy, piszemy:

. RETURN
. RETURN
. RETURN

   Na ekranie pojawiły się kolejno: 3 2 1. Odzyskaliśmy więc wszystkie wprowadzone liczby, ale od końca.

    Wszyscy, którzy mieli do czynienia z ASEMBLEREM (a wśród czytelników TA na pewno takich nie brakuje), znają ten sposób składowania liczb. Strukturą, która zapamiętała nasze liczby, jest STOS. W języku FORTH stos pełni ważną rolę "systemu nerwowego", bez którego zamarłby przepływ informacji (danych) między poszczególnymi słowami. Zastępuje on w znacznej części ZMIENNE wykorzystywane do tęgo celu w innych językach.

CO TO JEST STOS?

   Dla początkujących kilka słów wyjaśnienia, co to jest stos? Wyobraźmy sobie, ze nasze liczby 1, 2, 3 zapiszemy na oddzielnych kartkach papieru (mogą być gliniane tabliczki). Następnie kładziemy na stole kartkę z liczbą 1, na niej - z 2, a na końcu z liczbą 3. Tę stertę kartek nazywamy STOSEM. Jeżeli chcemy odzyskać te liczby, ściągamy je ze stosu. Na wierzchołku mamy liczbę 3; po zdjęciu jej ze stosu uzyskujemy dostęp do 2, a na końcu - 1. W taki to sposób postępował komputer ściągając ze stosu 1 wyświetlając na ekranie nasze liczby. Po co jednak komplikować sobie życie układając liczby jedną na drugiej? Można przecież rozłożyć kartki na całej powierzchni stołu, mielibyśmy wtedy bezpośredni dostęp do każdej liczby. To samo można by wykonać w pamięci komputera. Zauważmy jednak, że składając liczby na stos komputer nie potrzebował żadnej innej informacji oprócz samej liczby. Chcąc umieścić liczbę w dowolnym miejscu pamięci, musimy podać adres. Także podczas pobierania liczby należałoby określić miejsce.

LICZBY...

   Skoro znamy już zasadę funkcjonowania stosu, powróćmy do samych liczb. Wspomniałem, że zajmują one 2 bajty pamięci, a więc jedna komórka stosu zajmuje tyle samo, gdyż musi pomieścić całą liczbę. Czy jest tak rzeczywiście? Napiszemy teraz największą liczbę dwubajtową, czyli:

65535 RETURN

   Znanym już nam sposobem wywołujemy ją na ekran przy pomocy sekwencji:

. RETURN

   Ukazała się liczba: -1. Czyżby komputer się pomylił ? Piszemy jeszcze raz:

65535 RETURN

   Tym razem zamiast słowa "." (kropka) wpisujemy:

U. RETURN

Na ekranie widzimy wprowadzoną liczbę. Co się więc stało za pierwszym razem ? Słowo "." (kropka) interpretuje liczbę na stosie jako tzw. liczbę ze znakiem. Siódmy bit bardziej znaczącego bajtu liczby jest interpretowany jako znak minus. Dzięki temu uzyskujemy zakres od -32768 do 32767.

   Dla początkujących wyjaśnię może, co to znaczy siódmy bit bardziej znaczącego bajtu. Przedstawmy naszą liczbę w systemie dwójkowym, a wszystko będzie jasne:

   BZB       MZB

11111111 11111111

   7 bit bardziej znaczącego bajtu liczby zaznaczono strzałką. BZB to bardziej znaczący bajt. MZB to mniej znaczący bajt.

   Nie będę na razie tłumaczył całego mechanizmu liczb ze znakiem, należy jedynie pamiętać, że liczby większe od 32767 będą traktowane jako ujemne. Wykonajmy jeszcze jedną próbę wprowadzania liczb na stos; tym razem piszemy:

32768 RETURN

i wyświetlamy na ekranie:

. RETURN

   Następnie wpisujemy:

32768 RETURN

i wyświetlamy:

U. RETURN

   Mam nadzieję, że jest jasne dla czytelników to, co się stało podczas wykonywania tych działań.

Poznaliśmy dwa nowe słowa "." i "U." (kropka i U kropka) wyświetlające liczby ze szczytu stosu w dwóch różnych formatach. Przyjęło się, że litera U w nazwie oznacza interpretowanie danych na stosie jako liczby bez znaku.

DZIAŁANIA

   Aby móc zrealizować zadanie postawione na początku artykułu, musimy poznać podstawowe działania na liczbach. Są to: +, -, *, /. Znamy je przecież dobrze ze szkoły. Tym, którzy do szkoły nie chodzili, przypominam, że są to odpowiednio: dodawanie, odejmowanie, mnożenie i dzielenie. Chcąc je wypróbować, musimy poznać

ODWROTNĄ NOTACJĘ
POLSKĄ

   Wszystkim, którzy w tym momencie pragną porzucić dalszą lekturę tego artykułu, radziłbym się nie śpieszyć. Mam nadzieję, że uda mi się objaśnić ten odstraszający termin. Zacznijmy może od stwierdzenia, że wszystkie słowa języka FORTH (standardowe jak i stworzone przez nas) są równoprawne. Można więc powiedzieć, że w języku FORTH panuje idealna demokracja. Poznane do tej pory słowa "." lub "U." potrzebowały obecności jednego parametru na stosie: była to liczba zajmująca aktualny szczyt stosu. Działania +, -, * i / są także słowami FORTHa z tą różnicą, że potrzebują dwóch parametrów (danych wejściowych). Wszystkim zapewne wiadomo, że operacja + jest dokonywana na dwóch liczbach. Ponieważ każde słowo języka FORTH (wymagające parametrów wejściowych) pobiera dane ze stosu, także działania matematyczne szukają liczb na stosie. Uczono nas w szkole, że do rozwiązania zadania są potrzebne dane wejściowe; następnie wykonuje się zadanie i znajduje wartość szukaną. Logika zapisu działań matematycznych wyniesiona ze szkoły jest jednak zupełnie inna. Przyjrzyjmy się zapisowi: 2+3. Najpierw piszemy pierwszą daną: 2, potem działanie, które należy wykonać (ale jak wykonać dodawanie na jednej danej?), i dopiero za działaniem znajduje się druga potrzebna dana: 3. W języku FORTH będzie to wyglądało następująco:

2 3 + RETURN

   Pamiętać o spacjach! Działanie przebiegło poprawnie i na ekranie pojawił się napis OK. Co się jednak stało z wynikiem? Nie został przecież wyświetlony na ekranie. Większość czytelników domyśla się zapewne,że wynik znajduje się na stosie. Sprawdźmy, pisząc:

. RETURN

   Gdyby nie wyświetlać tej sumy na ekranie, mogłaby ona posłużyć jako dana wejściowa dla następnej operacji. Napiszmy więc jeszcze raz:

2 3 + RETURN

   Mamy na stosie wyliczoną sumę, dopiszmy jeszcze:

4 * RETURN

   (czy wiesz, dlaczego jedna dana?) i wyświetlamy wynik:

. RETURN

   Zostało wykonane działanie, które w szkolnym zapisie miałoby postać:

(2+3)*4

Widać wielką zaletę Odwrotnej Notacji Polskiej, a mianowicie brak nawiasów wymuszających pierwszeństwo dla danego działania. Wszystkie działania w języku FORTH są wykonywane zawsze w kolejności zapisu. Czytelnikom proponowałbym spróbować swych sił w następującym przykładzie:

(1+2*3)+(1+2)*(2+3)

Proszę zapisać to wyrażenie w ję- zyku FORTH i wyświetlić wynik. Czytelnik, który pierwszy prześle poprawny zapis na adres redakcji otrzyma bezpłatnie grę: "A.D.2044".

   Powróćmy jednak do naszego głównego celu, a mianowicie stworzenia słowa ZEGAR@ (znak "@" nazywa się po angielsku "at", czytaj: et; w Polsce bywa zwany robakiem, embrionem, małpą). Niezbędne okażą się nam jeszcze dwa bardzo ważne słowa języka FORTH:

C@ i @

   Pierwsze z nich umieszcza na stosie zawartość komórki, której adres znajdował się na stosie jako dana wejściowa. Drugie słowo wykonuje to samo, lecz pobiera wartość z dwóch kolejnych komórek pamięci, gdzie wartość spod wyższego adresu będzie traktowana jako starszy bajt liczby. Uwaga: słowa te interpretują oczywiście daną wejściową (adres) jako liczbę bez znaku. Wypróbujmy działanie tych słów na komputerze. Piszemy:

82 C@ . RETURN

   Na ekranie została wyświetlona szerokość lewego marginesu. Spróbujmy jeszcze następującego zapisu:

88 @ . RETURN

   Na ekranie pojawiła się liczba określająca adres początku ekranu. A teraz ciekawostka: co wyświetli następująca sekwencja słów:

88 @ C@ . RETURN

   Przeważnie liczbę 0, gdyż została pobrana wartość z pierwszej komórki ekranu, a tam znajdował się kod ekranowy spacji. Poznaliśmy do tej pory wszystkie słowa niezbędne do wykonania zadania postawionego na początku artykułu. Musimy sobie jeszcze przypomnieć, gdzie znajdują się komórki zegara. Mają one adresy: 18, 19 i 20. Komórka 20 zwiększa swoją wartość co 1/50 sekundy, komórka 19 - po każdym przepełnieniu komórki 20, a 18 - po przepełnieniu 19. Nasz pierwszy zegar zbudujemy na dwóch komórkach 19 i 20 . Nie można wykorzystać słowa @ do pobrania zawartości tych komórek (dlaczego?). Musimy zastosować słowo C@ i pobrać wartości z każdej komórki oddzielnie. Piszemy deklarację słowa ZEGAR@;

: ZEGAR@ 20 C@ 19 C@
256 * + ; RETURN

   Wyjaśnię kolejne kroki naszego postępowania:

: - służy do deklarowania słów (otwiera deklarację),

ZEGAR@ - taką nazwę będzie miało tworzone słowo.

   Słowa znajdujące się między nazwą a średnikiem, zostaną zakodowane w pamięci i będą wykonane dopiero po wywołaniu stworzonego słowa. Będą one działały w następujący sposób:

20 C@ - pobierze wartość z komórki 20 i umieści ją na stosie,

19 C@ - to samo dla komórki 19,

256 * - wprowadzi na stos liczbę 256 i wykona mnożenie na dwóch liczbach będących najbliżej szczytu stosu. Będzie to zawartość komórki 19 i liczba 256.

+ - doda wyliczony iloczyn do wartości pobranej z komórki 20,

; - kończy deklarację nowego słowa.

   Jeżeli kompilacja zadeklarowanego przez nas słowa przebiegła prawidłowo, znajdzie się ono w słowniku. Sprawdzamy:

VLIST RETURN

Teraz możemy sprawdzić jego działanie:

ZEGAR@ . RETURN

i po chwili znów:

ZEGAR@ . RETURN

   Liczby wyświetlone na ekranie różnią się od siebie, a więc nasz zegar "chodzi". Mamy nowe słowo w pamięci, lecz po wyłączeniu komputera tracimy je bezpowrotnie. Co zrobić, aby tego uniknąć? Jeżeli posiadamy implementację Extended fig-FORTH, sprawa jest prosta. Posiadacze magnetofonów piszą

CSAVE RETURN

i zapisują język FORTH rozbudowany o słowo ZEGAR@ na czystą kasetę. Właściciele stacji dysków robią to samo, lecz słowem

SAVE RETURN

Uwaga!: dyskietka musi być sformatowana w gęstości S lub E. Powinna być czysta, gdyż wszystkie dane wcześniej zapisane (zwłaszcza w początkowych sektorach) mogą ulec zniszczeniu.


Roland Pantoła

Powrót na start | Powrót do spisu treści | Powrót na stronę główną

Pixel 2001