0692 - Język FORTH cz.6

W poprzednim odcinku zajmowaliśmy się słowem WORD. Było ono używane do wprowadzenia dowolnego ciągu znaków do komputera. Wielu czytelników zauważyło zapewne, że nie da się użyć tego słowa do wprowadzania tekstu w czasie wykonywania programu, gdyż nie czeka ono na wykonanie tej czynności.

Aby tego dokonać, można wykorzystać słowo QUERY. Słowo to czeka na wprowadzenie tekstu o długości mniejszej od 80 znaków. Umieszcza tekst w buforze terminalu, skąd można go przesłać w inne miejsce. Adres bufora terminalu można odczytać ze zmiennej TIB. Słowo to jest wykorzystywane przez system operacyjny języka FORTH. Użycie go wewnątrz programu wprowadzi tekst do bufora terminalu, lecz zaraz po tym system FORTH-a będzie się starał zinterpretować tekst jako nazwę słowa ze słownika. Takie działanie spowoduje prawie zawsze sygnalizację błędu. Aby tego uniknąć, należy bezpośrednio za QUERY zastosować słowo WORD, które przyjmuje tekst spod TIB jako nową nazwę. Przykład :

 : INPUT$ QUERY 155 WORD HERE ; RETURN

Nasze nowo zadeklarowane słowo wprowadza tekst (aż do znaku o kodzie 155, czyli RETURN) pod adres, który wyprowadzi na stos słowo HERE. Adres ten będzie zostawiany na stosie po każdym użyciu słowa INPUT$. Sprawdźmy :

 : TEST INPUT$ CR COUNT TYPE ; RETURN

Po wykonaniu słowa TEST komputer będzie czekał na wprowadzenie tekstu, a następnie wyświetli go w nowej linii. Słowo INPUT$ działa podobnie jak instrukcja INPUT ze zmienną tekstową w Atari BASIC. Stworzyliśmy słowo wprowadzające dowolny tekst, co jednak uczynić, gdy wprowadzamy liczbę ? Gdyby użyć tylko słowa INPUT$, mielibyśmy dostęp do liczby zapisanej w formie ciągu cyfr. Aby uzyskać zamianę tego ciągu na wartość, należy użyć słowa NUMBER. Słowo to przekształca ciąg cyfr, poprzedzonych bajtem długości, na wartość. Parametrem wejściowym tego słowa jest adres początku ciągu znaków, a wartością wyjściową, pozostawioną na stosie, są dwie liczby określające wartość ciągu cyfr. Słowo NUMBER przekształca zapis na liczbę 4-bajtową, co możemy odczytać jako dwie liczby 2-bajtowe. Gdy korzystamy tylko z zakresu mieszczącego się w dwóch bajtach (a tak jest najczęściej), kasujemy słowem DROP liczbę 0 ze szczytu stosu i wykorzystujemy jedynie liczbę znajdującą się niżej.

Stwórzmy teraz słowo wprowadzające liczbę z klawiatury i zostawiające jej wartość na stosie :

 : INPUT INPUT$ NUMBER DROP ; RETURN

i sprawdźmy pisząc :

 INPUT . RETURN

DZIAŁANIA NA BLOKACH PAMIĘCI

W powyższym opisie, dotyczącym słów wprowadzających ciąg znaków, wspomniałem o przenoszeniu go w inne miejsce. Na szczęście, nie trzeba tworzyć w języku FORTH słowa wykonującego to zadanie, gdyż posiada on je w słowniku. Słowo to ma nazwę CMOVE i wymaga trzech liczb jako parametrów wejściowych. Pierwsza liczba określa adres, spod którego pobieramy dany blok pamięci. Druga - to adres docelowy, a trzecia określa długość przenoszonego bloku. Aby sprawdzić jego działanie, wyczyśćmy ekran (SHIFT i CLEAR). Następnie w lewym górnym rogu ekranu piszemy dowolne zdanie np. Ala ma kota. Nie zatwierdzając napisu klawiszem RETURN przenosimy kursor przy pomocy kilku naciśnięć klawisza BREAK w dolną część ekranu. Po tych czynnościach piszemy :

 88 @ DUP 80 + 40 CMOVE RETURN

