0193 - Język FORTH cz.11

W poprzednim numerze TA zamieszczony został listing Edytora FORTH-a. Edytor ten napisałem cztery lata temu. Używam go do tej pory i sądzę, że czytelnikom zainteresowanym programowaniem w języku FORTH, będzie on dobrze służył. W tym odcinku zajmiemy się opisem pozostałych funkcji tego edytora.

Gdy wywołamy edytor (np. 10 L). na ekranie ukażą się dwie pionowe linie wyznaczające lewy i prawy margines pola edycji. Z lewej strony znajduje się numer aktualnie wywoływanego ekranu, oraz liczba określająca ilość linii wprowadzonych do bufora. Jeden ekran FORTH-a składa się z 1024 bajtów i najczęściej bywa przedstawiany w postaci 16 linii po 64 znaki. Ja zastosowałem linie o długości 32 znaków, gdyż mieszczą się one w całości na ekranie wyświetlanym przez nasz komputer. W związku z tym cały ekran posiada 32 linie.

Każdą z linii wyświetlanych na ekranie można wprowadzić do bufora. Linię znajdującą się w buforze można następnie umieścić w dowolnym miejscu bieżącego ekranu lub przenieść do innego.

Aby wprowadzić linię do bufora należy najechać na nią kursorem, a następnie nacisnąć SHIFT i DELETE. Gdy powtórzymy tę czynność, wprowadzimy do bufora kolejną linię tekstu. Możemy w taki sposób umieścić tam cały ekran, a następnie przenieść go pod inny numer. Wyprowadzenie linii z bufora następuje po naciśnięciu klawisza TAB.

Uwaga: klawisz RETURN nie pełni w tym edytorze funkcji znacznika końca linii, gdyż wszystkie linie mają zawsze długość 32 znaków (także puste). Klawisz ten przenosi jedynie kursor do początku nowej linii, oraz czyści bufor.

Przejdźmy teraz do opisu edytora w wersji kasetowej, gdyż różni się on znacznie od wersji przeznaczonej dla stacji dysków. Podstawowa różnica polega na tym, że w pamięci komputera jest przechowywane jednocześnie 14 ekranów tworzących jeden blok. Pisany program może składać się z dowolnej ilości takich bloków, jednak podczas kompilacji muszą one być oddzielnie doczytywane. Praca na jednym bloku jest bardzo wygodna, gdyż umożliwia szybki dostęp do każdego ekranu zawartego w danym bloku. Cały blok ekranów jest umieszczany w pamięci, nad którą znajduje się ROM, nie zabiera więc pamięci dostępnej dla pisanego programu. Dzięki takiemu usytuowaniu bloku, nie znika on z pamięci komputera nawet po wykonaniu zimnego startu.

Wersja kasetowa ma kilka dodatkowych funkcji ułatwiających korzystanie z magnetofonu. Są to następujące słowa wywoływane z FORTH-a:

C:EDIT - odczyt bloków ekranów zapisanych na taśmie do pamięci. Wejście do Edytora następuje po wpisaniu :

 nrek L. RETURN

gdzie nrek to numer wywoływanego ekranu zawierający się w przedziale od 0 do 15.

C:FLUSH - zapis całego bloku ekranów na kasetę.

nrek LOAD - podobnie, jak w wersji dyskowej, jest to kompilacja ekranu o numerze nrek. Podany ekran musi znajdować się w bloku wprowadzonym wcześniej za pomocą C:EDIT. Aby kompilacja nie została zakończona na wywołanym ekranie, należy umieścić w końcowych liniach ekranu znak: -->

Wprowadziłem także słowo umożliwiające przenoszenie ekranów do Edytora FORTH-a z Edytora Wprowadzania. Uzyskujemy w ten sposób możliwość zapisu na taśmę wersji źródłowej wprowadzanego programu. Dzięki temu każdy z czytelników będzie mógł dowolnie modyfikować programy wklepane z Tajemnic Atari. Aby dokonać wyżej opisanych czynności należy, po zakończeniu wprowadzania programu przy pomocy EDW, napisać :

EDW-EDIT