Nasz napis przeniesiony został o dwie linie niżej. Słowo CMOVE jest napisane w języku maszynowym, posiada więc bardzo dużą szybkość działania i znajduje szerokie zastosowanie. Uwaga : CMOVE zaczyna przenoszenie od pierwszego bajtu i przesuwa działanie ku wyższym adresom. Jeżeli adres docelowy jest wyższy od adresu pobierania o małą wartość i obszary w związku z tym częściowo się pokrywają, dochodzi do utraty części danych. W takich sytuacjach należy stosować słowo CMOVE> występujące w niektórych implementacjach języka FORTH. Niestety w Extended fig-FORTH nie ma go w słowniku i należy je stworzyć samemu. Zajmiemy się tym podczas omawiania ASSEMBLERA FORTH-a.

Często podczas programowania zachodzi potrzeba wypełniania pewnego obszaru pamięci tą samą wartością. Funkcję tę spełnia słowo FILL. Piszemy :

 88 @ 960 33 FILL RETURN

Po wykonaniu powyższej sekwencji cały ekran został wypełniony literkami "A". Pierwszym parametrem słowa FILL (88 @) był adres początku wypełnianego obszaru. Drugi (960) - to długość tego obszaru, a trzeci - wartość wypełniania. W języku FORTH istnieją jeszcze dwa słowa zbudowane w oparciu o słowo FILL. Są to : ERASE oraz BLANKS.

Oba potrzebują jako parametr wejściowy adres obszaru oraz jego długość. Pierwsze z nich wypełnia podany obszar zerami (czyszczenie), a drugie kodami spacji.

EDYTOR WPROWADZANIA

Poznane do tej pory słowa języka FORTH, umożliwiają nam tworzenie dłuższych programów. Niestety, wprowadzanie nawet kilku wierszy w trybie bezpośrednim jest bardzo uciążliwe, gdyż trudno ustrzec się od błędów. Także tworzone słowa musiały mieścić się w dwóch liniach. Aby usunąć te niedogodności i ułatwić czytelnikom wprowadzanie dłuższych programów w języku FORTH, przedstawiam poniżej Edytor Wprowadzania. Spełnia on tą samą funkcję jak Generator Kodów Kontrolnych w języku BASIC. Działanie EDW (Edytora Wprowadzania) jest jednak nieco inne. Podstawową różnicą jest konieczność wprowadzania kodów kontrolnych razem z danymi. Dzięki tej zmianie komputer zajmuje się kontrolowaniem poprawności, nie ma więc możliwości wprowadzenia błędnego zapisu.

Aby zainstalować edytor, należy wklepać poniższe sekwencję do komputera, oczywiście po wczytaniu FORTH-a. Podczas tych czynności nie będziemy mieli żadnej kontroli poprawności wprowadzanego tekstu, należy więc robić to ze szczególną uwagą. Wprowadzanie odbywać się będzie w trybie bezpośrednim, czyli w takim, jaki używaliśmy do wprowadzania prezentowanych przykładów. Każda z sekwencji zaczyna się na początku linii, a kończy znaczkiem (RE), gdzie oczywiście należy nacisnąć RETURN. Każdy taki zapis wprowadzamy jednym ciągiem aż do (RE), nie zwracając uwagi na miejsce przeniesienia do nowej linii. Wszyscy posiadacze magnetofonów powinni najpierw wpisać :

 0 WARNING ! RETURN

Właściciele stacji dysków wkładają do stacji dyskietkę z językiem FORTH. Jeżeli pojawi się napis "ok", możemy wprowadzać następną sekwencję, gdy to nie nastąpi, musimy spróbować jeszcze raz. Można poprawiać błędny zapis widniejący jeszcze na ekranie, należy jednak wtedy usunąć komunikat o błędzie, ustawić kursor wewnątrz napisu i nacisnąć klawisz RETURN. Uwaga na spację ! A więc do dzieła :

 ( EDYTOR WPROWADZANIA ) (RE)
 : <=< OVER > >R < R> * ; (RE)
 37000 CONSTANT AD0 (RE)
 0 VARIABLE AB (RE)
 0 VARIABLE *K (RE)
 0 VARIABLE LIN (RE)
 0 VARIABLE EN (RE)
 : AF AD0 AB @ + ; (RE)
 : B32 32 BASE ! ; (RE)
 : NK IF 0 0 ELSE B32 AF NUMBER DECIMAL 1024 U/ ENDIF ; (RE)
 : N1 0 AF COUNT OVER + SWAP ; (RE)
 : NU N1 DO I C@ 47 OVER 58 <=< 64 ROT 87 <=< + 0= + LOOP NK ; (RE)
 : K0 1 *K +! C@ *K @ * EN +! + 1024 MOD ; (RE)
 : K1 DO I K0 I C@ 0= IF I 38 BLANKS LEAVE ENDIF LOOP ; (RE)
 : KP 0 *K ! 4 AF C! 32 AF 5 + C! NU 0 EN ! ; (RE)
 : KOD= KP >R >R 0 AF 38 + AF 6 + K1 R> = R> LIN @ = SWAP OVER * ; (RE)
 : .R2 0 <# # # #> TYPE SPACE ; (RE)
 : ?L LIN @ B32 .R2 DECIMAL ; (RE)
 : WP 125 EMIT 1 LIN +! ." Wprowadz linie" ?L CR CR ; (RE)
 : ?DOB DROP AF 6 + AF 32 CMOVE 32 AB +! WP 1 ; (RE)
 : ?Z CR CR AF 1+ 37 TYPE 155 EMIT 28 EMIT 0 ; (RE)
 : LL ." Teraz ma byc linia " ?L ; (RE)
 : ?ZLE 125 EMIT 0= IF LL ELSE ." Popraw:" ENDIF ?Z ; (RE)
 : KO KOD= IF ?DOB ELSE ?ZLE ENDIF EN @ 1442 = * ; (RE)
 : GO 125 EMIT CR ." GOTOWE!" CR ; (RE)
 : E1 1 82 C! 0 AB ! 0 LIN 1 WP ; (RE)
 : BBL AF 1024 AB @ OVER MOD - DUP AB +1 BLANKS ; (RE)
 : EDW E1 BEGIN AF 39 ERASE AF 1+ 37 EXPECT KO UNTIL BBL GO ; (RE)

Poniższe słowa wprowadzają tylko właściciele stacji dysków :

 : BSAV OVER + SWAP DO DUP I 0 R/W B/BUF + LOOP DROP ; (RE)
 : EDW-SAVE AD0 SWAP B/SCR * AB @ B/BUF / BSAV ; (RE)

A kolejne właściciele magnetofonów :

 1 VARIABLE CD (RE)
 : --> 0 CD ! ; (RE)
 BF< 16 8 DO DUP I 8 - B/BUF * + I BUFFER B/BUF CMOVE LOOP DROP ; (RE)
 : EL EMPTY-BUFFERS DUP BF< 1 CD ! 1 LOAD ; (RE)
 : EDW-COMP AD0 0 WARNING BEGIN EL 1024 + CD @ UNTIL DROP ; (RE)

Jeśli wszystko przebiegło poprawnie, jesteśmy od tej pory szczęśliwymi posiadaczami Edytora Wprowadzania. No, nie całkiem, gdyż należy pamiętać o utrwaleniu naszej pracy słowem SAVE na dysk, lub CSAVE na kasetę. Uwaga : w linii zaczynającej się od : --> po zatwierdzeniu klawiszem RETURN, pojawi się napis "MSG # 4" lub "Isn't unique", a dopiero na końcu "OK". Nie należy się tym przejmować, gdyż komunikat informuje o deklaracji słowa o nazwie będącej już w pamięci. Edytor wywołujemy pisząc EDW. W tym momencie pojawi się napis : "Wprowadź linię 01", podajemy więc linię, której kod zaczyna się od 01. Wprowadźmy na próbę znane nam słowa :

 011M ( 0ZEGAR! ZEGAR@ )
 0200
 03SM : 0ZEGAR! 0 19 ! ;
 04HN : ZEGAR@ 20 C@ 19 C@ 256 * ;
 05D2 ( END )

Pierwsza linia zawiera komentarz, który będzie nagłówkiem ekranu. Ostatnia zawiera instrukcję wyjścia z edytora. Po wprowadzeniu każdej linii należy nacisnąć RETURN. Jeżeli edytor nie zawiera błędów, to po wpisaniu z jego pomocą powyższych linii, pojawi się napis GOTOWE!.

W tym momencie właściciele magnetofonów mogą skompilować wprowadzony tekst słowem EDW-COMP ., a następnie zapisać na taśmie za pomocą CSAVE .

Posiadacze stacji dysków, mogą zapisać program w wersji źródłowej słowem EDW-SAVE.

Uwaga : Przed wywołaniem tego słowa należy podać numer ekranu, od którego program zostanie zapisany. Przypominam, że ekrany mogą mieć numery od 1 do 87. Aby skompilować tak zapisany program źródłowy, należy użyć sekwencji :

 NRekr LOAD RETURN