a następnie wywołać Edytor FORTH-a, np 1 L. aby zobaczyć wprowadzony tekst. Po wyjściu z edytora (przy pomocy klawiszy ECS i SPACJA) możemy zapisać całość na kasecie słowem : C:FLUSH

Właściciele magnetofonów zainteresowani językiem FORTH nie mieli niestety możliwości poznania ciekawych słów znajdujących się na dyskietce zawierającej implementację Extended fig-FORTH. Aby im to umożliwić wprowadziłem do Edytora FORTH-a słowo :

D:EDIT

Umożliwia ono przeniesienie do Edytora FORTH-a w wersji kasetowej dowolnych ekranów z dysku. wywołując powyższe słowo, należy podać przed nim dwie liczby określające numer pierwszego i ostatniego ekranu, które chcemy przenieść, np. 10 21 D:EDIT. Warunkiem koniecznym do przeprowadzenia takiej operacji jest oczywiście dobra znajomość z właścicielem stacji dysków.

Udało mi się przedstawić Czytelnikom najważniejsze słowa języka FORTH, oraz podstawowe narzędzia (ASSEMBLER i EDYTOR), niezbędne do pisania własnych programów. Myslę więc, że zaczną powstawać ciekawe programy w tym języku tworzone przez Czytelników. Ja chciałbym na razie zakończyć ten cykl poświęcony językowi FORTH. Czekam jednak na propozycje Czytelników i jeśli się takie pojawią - zostaną zamieszczone w Tajemnicach Atari. Wszystkim czytelnikom, pragnącym pogłębić swoją znajomość z językiem, polecałbym książkę Jana Ruszyca pt. "Poznajemy FORTH". Została ona wydana przez wydawnictwo SOETO, mieszczące się na ulicy Hożej w Warszawie.

Przez wszystkie docinki tego cyklu przedstawiłem mój subiektywny punkt widzenia na temat języka FORTH. Na zakończenie pragnę więc trochę przewrotnie przedstawić opinię poważnych znawców z dziedziny informatyki. Oto ona :

"Język FORTH jest tylko i wyłącznie ciekawostką informatyczną, która nie ma i nie znajdzie żadnego praktycznego (poważnego ) zastosowania."