W miejsce NRekr wstawiamy numer ekranu, od którego program został zapisany. Wszystkim posiadaczom stacji dysków polecałbym wpisanie tekstu źródłowego Edytora Wprowadzania, przy pomocy tego edytora wprowadzonego wcześniej w trybie bezpośrednim. Następnie zapisujemy tekst źródłowy na czystym dysku sformatowanym w gęstości S lub E, pisząc np. 5 EDW-SAVE . Od tej pory będziemy mogli dołączać edytor do FORTH-a przez wywołanie 5 LOAD . Tekst edytora (tym razem już z kodami) zamieszczam poniżej.

 01J5 ( EDytor Wprowadzania )
 0200
 03E5 ( w jezyku FORTH )
 0400
 05CO ( autor: Roland Pantola )
 065T ( [c] 1992 Tajemnice Atari )
 0700
 08JG : <=< OVER > >R < R> * ;
 09NK 37000 CONSTANT AD0
 0AM1 0 VARIABLE AB
 0BH2 0 VARIABLE *k
 0CV4 0 VARIABLE LIN
 0DSD 0 VARIABLE EN
 0EA7 : AF AD0 AB @ + ;
 0FHP : B32 32 BASE ! ;
 0G0V : NK IF 0 0 ELSE B32 AF NUMBER
 0HL8 DECIMAL 1024 U/ ENDIF ;
 0IH0 : N1 0 AF COUNT OVER + SWAP ;
 0JM9 : NU N1 DO I C@ 47 OVER 58 <=<
 0KA0 64 ROT 87 <=< + 0= + LOOP NK ;
 0LRU : K0 1 *K +! C@ *K @ * DUP EN
 0M6V +! + 1024 MOD ;
 0N6A : K1 DO I K0
 0O3M I C@ 0= IF I 38 BLANKS
 0PPI LEAVE ENDIF LOOP ;
 0QPL : KP 0 *K ! 4 AF C!
 0R90 32 AF 5 + C! NU 0 EN ! ;
 0SH5 : KOD= KP >R >R 0
 0T5M AF 38 + AF 6 + K1
 0U42 R> = R> LIN @ = SWAP OVER * ;
 0VA1 -->
 1000
 1100
 1200
 13LJ : .R2 0 <# # # #> TYPE SPACE ;
 1496 : ?L LIN @ B32 .R2 DECIMAL ;
 15EG : WP 125 EMIT 1 LIN +!
 1661 ." Wprowadz linie " ?L CR CR ;
 17G4 : ?DOB DROP AF 6 + AF 32
 18G7 CMOVE 32 AB +! WP 1 ;
 19B4 : ?Z CR CR AF 1+ 37 TYPE
 1AHM 155 EMIT 28 EMIT 0 ;
 1BS2 : LL ." Teraz ma byc linia "
 1CH3 ?L ;
 1DB4 : ?ZLE 125 EMIT 0= IF LL
 1EFF ELSE ." Popraw:" ENDIF ?Z ;
 1F0F : KO KOD= IF ?DOB ELSE ?ZLE
 1GTQ ENDIF EN @ 1442 = * ;
 1HH8 : GO 125 EMIT
 1IK1 CR ." GOTOWE!" CR ;
 1JIS : E1 1 82 C! 0 AB ! 0 LIN !
 1KI3 WP ;
 1LGM : BBL AF 1024 AB @ OVER MOD -
 1MT2 DUP AB +! BLANKS ;
 1N00
 1OMD : EDW E1 BEGIN AF 39 ERASE AF
 1PIP 1+ 37 EXPECT KO UNTIL BBL GO ;
 1Q00
 1RK4 ( ---
 1SVG ( wlancza edytor wprowadzania )
 1T00
 1UA1 -->
 1V00
 2000
 21IP ( EDW-SAVE)
 2200
 23MA : BSAV OVER + SWAP DO DUP I 0
 24TK R/W B/BUF + LOOP DROP ;
 2500
 26IP : EDW-SAVE AD0 SWAP B/SCR *
 27RN AB @ B/BUF / BSAV ;
 2800
 29QK ( NREK ---
 2AJ8 ( zapisuje wprowadzony blok na
 2BEB ( dysk od ekranu numer NREK
 2CD2 ( END )

Uwaga ! Edytor Wprowadzania nie będzie działał w ELKOMP-FORTH, gdyż implementacja ta nie posiada możliwości poprawiania wprowadzonego tekstu. Najlepszym wyjściem jest wprowadzenie edytora w implementacji Extended fig-FORTH. Posiadacze magnetofonów powinni poszukać tej implementacji u kolegów ze stacją dysków, a następnie nagrać na kasetę słowem CSAVE. Proszę o listowne relacje z prób instalowania EDW w swoich komputerach.

Roland Pantoła
Tajemnice Atari, Nr.06-07/1992r.