Na koniec - część edytora przeznaczona dla posiadaczy magnetofonów, która nie zmieściła się w poprzednim odcinku cyklu :

 Listing 1.

 01AU ( ED-KASETA )
 0200 
 03TN 0 VARIABLE PDL
 04N8 XSAVE 12 + CONSTANT Z%
 05JN XSAVE 14 + CONSTANT D% HEX
 06PU CODE PST BEGIN, D40B LDA, 
 074G 0< NOT UNTIL, BEGIN, D40B LDA,
 08A9 0< UNTIL, FF # LDA, D40A STA, 
 099K SEI, D301 DEC, RTS, C;
 0APH CODE >BL MAC PST
 0B70 BEGIN, DEY, Z% )Y LDA, 
 0C5J D% )Y STA, 0 # CPY, 0=
 0D1V UNTIL, D301 INC, CLI, RTS, C; 
 0ES7 CODE PMV  XSAVE STX, 
 0F67 PDL 1+ LDX, 0 # LDY, 
 0GTC 0 # CPX, 0= NOT IF, 
 0HBK BEGIN, MAC >BL Z% 1+ INC, D% 
 0I01 1+ INC, DEX, 0= UNTIL, THEN, 
 0J6A PDL LDA, 0= NOT 
 0KAH IF, PDL LDY, MAC >BL THEN, 
 0L8S XSAVE LDX, NEXT JMP, C; DECIMAL 
 0MMR : PMOVE PDL ! D% ! Z% ! PMV ; 
 0NAM HEX 2800 CONSTANT G28 
 0OSU : 2DL OVER + DUP >R G28 < 0= 
 0P6R IF DUP G28 < 0= 
 0QSI IF >R 0 0 C000 R G28 - + 
 0RRG R> R SWAP - 
 0SD3 ELSE >R D800 R + G28 R> - 
 0TIN C000 R G28 - ENDIF ELSE 
 0UDT >R D800 R + R> R SWAP - 0 0 
 0V4F ENDIF R> DROP >R OVER R> SWAP ; 
 10MH   -->
 1100 
 1200 
 13V5 : >ROM ROT >R 2DL R + ROT ROT 
 14H3 PMOVE R> ROT ROT PMOVE ; 
 157D : <ROM ROT >R 2Dl R + SWAP 
 166E PMOVE R> SWAP PMOVE ; DECIMAL 
 1700 
 18ML HEX 340 VARIABLE IOCB 
 19RM 0 VARIABLE IO.X 
 1ALR 0 VARIABLE IO.CH 
 1B39 : IOCC 10 * 70 MIN DUP IO.X C! 
 1C3E 340 + IOCB ! ; 
 1D2G : <IO> <BUILDS , DOES> @ IOCB 
 1EU4 @ + ; 2 <IO> COM 
 1FOB 4 <IO> BAL 8 <IO> BLL 
 1GG4 A <IO> AX1 B <IO> AX2 
 1HRB CODE XCIO XSAVE STX, IO.X LDX, 
 1I3G IO.CH LDA, E456 JSR, 
 1JID XSAVE LDX, IO.CH STA, TYA, 
 1K4J PUSH0A JMP, C;
 1LEL : OPEN IOCC AX2 C! AX1 C! 
 1M24 BAL ! 03 COM C! XCIO ; 
 1NJB : <C> IOCC COM C! XCIO ; 
 1OTB : GB IOCC 7 COM C! BLL ! 
 1PEO BAL ! XCIO ; 
 1Q1V : PB IOCC B COM C! BLL ! 
 1R3H BAL ! XCIO ; DECIMAL 
 1SF8 67 VARIABLE C: 
 1T5S : <O> C: SWAP 128 3 
 1U3T OPEN DROP ; 
 1VR3 : OPL 4 <O> ; : OPS 8 <O> ; 
 20M7 : CLO 3 <C> DROP ; --> 
 2100 
 2200 
 23EA : GETR B/BUF 3 GB ; 
 24LL : PUTR B/BUF 3 PB ; 
 2536 0 VARIABLE AROM 
 263C 0 VARIABLE ROM 
 27LG 0 VARIABLE S-L 
 283J : NARC <R AROM ! PAD R> 
 299N PAD AROM @ B/BUF ROM @ 
 2ALA IF <ROM ELSE >R SWAP R> 
 2BID CMOVE ENDIF ; 
 2CKR : +NC S-L @ 
 2DIT IF PAD AROM @ B/BUF 
 2EAB ROM @ IF <ROM ELSE CMOVE ENDIF 
 2F1J B/BUF AROM +! ELSE B/BUF 
 2GRH AROM +! PAD AROM @ B/BUF 
 2H09 ROM @ IF <ROM ELSE 
 2I1M >R SWAP R> CMOVE ENDIF ENDIF ; 
 2JFS 0 VARIABLE #ER 
 2K91 : BCAS NARC 0 
 2LGK DO DUP S-L @ IF GETR ELSE 
 2MFS PUTR ENDIF #ER !
 2N6E #ER C@ 1 = IF +NC 
 2OE5 ELSE #ER @ % 136 = #ER @ 4 = 
 2PVC + 0= IF I 0= 
 2QV3 IF 3 ELSE 2 ENDIF #ER ! 
 2R50 ELSE #ER @ % 136 = 
 2SA3 IF 1 #ER ! ENDIF ENDIF LEAVE 
 2TNO ENDIF LOOP DROP -1 #ER +! ; 
 2U55 : LCAS 1 S-L ! OPL BCAS CLO ; 
 2V9G : SCAS 0 S-L ! OPS BCAS CLO ; 
 30A1 -->
 Listing cd.

 34MQ INDEX ; 
 351Q 1024 CONSTANT &24 
 36DD : B>R DUP >R BLOCK R> B/BUF * 
 370C &24 - B/BUF >ROM 
 38L4 : BR DUP >R BUFFER R> B/BUF * 
 39QK &24 - B/BUF ; : B<R BR <ROM ; 
 3A60 : ER B/SCR * DUP 
 3B72 B/SCR + SWAP ;
 3C1J : E>R ER DO I B>R LOOP ; 
 3D0B : E<R ER DO I B<R LOOP ; 
 3EEE ( NREKR --- ) 
 3FUD 0 VARIABLE FR 
 3G9B : FROM % 14 0 
 3HCO DO FR &24 I * 2 >ROM 
 3I8P LOOP ; 
 3J33 ( --- ) 
 3K00 
 3L39 0 VARIABLE SR 
 3MU5 : ILR SR SWAP 1 - &24 
 3NO2 * 2 <ROM SR @ ; 
 3OH5 ( NREK --- F=0 ) 
 3P00 
 3Q79 : ILROM 0 0 14 
 3RB0 DO I ILR 
 3SD5 IF LEAVE ELSE 1+ ENDIF 
 3TGG -1 +LOOP % 14 SWAP - ; 
 3U0P ( --- ILEKR ) 
 3V00 
 40A1 --> 
 4100 
 4200 
 4305 : YF % 252 1 ILR 256 
 44JA <=< IF FROM ENDIF ; 
 45JM : 0WA 0 WARNING ! ; 
 4600 
 478D : E. EMPTY-BUFFERS 0WA YF 
 485A SCR @ 1 MAX % 14 MIN DUP SCR ! 
 4944 >R R E<r R ILR 0= IF 
 4AQG CLEAR ENDIF (E) 
 4B8V EXF0 R> E>R ;
 4C33 ( --- ) 
 4D00 
 4EGK : ?DNR 0 OVER % 15 <=< IF 
 4FGL 1 ELSE DROP 
 4G6J CR ."Zly numer" 
 4HRS CR BEEP 0 ENDIF ; 
 4IGU : L. ?DNR IF SCR ! E. ENDIF ; 
 4JEE ( NREKR --- ) 
 4K52 : CSOU 8 0 DO 0 53760 I + C! 
 4LMB 2 +LOOP ; 
 4M33 ( --- ) 
 4NMF : C:FLUSH 1 ROM ! 
 4O6K 0 ILROM B/SCR * SCAS CSOU ; 
 4P33 ( --- ) 
 4QMU : C:EDIT 0WA FROM 1 ROM ! 
 4R8P 0 [ 14 8 * ] LITERAL LCAS 
 4S72 #ER @ IF CR ."Blad odczytu" 
 4T6V BEEP CR ENDIF ; 
 4U33 ( --- ) 
 4V00 
 50A1 --> 
 5133 ( --- ) 
 5200 
 53E0 : IND EMPTY-BUFFERS YF 
 54SN % 15 1 DO I B/SCR * DUP 
 55GB B<R BLOCK DUP C@ 
 566Q IF % 32 -TRAILING CR I . 
 57UH TYPE ELSE DROP ENDIF 
 588P LOOP ; 
 5933 ( --- ) 
 5ACA : LOAD ?DNR IF 0WA BEGIN 1 CG 
 5BJA ! EMPTY-BUFFERS DUP ILR IF DUP 
 5CEG E<R DUP >R LOAD R> 1+ ENDIF 
 5DBI CG @ UNTIL DROP ENDIF ; 
 5EL0 ( NREK --- ) 
 5FDO : E<EW ER DO I BR >R 
 5G9A 37000 + SWAP R> CMOVE LOOP ; 
 5HL0 ( NREK --- ) 
 5ILE : EDW-EDIT FROM EW AB @ 
 5JNJ &24 / 1+ 1 DO EMPTY-BUFFERS 
 5KJH I E<EW I E>R LOOP ; 
 5LBO ( --- z EDW do EDYTORA ) 
 5MOR : D:EDIT 0WA FROM OVER - 1+ 
 5NB0 % 14 MIN OVER + EMPTY-BUFFERS 
 5O8D B/SCR 8 SWAP B/SCR * 
 5P9R 0 ROT ROT DO I BLOCK OVER 
 5QHN B/BUF >ROM B/BUF + LOOP DROP ; 
 5RBD ( EKR1 EK2 --- ) 
 5SQJ : CLEAR SCR @ ?DNR IF SCR @ 
 5TKO EMPTY-BUFFERS 
 5UMT E<R CLEAR SCR @ E>R ENDIF ; 
 5VD2 ( END ) 
 3100 
 3200 
 33E7 : INDEX EMPTY-BUFFERS 
 

Roland Pantoła
Tajemnice Atari Nr.11/1993r.