Serwis Edukacyjny w I-LO w Tarnowie Materiały dla uczniów liceum |
Wyjście Spis treści Wstecz Dalej Autorzy: dr Ian Logan i dr Frank O'Hara |
©2024 mgr Jerzy Wałaszek |
i. Tablica offsetów
Dla każdego z pięćdziesięciu rozkazów języka BASIC istnieje określona wartość offsetu
Rozkaz Adres Rozkaz Adres 1A48 DEFB +B1 DEF FN 1AF9 1A61 DEFB +94 BORDER 1AF5 1A49 DEFB +CB CAT 1B14 1A62 DEFB +56 CONTINUE 1AB8 1A4A DEFB +BC FORMAT 1B06 1A63 DEFB +3F DIM 1AA2 1A4B DEFB +BF MOVE 1B0A 1A64 DEFB +41 REM 1AA5 1A4C DEFB +C4 ERASE 1B10 1A65 DEFB +2B FOR 1A90 1A4D DEFB +AF OPEN # 1AFC 1A66 DEFB +17 GO TO 1A7D 1A4E DEFB +B4 CLOSE # 1B02 1A67 DEFB +1F GO SUB 1A86 1A4F DEFB +93 MERGE 1AE2 1A68 DEFB +37 INPUT 1A9F 1A50 DEFB +91 VERIFY 1AE1 1A69 DEFB +77 LOAD 1AE0 1A51 DEFB +92 BEEP 1AE3 1A6A DEFB +44 LIST 1AAE 1A52 DEFB +95 CIRCLE 1AE7 1A6B DEFB +0F LET 1A7A 1A53 DEFB +98 INK 1AEB 1A6C DEFB +59 PAUSE 1AC5 1A54 DEFB +98 PAPER 1AEC 1A6D DEFB +2B NEXT 1A98 1A55 DEFB +98 FLASH 1AED 1A6E DEFB +43 POKE 1AB1 1A56 DEFB +98 BRIGHT 1AEE 1A6F DEFB +2D PRINT 1A9C 1A57 DEFB +98 INVERSE 1AEF 1A70 DEFB +51 PLOT 1AC1 1A58 DEFB +98 OVER 1AF0 1A71 DEFB +3A RUN 1AAB 1A59 DEFB +98 OUT 1AF1 1A72 DEFB +6D SAVE 1ADF 1A5A DEFB +7F LPRINT 1AD9 1A73 DEFB +42 RANDOMIZE 1AB5 1A5B DEFB +81 LLIST 1ADC 1A74 DEFB +0D IF 1A81 1A5C DEFB +2E STOP 1A8A 1A75 DEFB +49 CLS 1ABE 1A5D DEFB +6C READ 1AC9 1A76 DEFB +5C DRAW 1AD2 1A5E DEFB +6E DATA 1ACC 1A77 DEFB +44 CLEAR 1ABB 1A5F DEFB +70 RESTORE 1ACF 1A78 DEFB +15 RETURN 1A8D 1A60 DEFB +48 NEW 1AA8 1A79 DEFB +5D COPY 1AD6 |
ii. Tablica parametrów
Dla każdego z pięćdziesięciu rozkazów języka BASIC istnieje do ośmiu elementów w tablicy parametrów. Elementy te określają szczegóły klasy rozkazu, wymagane separatory oraz w odpowiednich miejscach adresy procedur.
1A7A P-LET DEFB +01 CLASS-01 DEFB +3D '=' DEFB +02 CLASS-02 1A7D P-GO-TO DEFB +06 CLASS-06 DEFB +00 CLASS-00 DEFB +67,+1E GO-TO,1E67 1A81 P-IF DEFB +06 CLASS-06 DEFB +CB 'THEN' DEFB +05 CLASS-05 DEFB +F0,+1C IF,1CF0 1A86 P-GO-SUB DEFB +06 CLASS-06 DEFB +00 CLASS-00 DEFB +ED,+1E GO-SUB,1EED 1A8A P-STOP DEFB +00 CLASS-00 DEFB +EE,+1C STOP,1CEE 1A8D P-RETURN DEFB +00 CLASS-00 DEFB +23,+1F RETURN,1F23 1A90 P-FOR DEFB +04 CLASS-04 DEFB +3D '=' DEFB +06 CLASS-06 DEFB +CC 'TO' DEFB +06 CLASS-06 DEFB +05 CLASS-05 DEFB +03,+1D FOR,1D03 1A98 P-NEXT DEFB +04 CLASS-04 DEFB +00 CLASS-00 DEFB +AB,+1D NEXT,1DAB 1A9C P-PRINT DEFB +05 CLASS-05 DEFB +CD,+1F PRINT,1FCD 1A9F P-INPUT DEFB +05 CLASS-05 DEFB +89,+20 INPUT,2089 1AA2 P-DIM DEFB +05 CLASS-05 DEFB +02,+2C DIM,2C02 1AA5 P-REM DEFB +05 CLASS-05 DEFB +B2,+1B REM,1BB2 1AA8 P-NEW DEFB +00 CLASS-00 DEFB +B7,+11 NEW,11B7 1AAB P-RUN DEFB +03 CLASS-03 DEFB +A1,+1E RUN,1EA1 1AAE P-LIST DEFB +05 CLASS-05 DEFB +F9,+17 LIST,17F9 1AB1 P-POKE DEFB +08 CLASS-08 DEFB +00 CLASS-00 DEFB +80,+1E POKE,1E80 1AB5 P-RANDOM DEFB +03 CLASS-03 DEFB +4F,+1E RANDOMIZE,1E4F 1AB8 P-CONT DEFB +00 CLASS-00 DEFB +5F,+1E CONTINUE,1E5F 1ABB P-CLEAR DEFB +03 CLASS-03 DEFB +AC,+1E CLEAR,1EAC 1ABE P-CLS DEFB +00 CLASS-00 DEFB +6B,+0D CLS,0D6B 1AC1 P-PLOT DEFB +09 CLASS-09 DEFB +00 CLASS-00 DEFB +DC,+22 PLOT,22DC 1AC5 P-PAUSE DEFB +06 CLASS-06 DEFB +00 CLASS-00 DEFB +3A,+1F PAUSE,1F3A 1AC9 P-READ DEFB +05 CLASS-05 DEFB +ED,+1D READ,1DED 1ACC P-DATA DEFB +05 CLASS-05 DEFB +27,+1E DATA,1E27 1ACF P-RESTORE DEFB +03 CLASS-03 DEFB +42,+1E RESTORE,1E42 1AD2 P-DRAW DEFB +09 CLASS-09 DEFB +05 CLASS-05 DEFB +82,+23 DRAW,2382 1AD6 P-COPY DEFB +00 CLASS-00 DEFB +AC+0E COPY,0EAC 1AD9 P-LPRINT DEFB +05 CLASS-05 DEFB +C9,+1F LPRINT,1FC9 1ADC P-LLIST DEFB +05 CLASS-05 DEFB +F5,+17 LLIST,17F5 1ADF P-SAVE DEFB +0B CLASS-0B 1AE0 P-LOAD DEFB +0B CLASS-0B 1AE1 P-VERIFY DEFB +0B CLASS-0B 1AE2 P-MERGE DEFB +0B CLASS-0B 1AE3 P-BEEP DEFB +08 CLASS-08 DEFB +00 CLASS-00 DEFB +F8,+03 BEEP,03F8 1AE7 P-CIRCLE DEFB +09 CLASS-09 DEFB +05 CLASS-05 DEFB +20,+23 CIRCLE,2320 1AEB P-INK DEFB +07 CLASS-07 1AEC P-PAPER DEFB +07 CLASS-07 1AED P-FLASH DEFB +07 CLASS-07 1AEE P-BRIGHT DEFB +07 CLASS-07 1AEF P-INVERSE DEFB +07 CLASS-07 1AF0 P-OVER DEFB +07 CLASS-07 1AF1 P-OUT DEFB +08 CLASS-08 DEFB +00 CLASS-00 DEFB +7A,+1E OUT,1E7A 1AF5 P-BORDER DEFB +06 CLASS-06 DEFB +00 CLASS-00 DEFB +94,+22 BORDER,2294 1AF9 P-DEF-FN DEFB +05 CLASS-05 DEFB +60,+1F DEF-FN,1F60 1AFC P-OPEN DEFB +06 CLASS-06 DEFB +2C ',' DEFB +0A CLASS-0A DEFB +00 CLASS-00 DEFB +36,+17 OPEN,1736 1B02 P-CLOSE DEFB +06 CLASS-06 DEFB +00 CLASS-00 DEFB +E5,+16 CLOSE,16E5 1B06 P-FORMAT DEFB +0A CLASS-0A DEFB +00 CLASS-00 DEFB +93,+17 CAT-ETC,1793 1B0A P-MOVE DEFB +0A CLASS-0A DEFB +2C ',' DEFB +0A CLASS-0A DEFB +00 CLASS-00 DEFB +93,+17 CAT-ETC,1793 1B10 P-ERASE DEFB +0A CLASS-0A DEFB +00 CLASS-00 DEFB +93,+17 CAT-ETC,1793 1B14 P-CAT DEFB +00 CLASS-00 DEFB +93,+17 CAT-ETC,1793 |
Uwaga: wymagania dla każdej z różnych klas rozkazów są następujące:
CLASS-00 – Brak dalszych parametrów.
CLASS-01 – Używana w LET. Wymagana jest zmienna.
CLASS-02 – Używana w LET. Musi wystąpić wyrażenie liczbowe lub znakowe.
CLASS-03 – Może wystąpić wyrażenie liczbowe. Jeśli go nie ma, przyjmuje się
standardowo zero.
CLASS-04 – Musi wystąpić zmienna o jednoliterowej nazwie.
CLASS-05 – Może być podany zbiór elementów.
CLASS-06 – Musi wystąpić wyrażenie liczbowe.
CLASS-07 – Obsługuje elementy kolorów.
CLASS-08 – Muszą wystąpić dwa wyrażenia liczbowe rozdzielone przecinkiem.
CLASS-09 – Jak dla CLASS-08, lecz elementy kolorów mogą poprzedzać
wyrażenia.
CLASS-0A – Musi wystąpić wyrażenie łańcuchowe.
CLASS-0B – Obsługuje procedury magnetofonu.
Gdy sprawdzana jest składnia, to wejście do procedury interpretacji poleceń języka BASIC następuje w punkcie LINE-SCAN, natomiast przy wykonywaniu rozkazów punktem wejścia jest LINE-RUN.
Każde polecenie zostaje po kolei przetworzone, a zmienna systemowa CH-ADD jest wykorzystywana do wskazywania każdego kodu lub rozkazu pojawiającego się w obszarze programu lub w obszarze edycyjnym.
1B17 LINE-SCAN RES 7,(FLAGS) Sygnalizuj 'sprawdzanie składni'. CALL 19FB,E-LINE-NO CH-ADD zostaje ustawione na pierwszy kod za każdym numerem wiersza. XOR A Zmienna systemowa SUBPPC LD (SUBPPC),A jest inicjowana na +00 DEC A a ERR-NR na +FF. LD (ERR-NR),A JR 1B29,STMT-L-1 Skocz naprzód, aby przetworzyć pierwszy rozkaz wiersza. |
Każdy rozkaz jest kolejno przetwarzany aż do osiągnięcia końca wiersza.
1B28 STMT-LOOP RST 0020,NEXT-CHAR Zwiększaj CH-ADD wzdłuż wiersza. 1B29 STMT-L-1 CALL 16BF,SET-WORK Przestrzeń robocza jest czyszczona. INC (SUBPPC) Zwiększaj SUBPPC przy każdym obiegu pętli. JP M,1C8A,REPORT-C Lecz dozwolone jest tylko '127' rozkazów w pojedynczym wierszu. RST 0018,GET-CHAR Pobierz znak. LD B,+00 Wyzeruj ten rejestr na później. CP +0D Jeśli znakiem jest 'powrót karetki', JR Z,1BB3,LINE-END to wykonaj skok. CP +3A Jeśli jest to ':', JR Z,1B28,STMT-LOOP to wróć na początek pętli. |
Zidentyfikowano polecenie, zatem rozpatrzony zostanie pierwszy rozkaz.
LD HL,+1B76 Załaduj na stos maszynowy PUSH HL adres powrotny STMT-RET. LD C,A Chwilowo zapamiętaj rozkaz RST 0020,NEXT-CHAR w rejestrze C, gdy CH-ADD LD A,C jest ponownie przesuwane. SUB +CE Zmniejsz kod rozkazu o +CE; da to zakres od +00 do +31 dla pięćdziesięciu rozkazów. JP C,1C8A,REPORT-C Twórz odpowiedni raport błędu, jeśli kod nie oznacza rozkazu. LD C,A Przenieś kod rozkazu do pary rejestrów BC (B zawiera +00). LD HL,+1A48 Adres bazowy tablicy składniowej offsetów. ADD HL,BC Pożądany offset jest przekazywany do LD C,(HL) rejestru C i używany do wyliczenia ADD HL,BC adresu bazowego dla pozycji rozkazu w tablicy parametrów. JR 1B55,GET-PARAM Skocz naprzód do pętli skanującej z tym adresem. |
Wykonywane są po kolei procedury klas rozkazów, które odnoszą się do bieżącego polecenia. Przetwarza się również wszystkie niezbędne separatory.
1B52 SCAN-LOOP LD HL,(T-ADDR) Tymczasowy wskaźnik do elementów w tablicy parametrów. 1B55 GET-PARAM LD A,(HL) Pobierz kolejno każdy element. INC HL Uaktualnij wskaźnik elementów dla LD (T-ADDR),HL następnego obiegu. LD BC,+1B52 Załaduj na stos maszynowy PUSH BC adres powrotny - SCAN-LOOP. LD C,A Przepisz element do rejestru C na później. CP +20 Skocz naprzód, jeśli element jest JR NC,1B6F,SEPARATOR 'separatorem'. LD HL,+1C01 Adres bazowy tablicy 'klas rozkazów'. LD B,+00 Wyczyść rejestr B i ADD HL,BC zaindeksuj tę tablicę. LD C,(HL) Pobierz przesunięcie i oblicz ADD HL,BC adres startowy procedury pożądanej klasy rozkazów. PUSH HL Umieść ten adres na stosie maszynowym. RST 0018,GET-CHAR Przed wykonaniem skoku pośredniego DEC B do procedury klasy rozkazu przenieś RET kod rozkazu do rejestru A i ustaw rejestr B na +FF. |
Zostaje utworzony raport błędu – 'Nonsense in BASIC', jeśli brak wymaganego separatora. Jednakże zwróć uwagę, iż w czasie sprawdzania składni raport ten nie pojawia się na ekranie – jedynie 'znacznik błędu'.
1B6F SEPARATOR RST 0018,GET-CHAR Bieżący znak zostaje pobrany CP C i porównany z elementem tablicy parametrów. JP NZ,1C8A,REPORT-C Jeśli nie ma zgodności, utwórz raport błędu. RST 0020,NEXT-CHAR Przejdź za poprawny znak RET i powróć. |
Po poprawnej interpretacji polecenia wykonywany jest powrót do punktu wejścia.
1B76 STMT-RET CALL 1F54,BREAK-KEY Klawisz BREAK jest sprawdzany po każdym poleceniu. JR C,1B7D,STMT-R-1 Skocz naprzód, chyba że jest naciśnięty. |
Raport L - 'PRZERWA w programie'
1B7B REPORT-L RST 0008,ERROR-1 Wywołaj procedurę obsługi błędów. DEFB +14 |
Kontynuuj w tym miejscu, jeśli klawisza BREAK nie naciśnięto.
1B7D STMT-R-1 BIT 7,(NSPPC) Skocz naprzód, jeśli nie należy wykonać JR NZ,1BF4,STMT-NEXT 'przeskoku' w programie. LD HL,(NEWPPC) Pobierz numer 'nowego wiersza' BIT 7,H i skocz naprzód, chyba że jest przetwarzane JR Z,1B9E,LINE-NEW kolejne polecenie w obszarze edycyjnym. |
Ten punkt wejścia jest używany zawsze, gdy ma zostać uruchomiony wiersz programu w obszarze edycyjnym. W takim przypadku znacznik składni/uruchomienia (bit nr 7 zmiennej FLAGS) będzie ustawiony na 1.
Wejście to jest również używane przy sprawdzaniu składni wiersza w obszarze edycyjnym, który zawiera więcej niż jedno polecenie (bit 7 FLAGS będzie wyzerowany).
1B8A LINE-RUN LD HL,+FFFE Wiersz w obszarze edycyjnym LD (PPC),HL jest uważany za wiersz '-2'. LD HL,(WORKSP) Ustaw HL na znacznik końca DEC HL obszaru edycyjnego, LD DE,(E-LINE) a DE na komórkę tuż przed DEC DE początkiem tego obszaru. LD A,(NSPPC) Pobierz numer następnego polecenia do obsłużenia JR 1BD1,NEXT-LINE przed skokiem naprzód. |
W programie nastąpił skok i należy znaleźć adres początku nowego wiersza.
1B9E LINE-NEW CALL 196E,LINE-ADDR Znajdowany jest adres startowy wiersza lub adres pierwszego następnego wiersza. LD A,(NSPPC) Pobierz numer polecenia. JR Z,1BBF,LINE-USE Skocz naprzód, jeśli pożądany AND A wiersz został znaleziony; inaczej JR NZ,1BEC,REPORT-N sprawdź poprawność numeru polecenia - musi być zero. LD B,A Również sprawdź, czy 'pierwszy wiersz za nim' LD A,(HL) nie jest faktycznie poza 'końcem programu'. AND +C0 LD A,B JR Z,1BBF,LINE-USE Skocz naprzód przy poprawnym adresie; inaczej sygnalizuj błąd 'OK'. |
Raport 0 - 'OK'
1BB0 REPORT-0 RST 0008,ERROR-1 Wywołaj procedurę obsługi błędów. DEFB +FF |
Uwaga: Oczywiście nie jest to błąd w normalnym sensie – raczej skok poza program.
Adres powrotny do STMT-RET jest usuwany ze stosu, co w rezultacie powoduje zignorowanie reszty wiersza.
1BB2 REM POP BC Usuń adres - STMT-RET. |
Przy sprawdzaniu składni wykonywany jest prosty powrót, jednakże w czasie 'uruchomienia' adres przechowywany przez NXTLIN musi zostać sprawdzony przed użyciem.
1BB3 LINE-END CALL 2530,SYNTAX-Z Wróć, jeśli sprawdzana jest składnia; RET Z inaczej pobierz adres LD HL,(NXTLIN) przechowywany w NXTLIN. LD A,+C0 Również wróć, jeśli ten adres AND (HL) wskazuje poza program RET NZ - 'uruchomienie' dobiegło końca. XOR A Sygnalizuj 'polecenie zero' przed kontynuowaniem. |
Ta krótka procedura posiada trzy funkcje:
i. Zmienia polecenie zera na polecenie '1'.
ii. Znalezienie numeru nowego wiersza i wprowadzenie go do PPC.
iii. Utworzenie adresu początku kolejnego wiersza.
1BBF LINE-USE CP +01 Rozkaz zero staje się ADC A,+00 rozkazem '1' LD D,(HL) Numer wiersza, który ma zostać INC HL użyty, jest pobierany LD E,(HL) i przekazywany do PPC. LD (PPC),DE INC HL Teraz znajdź 'długość' LD E,(HL) tego wiersza. INC HL LD D,(HL) EX DE,HL Wymień ze sobą te wartości. ADD HL,DE Utwórz adres początku INC HL kolejnego wiersza w HL, a adres pierwszej komórki przed pierwszym znakiem 'następnego' wiersza w DE. |
Na wejściu para rejestrów HL wskazuje na pierwszą komórkę za końcem 'następnego' wiersza do obsługi, a para rejestrów DE wskazuje na komórkę przed pierwszym znakiem tego wiersza. Stosuje się to zarówno do wierszy w obszarze programu jak i do wiersza w obszarze edycyjnym, gdzie następnym wierszem będzie znów ten sam wiersz, gdy zawiera on polecenia wciąż do interpretacji.
1BD1 NEXT-LINE LD (NXTLIN),HL Ustaw NXTLIN do użytku, gdy bieżący wiersz został skompletowany. EX DE,HL Jak zwykle, CH-ADD wskazuje na komórkę LD (CH-ADD),HL przed pierwszym znakiem do interpretacji. LD D,A Zostaje pobrany numer polecenia. LD E,+00 Rejestr E jest zerowany w przypadku korzystania z EACH-STMT. LD (NSPPC),+FF Sygnalizuj 'bez skoku'. DEC D Numer polecenia minus jeden LD (SUBPPC),D idzie do SUBPPC. JP Z,1B28,STMT-LOOP Teraz można przetworzyć pierwsze polecenie. INC D Jednakże dla dalszych poleceń CALL 198B,EACH-STMT należy znaleźć 'adres początkowy'. JR Z,1BF4,STMT-NEXT Skocz naprzód, chyba że polecenie nie istnieje. |
Raport N - 'Rozkaz utracony'
1BEC REPORT-N RST 0008,ERROR-1 Wywołaj procedurę obsługi błędów DEFB +16 |
Jest to ważna procedura i wywołuje się ją z wielu miejsc w programie monitora w trakcie sprawdzania składni edytowanego wiersza. Celem procedury jest utworzenie raportu błędu, jeśli koniec polecenia nie został osiągnięty, oraz przejście do następnego polecenia w przypadku prawidłowej składni.
1BEE CHECK-END CALL 2530,SYNTAX-Z Nie kontynuuj, jeśli nie jest RET NZ sprawdzana składnia. POP BC Usuń adresy POP BC SCAN-LOOP i STMT-RET przed przejściem do STMT-NEXT. |
Jeśli bieżącym znakiem jest 'powrót karetki', to następne polecenie znajduje się w 'następnym wierszu'; jeśli jest nim ':', to jest ono w tym samym wierszu; lecz jeśli występuje dowolny inny znak, to mamy błąd składni.
1BF4 STMT-NEXT RST 0018,GET-CHAR Pobierz bieżący znak. CP +0D Wybierz 'następny wiersz', jeśli JR Z,1BB3,LINE-END jest nim 'powrót karetki'. CP +3A Wybierz 'następne polecenie', JP Z,1B28,STMT-LOOP jeśli jest to ' : '. JP 1C8A,REPORT-C W przeciwnym razie występuje błąd składniowy. |
adres przesunięcie klasa adres klasy 1C01 0F CLASS-00 1C10 1C02 1D CLASS-01 1C1F 1C03 4B CLASS-02 1C4E 1C04 09 CLASS-03 1C0D 1C05 67 CLASS-04 1C6C 1C06 0B CLASS-05 1C11 1C07 7B CLASS-06 1C82 1C08 8E CLASS-07 1C96 1C09 71 CLASS-08 1C7A 1C0A B4 CLASS-09 1CBE 1C0B 81 CLASS-0A 1C8C 1C0C CF CLASS-0B 1CDB |
Za rozkazami klasy-03 może wystąpić liczba, lecz może jej również nie być, np. RUN lub RUN 200.
1C0D CLASS-03 CALL 1CDE,FETCH-NUM Pobierana jest liczba, lecz zostanie użyte zero, jeśli jej nie będzie. |
Rozkazy klasy-00 nie powinny mieć jakichkolwiek parametrów, np. COPY lub CONTINUE.
1C10 CLASS-00 CP A Ustaw znacznik zera na później. |
Rozkazy klasy-05 mogą posiadać ciąg parametrów, np. PRINT lub PRINT "222".
1C11 CLASS-05 POP BC We wszystkich przypadkach usuń adres SCAN-LOOP. CALL Z,1BEE,CHECK-END Jeśli są przetwarzane rozkazy klas 00 i 03 oraz jest sprawdzana składnia, to przejdź dalej do przetwarzania następnego polecenia. EX DE,HL Zapamiętaj wskaźnik wiersza w parze rejestrów DE. |
Po przetworzeniu elementów klas rozkazów i separatorów w tablicy parametrów skocz do odpowiedniej procedury obsługującej właściwy rozkaz.
1C16 JUMP-C-R LD HL,(T-ADDR) Pobierz wskaźnik do LD C,(HL) elementów tablicy parametrów INC HL oraz pobierz adres pożądanej LD B,(HL) procedury rozkazu. EX DE,HL Z powrotem wymień wskaźniki PUSH BC i wykonaj pośredni skok RET do procedury rozkazu. |
Te trzy klasy rozkazów są używane przez rozkazy przetwarzające zmienne – LET, FOR i NEXT oraz pośrednio przez READ i INPUT.
Rozkaz klasy 01 dotyczy identyfikacji zmiennej w poleceniu LET, READ lub INPUT.
1C1F CLASS-01 CALL 28B2,LOOK-VARS Sprawdź w obszarze zmiennych, czy dana zmienna była lub nie była jeszcze użyta. |
Ta procedura tworzy odpowiednie wartości dla zmiennych systemowych DEST i STRLEN.
1C22 VAR-A-1 LD (FLAGX),+00 Inicjuj FLAGX na +00. JR NC,1C30,VAR-A-2 Skocz naprzód, jeśli ta zmienna była wcześniej używana. SET 1,(FLAGX) Sygnalizuj 'nowa zmienna'. JR NZ,1C46,VAR-A-3 Utwórz błąd, jeśli jest próba użycia 'niezwymiarowanej tablicy'. |
Raport 2 - Zmienna nieznaleziona
1C2E REPORT-2 RST 0008,ERROR-1 Wywołaj procedurę obsługi błędów. DEFB +01 |
Kontynuuj obsługę istniejących zmiennych.
1C30 VAR-A-2 CALL Z,2996,STK-VARS Parametry prostych zmiennych łańcuchowych
oraz wszystkich zmiennych tablicowych
są przekazywane na stos kalkulatora.
(STK-VARS wykona 'slicing' łańcucha,
jeśli będzie to potrzebne.)
BIT 6,(FLAGS) Skocz naprzód, jeśli jest obsługiwana
JR NZ,1C46,VAR-A-3 zmienna numeryczna.
XOR A Wyczyść rejestr A.
CALL 2530,SYNTAX-Z Parametry łańcucha zmiennej łańcuchowej
CALL NZ,2BF1,STK-FETCH zostają pobrane, chyba że jest sprawdzana składnia.
LD HL,+5C71 To jest FLAGX.
OR (HL) Bit 0 jest ustawiany tylko wtedy, gdy obsługiwane są
LD (HL),A całe 'proste łańcuchy', a stąd sygnalizuje on
potrzebę 'usunięcia starej kopii'.
EX DE,HL HL teraz wskazuje na łańcuch lub na
element tablicy. |
Ścieżki teraz schodzą się ze sobą, aby odpowiednio ustawić STRLEN i DEST. Dla wszystkich zmiennych numerycznych oraz 'nowych' łańcuchów i zmiennych tablic łańcuchów STRLEN zawiera 'literę' nazwy zmiennej. Lecz dla 'starych' łańcuchów i zmiennych tablicowych łańcuchów 'dzielonych' lub pełnych przechowuje ona długość w 'przypisaniu'.
1C46 VAR-A-3 LD (STRLEN),BC Ustaw odpowiednio STRLEN. |
DEST przechowuje adres 'przeznaczenia' 'starej' zmiennej, lecz w rzeczywistości będzie to adres 'źródła' dla 'nowej' zmiennej.
LD (DEST),HL Ustaw odpowiednio DEST RET i powróć. |
Klasa rozkazów 02 zajmuje się faktycznym obliczeniem wartości, która ma zostać przypisana w poleceniu LET.
1C4E CLASS-02 POP BC Adres SCAN-LOOP jest usuwany ze stosu. CALL 1C56,VAL-FET-1 Wykonane zostaje przypisanie. CALL 1BEE,CHECK-END Przesuń się do kolejnego polecenia albo poprzez CHECK-END przy sprawdzaniu RET składni, albo przez STMT-RET w czasie 'wykonywania' programu. |
Ta procedura używana jest przez polecenia LET, READ i INPUT do obliczenia najpierw wartości, a następnie do przypisania jej przydzielonej zmiennej.
Punkt wejścia VAL-FET-1 jest używany przez LET i READ i bierze pod uwagę FLAGS, natomiast punkt wejścia VAL-FET-2 jest używany przez INPUT i bierze pod uwagę FLAGX.
1C56 VAL-FET-1 LD A,(FLAGS) Użyj FLAGS. 1C59 VAL-FET-2 PUSH AF Zapamiętaj na stosie FLAGS lub FLAGX. CALL 24FB,SCANNING Oblicz następne wyrażenie. POP AF Pobierz stare FLAGS lub FLAGX. LD D,(FLAGS) Pobierz nowe FLAGS. XOR D Zmienna i wyrażenie muszą być tej samej natury AND +40 numeryczne lub znakowe. JR NZ,1C8A,REPORT-C Jeśli nie są, utwórz raport C. BIT 7,D Skocz naprzód, aby wykonać JP NZ,2AFF,LET przypisanie, chyba że jest sprawdzana RET składnia, to wtedy po prostu powróć |
Punkt wejścia do klasy rozkazów 0r jest używany przez polecenia FOR i NEXT.
1C6C CLASS-04 CALL 28B2,LOOK-VARS Poszukaj w obszarze zmiennych używanej zmiennej. PUSH AF Zapamiętaj parę rejestrów AF podczas LD A,C testowania bajtu ogranicznika w celu OR +9F upewnienia się, że zmienna ta jest INC A zmienną sterującą pętli FOR-NEXT. JR NZ,1C8A,REPORT-C POP AF Odtwórz rejestr znaczników JR 1C22,VAR-A-1 i skocz wstecz, aby uczynić znalezioną zmienną 'zmienną w przypisaniu'. |
Istnieje ciąg krótkich procedur, które są używane do pobierania wyniku obliczenia następnego wyrażenia. Wynik z pojedynczego wyrażenia jest zwracany jako 'ostatnia wartość' na stosie kalkulatora.
Punkt wejścia NEXT-2NUM jest używany, gdy zmienna systemowa CH-ADD musi być uaktualniona, aby wskazywać początek pierwszego wyrażenia.
1C79 NEXT-2NUM RST 0020,NEXT-CHAR Zwiększ CH-ADD. |
Punkt wejścia EXPT-2NUM (EQU. CLASS-08) zezwala na obliczenie dwóch wyrażeń numerycznych rozdzielonych przecinkiem.
1C7A EXPT-2NUM CALL 1C82,EXPT-1NUM Oblicz kolejno każde z wyrażeń.
(CLASS-08)
CP +2C Twórz raport błędów, jeśli separator
JR NZ,1C8A nie jest przecinkiem.
RST 0020,NEXT-CHAR Zwiększ CH-ADD. |
Punkt wejścia EXPT-1NUM (EQU. CLASS-06) zezwala na obliczenie pojedynczego wyrażenia.
1C82 EXPT-1NUM CALL 24FB,SCANNING Oblicz pierwsze wyrażenie.
(CLASS-06)
BIT 6,(FLAGS) Wróć, gdy wynik był numeryczny;
RET NZ inaczej jest to błąd. |
Raport C - Nonsens w BASIC
1C8A REPORT-C RST 0008,ERROR-1 Wywołaj procedurę obsługi błędów. DEFB +0B |
Punkt wejścia EXPT-EXP (EQU. CLASS-0A) zezwala na obliczenie pojedynczego wyrażenia łańcuchowego.
1C8C EXPT-EXP CALL 24FB,SCANNING Oblicz następne wyrażenie.
(CLASS-0A)
BIT 6,(FLAGS) Tym razem wróć, jeśli wynikiem
RET Z jest łańcuch; inaczej generuj
JR 1C8A,REPORT-C raport błędu. |
Ta procedura umożliwia kolorom tymczasowym przejście w kolory stałe. Jako klasa rozkazów 07 staje się ona procedurą obsługi sześciu rozkazów związanych z elementami koloru.
1C96 PERMS BIT 7,(FLAGS) Odczytany zostaje znacznik składnia/uruchomienie. (CLASS-07) RES 0,(TV-FLAG) Sygnalizuj 'główny ekran'. CALL NZ,0D4D,TEMPS Tylko podczas 'uruchomienia' wywołaj TEMPS, aby upewnić się, że kolory tymczasowe będą głównymi kolorami ekranu. POP AF Usuń adres powrotny do SCAN-LOOP. LD A,(T-ADDR) Pobierz młodszy bajt T-ADDR i odejmij +13, aby otrzymać SUB +13 zakres od +D9 do +DE, co odpowiada kodom symboli od INK do OVER. CALL 21FC,CO-TEMP-4 Skocz naprzód, aby zmienić kolory tymczasowe zgodnie z rozkazem BASIC. CALL 1BEE,CHECK-END Przejdź do następnego polecenia przy sprawdzaniu składni. LD HL,(ATTR-T) Teraz wartości kolorów tymczasowych LD (ATTR-P),HL stają się wartościami kolorów stałych (oba ATTR-P i MASK-P). LD HL,+5C91 To jest P-FLAG; i jego również LD A,(HL) należy wziąć pod uwagę. |
Następne instrukcje sprytnie kopiują parzyste bity dostarczonego bajtu do bitów nieparzystych. W rezultacie bity stałe stają się takie same jak bity tymczasowe.
RLCA Przesuń maskę w lewo. XOR (HL) Ustaw w masce tylko AND +AA parzyste bity pozostałego bajtu. XOR (HL) LD (HL),A Odtwórz wynik. RET |
Procedura ta jest używana przez rozkazy PLOT, DRAW i CIRCLE do określenia standardowych warunków jako 'FLASH 8; BRIGHT 8; PAPER 8;', które są ustawiane przed przetworzeniem jakichkolwiek osadzonych elementów koloru.
1CBE CLASS-09 CALL 2530,SYNTAX-Z Skocz naprzód, jeśli JR Z,1CD6,CL-09-1 jest sprawdzana składnia. RES 0,(TV-FLAG) Sygnalizuj 'główny ekran'. CALL 0D4D,TEMPS Ustaw kolory tymczasowe dla głównego ekranu. LD HL,+5C90 To jest MASK-T. LD A,(HL) Pobierz jej bieżącą wartość, lecz OR +F8 zatrzymaj tylko część INK 'niemaskowaną'. LD (HL),A Odtwórz tę wartość, która teraz oznacza 'FLASH 8; BRIGHT 8; PAPER 8;'. RES 6,(P-FLAG) Również upewnij się, że nie występuje 'PAPER 9'. RST 0018,GET-CHAR Pobierz bieżący znak przed rozpoczęciem przetwarzania osadzonych elementów koloru. 1CD6 CL-09-1 CALL 21E2,CO-TEMP Zajmij się lokalnie dominującymi elementami koloru. JR 1C7A,EXPT-2NUM Teraz pobierz dwa pierwsze parametry dla PLOT, DRAW lub CIRCLE. |
Ta procedura jest używana przez rozkazy SAVE, LOAD, VERIFY i MERGE.
1CDB CLASS-0B JP 0605,SAVE-ETC Skocz do procedury obsługi magnetofonu. |
Procedura ta powoduje obliczenie wartości wyrażenia liczbowego, lecz daje zero w przypadku jego braku.
1CDE FETCH-NUM CP +0D Skocz naprzód, jeśli koniec wiersza. JR Z,1CE6,USE-ZERO CP +3A Lecz skocz do EXPT-1NUM, chyba że JR NZ,1C82,EXPT-1NUM jesteśmy na końcu polecenia. |
Teraz jest używany kalkulator, aby dodać zero do stosu kalkulatora.
1CE6 USE-ZERO CALL 2530,SYNTAX-Z Nie wykonuj tej operacji RET Z przy sprawdzaniu składni. RST 0028,FP-CALC Użyj kalkulatora. DEFB +A0,stk-zero 'Ostatnia wartość' to teraz zero. DEFB +38,end-calc RET Wróć z zerem dodanym do stosu kalkulatora. |
Ta część 16KB programu monitora od adresu 1CEE do 23FA zawiera w większości procedury rozkazów interpretera języka BASIC.
Procedura rozkazu STOP zawiera jedynie wywołanie procedury obsługi błędów.
1CEE STOP RST 0008,ERROR-1 Wywołaj procedurę obsługi błędów.
(RAPORT-9) DEFB +08 |
Na wejściu wyrażenie pomiędzy IF a THEN jest 'ostatnią wartością' na stosie kalkulatora. Jeśli logicznie sprowadza się do prawdy, to zostanie obsłużony następny rozkaz; w przeciwnym razie wiersz zostanie potraktowany jako zakończony.
1CF0 IF POP BC Usuń adres powrotny - STMT-RET. CALL 2530,SYNTAX-Z Skocz naprzód, jeśli sprawdzana JR Z,1D00,IF-1 jest składnia. |
Teraz użyj kalkulatora do usunięcia ostatniej wartości na stosie kalkulatora, lecz pozostaw parę rejestrów DE wskazującą pierwszy bajt tej wartości.
RST 0028,FP-CALC Użyj kalkulatora. DEFB +02,delete Obecna 'ostatnia wartość' jest usuwana. DEFB +38,end-calc EX DE,HL Ustaw HL na wskazywanie pierwszego bajtu CALL 34E9,TEST-ZERO i wywołaj TEST-ZERO. JP C,1BB3,LINE-END Jeśli wartość była 'fałszem', skocz do następnego wiersza. 1D00 IF-1 JP 1B29,STMT-L-1 Przy 'prawdzie' skocz do rozkazu za THEN. |
Wejście do tej procedury rozkazu następuje z WARTOŚCIĄ i GRANICĄ dla polecenia FOR umieszczonymi na szczycie stosu kalkulatora.
1D03 FOR CP +CD Skocz naprzód o ile nie jest obecny parametr 'STEP'. JR NZ,1D10,F-USE-1 RST 0020,NEXT-CHAR Przesuń do przodu CH-ADD i pobierz CALL 1C82,EXPT-1NUM wartość kroku dla STEP. CALL 1BEE,CHECK-END Przejdź dalej do kolejnego rozkazu JR 1D16,F-REORDER jeśli jest sprawdzana składnia; inaczej skocz naprzód. |
Nie występuje parametr STEP, zatem zostanie użyta wartość '1'.
1D10 F-USE-1 CALL 1BEE,CHECK-END Przejdź do następnego rozkazu przy sprawdzaniu składni; inaczej RST 0028,FP-CALC użyj kalkulatora do umieszczenie '1' DEFB +A1,stk-one na stosie kalkulatora. DEFB +38,end-calc |
Elementami na stosie są WARTOŚĆ (w), GRANICA (g) i KROK (k). Wartości te teraz należy przetworzyć.
1D16 F-REORDER RST 0028,FP-CALC w, g, k DEFB +C0,st-mem-0 w, g, k (mem-0 = k) DEFB +02,delete w, g DEFB +01,exchange g, w DEFB +E0,get-mem-0 g, w, k DEFB +01,exchange g, k, w DEFB +38,end-calc |
Zostaje teraz ustawiona zmienna sterująca pętli FOR i jest traktowana jako tymczasowy obszar pamięci kalkulatora.
CALL 2AFF,LET Zmienna zostaje znaleziona lub w razie potrzeby
utworzona (używane jest w).
LD (MEM),HL Uczyń ją 'obszarem pamięci'. |
Znaleziona zmienna może okazać się zwykłą zmienną liczbową zajmującą sześć komórek, a w takim przypadku należy ją rozszerzyć.
DEC HL Pobierz jednoliterową nazwę znakową. LD A,(HL) SET 7,(HL) Upewnij się, że bit 7 tej nazwy jest ustawiony. LD BC,+0006 Będzie miała co najmniej sześć komórek. ADD HL,BC Ustaw HL za nimi. RLCA Obróć nazwę i skocz, jeśli JR C,1D34,F-L&S była to już zmienna pętli FOR. LD C,+0D Inaczej zarezerwuj trzynaście dalszych komórek. CALL 1655,MAKE-ROOM INC HL Ponownie ustaw HL na pozycję GRANICY. |
Teraz są dodawane początkowe wartości GRANICY i KROKU..
1D34 F-L&S PUSH HL Wskaźnik zostaje zapamiętany. RST 0028,FP-CALC g, k DEFB +02,delete g DEFB +02,delete - DEFB +38,end-calc DE wciąż wskazuje na 'g'. POP HL Wskaźnik jest odtwarzany i EX DE,HL oba wskaźniki są wymieniane ze sobą. LD C,+0A Dziesięć bajtów GRANICY LDIR i KROKU zostaję przemieszczone. |
Teraz zostają wprowadzone numery wiersza i rozkazu początku pętli.
LD HL,(PPC) Numer bieżącego wiersza. EX DE,HL Wymień rejestry przed LD (HL),E dołączeniem tego numeru do INC HL zmiennej sterującej pętli FOR. LD (HL),D LD D,(SUBPPC) Pierwszym rozkazem w pętli INC D zawsze jest następny rozkaz w wierszu - INC HL czy istnieje lub nie. LD (HL),D |
Zostaje wywołana procedura NEXT-LOOP, aby sprawdzić możliwość 'obiegu' i następuje powrót, jeśli taki obieg jest możliwy; w przeciwnym razie musi zostać zidentyfikowany rozkaz za pętlą FOR-NEXT.
CALL 1DDA,NEXT-LOOP Czy 'obieg' możliwy? RET NC Wróć, jeśli tak. LD B,(STRLEN-lo) Pobierz nazwę zmiennej. LD HL,(PPC) Skopiuj bieżący numer wiersza LD (NEWPPC),HL do NEWPPC. LD A,(SUBPPC) Pobierz numer bieżącego rozkazu NEG i zaneguj go arytmetycznie. LD D,A Przenieś wynik do rejestru D. LD HL,(CH-ADD) Pobierz bieżącą wartość zmiennej CH-ADD. LD E,+F3 Będzie wykonane poszukiwanie 'NEXT'. |
Teraz w obszarze programu od bieżącej pozycji w górę poszukiwane jest pierwsze wystąpienie NEXT z odpowiednią zmienną.
1D64 F-LOOP PUSH BC Zapamiętaj nazwę zmiennej. LD BC,(NXTLIN) Pobierz bieżącą wartość NXTLIN. CALL 1D86,LOOK-PROG Teraz obszar programu będzie przeszukiwany, a BC będzie się zmieniać przy każdym testowanym wierszu. LD (NXTLIN),BC Przy powrocie zapamiętaj wskaźnik. POP BC Odtwórz nazwę zmiennej. JR C,1D84,REPORT-I Jeśli nie ma dalszych rozkazów NEXT, to sygnalizuj błąd. RST 0020,NEXT-CHAR Przesuń się za znalezione NEXT. OR +20 Zezwól na duże lub małe litery, CP B zanim zostanie sprawdzona nazwa zmiennej. JR Z,1D7C,F-FOUND Skocz naprzód, jeśli jest zgodna. RST 0020,NEXT-CHAR Zwiększ ponownie CH-ADD i JR 1D64,F-LOOP skocz wstecz, jeśli zmienna nie jest właściwa. |
NEWPPC zawiera numer wiersza, w którym znaleziono właściwy rozkaz NEXT. Teraz należy znaleźć numer rozkazu i umieścić go w NSPPC.
1D7C F-FOUND RST 0020,NEXT-CHAR Zwiększ CH-ADD. LD A,+01 Licznik rozkazów w rejestrze D SUB D zliczał rozkazy wstecz od zera, zatem należy go odjąć od '1'. LD (NSPPC),A Wynik zostaje zachowany. RET Teraz powróć do STMT-RET. |
Raport I - FOR bez NEXT
1D84 REPORT-I RST 0008,ERROR-1 Wywołaj procedurę obsługi błędów. DEFB +11 |
Ta procedura wykorzystywana jest do znalezienia DATA, DEF FN lub NEXT. Na wejściu kod właściwego rozkazu umieszczony jest w rejestrze E, a para rejestrów HL wskazuje na początek przeszukiwanego obszaru.
1D86 LOOK-PROG LD A,(HL) Pobierz bieżący znak. CP +3A Skocz naprzód, jeśli jest nim ':', JR Z,1DA3,LOOK-P-2 co będzie oznaczało, że w bieżącym wierszu znajduje się więcej rozkazów. |
Teraz zostaje rozpoczęta pętla, która zbada każdy kolejny wiersz w programie.
1D8B LOOK-P-1 INC HL Pobierz starszy bajt LD A,(HL) numeru wiersza i wróć z AND +CO ustawionym przeniesieniem, jeśli SCF w programie nie ma dalszych wierszy. RET NZ LD B,(HL) Numer wiersza zostaje pobrany INC HL i przekazany do NEWPPC. LD C,(HL) LD (NEWPPC),BC INC HL Następnie zostaje pobrana długość. LD C,(HL) INC HL LD B,(HL) PUSH HL Wskaźnik jest zapamiętywany podczas ADD HL,BC tworzenia adresu końca wiersza LD B,H w parze rejestrów BC. LD C,L POP HL Wskaźnik jest odtwarzany. LD D,+00 Ustaw licznik rozkazów na zero. 1DA3 LOOK-P-2 PUSH BC Wskaźnik końca wiersza jest zapamiętywany CALL 198B,EACH-STMT podczas sprawdzania rozkazów w wierszu. POP BC RET NC Powróć, jeśli wystąpił poszukiwany rozkaz; JR 1D8B,LOOK-P-1 inaczej rozważ następny wiersz. |
'Przypisywana zmienna' została już określona (zobacz CLASS-04,1C6C); pozostaje zmiana WARTOŚCI wg wymagań.
1DAB NEXT BIT 1,(FLAGX) Jeśli zmienna nie została znaleziona, JP NZ,1C2E,REPORT-2 to skocz do raportu błędu. LD HL,(DEST) Adres zmiennej zostaje pobrany BIT 7,(HL) a nazwa jest dalej testowana. JR Z,1DD8,REPORT-1 |
Następnie WARTOŚĆ i KROK zmiennej są przetwarzane przez kalkulator.
INC HL Przejdź poza nazwę. LD (MEM),HL Uczyń zmienną tymczasowym 'obszarem pamięci' RST 0028,FP-CALC - DEFB +E0,get-mem-0 w DEFB +E2,get-mem-2 w, k DEFB +0F,addition w+k DEFB +C0,st-mem-0 w+k DEFB +02,delete - DEFB +38,end-calc - |
Wynik dodawania WARTOŚCI i KROKU jest teraz sprawdzany z GRANICĄ przez wywołanie NEXT-LOOP.
CALL 1DDA,NEXT-LOOP Sprawdź nową WARTOŚĆ z GRANICĄ. RET C Powreóć, jeśli pętla FOR-NEXT została ukończona. |
Inaczej zbierz numer wiersza i rozkazu początku pętli.
LD HL,(MEM) Znajdź adres młodszego bajtu LD DE,+000F początkowego numeru wiersza. ADD HL,DE LD E,(HL) Teraz pobierz ten numer wiersza. INC HL LD D,(HL) INC HL LD H,(HL) A za nim numer rozkazu. EX DE,HL Wymień te numery przed JP 1E73,GO-TO-2 skokiem naprzód, aby zostały potraktowane jak wiersz docelowy rozkazu GO TO. |
Raport 1 - NEXT bez FOR
1DD8 REPORT-1 RST 0008,ERROR-1 Wywołaj procedurę obsługi błędów. DEFB +00 |
Ta procedura jest używana do określenia, czy GRANICA przekroczyła bieżącą WARTOŚĆ. Procedura musi sprawdzać znak KROKU.
Jeśli GRANICA jest przekroczona, procedura wraca z ustawionym znacznikiem przeniesienia.
1DDA NEXT-LOOP RST 0028,FP-CALC - DEFB +E1,get-mem-1 g DEFB +E0,get-mem-0 g, w DEFB +E2,get-mem-2 g, w, k DEFB +36,less-0 g, w,(1/0) DEFB +00,jump-true g, w,(1/0) DEFB +02,to NEXT-1 g, w,(1/0) DEFB +01,exchange w, g 1DE2 NEXT-1 DEFB +03,subtract w-g lub g-w DEFB +37,greater-0 (1/0) DEFB +00,jump-true (1/0) DEFB +04,to NEXT-2 - DEFB +38,end-calc - AND A Wyczyść znacznik przeniesienia RET i powróć - pętla jest możliwa. |
Jednakże, gdy pętla nie jest możliwa, znacznik przeniesienia musi być ustawiony.
1DE9 NEXT-2 DEFB +38,end-calc - SCF Ustaw znacznik przeniesienia RET i powróć. |
Rozkaz READ pozwala odczytywać listę DATA i posiada efekt podobny do ciągu rozkazów LET.
Każde przypisanie w pojedynczym rozkazie READ jest obsługiwane kolejno. Zmienna systemowa X-PTR używana jest do przechowywania wskaźnika rozkazu READ, podczas gdy CH-ADD używane jest do przechodzenia przez listę DATA.
1DEC READ-3 RST 0020,NEXT-CHAR Wróć tutaj przy każdym obiegu po pierwszym, aby przejść wzdłuż rozkazu READ. 1DED READ CALL 1C1F,CLASS-01 Sprawdź, czy zmienna była wcześniej użyta; jeśli tak, to ją odszukaj. CALL 2530,SYNTAX-Z Skocz naprzód, jeśli jest sprawdzana JR Z,1E1E,READ-2 składnia. RST 0018,GET-CHAR Zapamiętaj bieżący wskaźnik LD (X-PTR),HL CH-ADD w X-PTR. LD HL,(DATADD) Pobierz wskaźnik do bieżącej listy DATA LD A,(HL) i skocz naprzód, chyba że CP +2C musi być znaleziony następny JR Z,1E0A,READ-1 rozkaz DATA. LD E,+E4 Szukanie 'DATA'. CALL 1D86,LOOK-PROG Skocz naprzód, jeśli szukanie się JR NC,1E0A,READ-1 powiodło. |
Raport E - Brak danych w DATA
1E08 REPORT-E RST 0008,ERROR-1 Wywołaj procedurę obsługi błędów. DEFB +0D |
Kontynuacja – pobieranie wartości z listy DATA.
1E0A READ-1 CALL 0077,TEMP-PTR1 Przesuń wskaźnik wzdłuż listy DATA i ustaw CH-ADD. CALL 1C56,VAL-FET-1 Pobierz wartość i przypisz ją zmiennej. RST 0018,GET-CHAR Pobierz bieżącą wartość LD (DATADD),HL CH-ADD i zapisz ją w DATADD. LD HL,(X-PTR) Pobierz wskaźnik rozkazu LD (X-PTR-hi),+00 READ i wyczyść X-PTR. CALL 0078,TEMP-PTR2 Ustaw CH-ADD ponownie na rozkaz READ. 1E1E READ-2 RST 0018,GET-CHAR Pobierz bieżący znak i sprawdź, CP +2C czy jest to ','. JR Z,1DEC,READ-3 Jeśli tak, to skocz wstecz, ponieważ są jeszcze dalsze elementy; CALL 1BEE,CHECK-END inaczej wróć poprzez RET CHECK-END (jeśli sprawdza się składnię) lub wykonaj instrukcję RET (do STMT-RET). |
Podczas sprawdzania składni rozkaz DATA jest sprawdzany, aby upewnić się, że zawiera poprawne wyrażenia rozdzielone przecinkami. W czasie wykonania rozkaz ten jest pomijany.
1E27 DATA CALL 2530,SYNTAX-Z Skocz naprzód o ile nie jest JR NZ,1E37,DATA-2 sprawdzana składnia. |
Teraz następuje wejście do pętli, które obsługuje każde wyrażenie w rozkazie DATA.
1E2C DATA-1 CALL 24FB,SCANNING Skanuj następne wyrażenie. CP +2C Sprawdź, czy jest poprawny separator - ','; CALL NZ,1BEE,CHECK-END lecz przejdź do następnego rozkazu, jeśli porównanie się nie powiodło RST 0020,NEXT-CHAR Gdy są wciąż nieprzeglądnięte wyrażenia, JR 1E2C,DATA-1 wracaj na początek pętli. |
W czasie wykonania rozkaz DATA musi być pominięty.
1E37 DATA-2 LD A,+E4 Należy pominąć rozkaz 'DATA'. |
Na wejściu rejestr A zawiera albo kod rozkazu DATA, albo kod rozkazu DEF FN w zależności od typu rozkazu, który ma zostać pominięty.
1E39 PASS-BY LD B,A Do pary rejestrów BC wpisz bardzo dużą liczbę.
CPDR Szukaj wstecz kodu rozkazu.
LD DE,+0200 Teraz szukaj wzdłuż wiersza
JP 198B,EACH-STMT następnego rozkazu. (rozkaz numer 'D-1'th
od bieżącej pozycji). |
Parametrem rozkazu RESTORE jest numer wiersza. Jeśli go nie podano, zostanie użyty numer zero.
Punkt wejścia REST-RUN jest używany przez procedurę rozkazu RUN.
1E42 RESTORE CALL 1E99,FIND-INT2 Wstaw parametr do pary rejestrów BC. 1E45 REST-RUN LD H,B Przenieś wynik do LD L,C pary rejestrów HL. CALL 196E,LINE-ADDR Teraz odszukaj adres tego wiersza lub pierwszego za nim. DEC HL Ustaw DATADD na pozycję poprzedzającą LD (DATADD),HL ten adres. RET Gdy skończone, powróć. |
Jeśli z rozkazem występuje parametr, to zostaje on umieszczony w parze rejestrów BC, a następnie przesłany do odpowiedniej zmiennej systemowej. Jednakże, jeśli parametr ma wartość zero, to zamiast niego będzie użyta zawartość zmiennych FRAMES1 i FRAMES2.
1E4F RANDOMIZE CALL 1E99,FIND-INT2 Pobierz parametr. LD A,B Skocz naprzód o ile OR C wartość parametru nie wynosi zero. JR NZ,1E5A,RAND-1 LD BC,(FRAMES1) Zamiast tego pobierz dwa młodsze bajty zmiennej systemowej FRAMES. 1E5A RAND-1 LD (SEED),BC Teraz umieść wynik w zmiennej SEED RET i powróć. |
Numer wiersza oraz numer rozkazu w wierszu są wykorzystywane do wykonania skoku.
1E5F CONTINUE LD HL,(OLDPPC) Numer wiersza. LD D,(OSPPC) Numer rozkazu w wierszu. JR 1E73,GO-TO-2 Skocz naprzód. |
Argument rozkazu GO TO powinien być numerem wiersza w zakresie od 1 do 9999, lecz faktyczny test sprawdza górną wartość 61439.
1E67 GO-TO CALL 1E99,FIND-INT2 Pobierz argument i przekaż go LD H,B do pary rejestrów HL. LD L,C LD D,+00 Ustaw numer rozkazu na zero. LD A,H Zgłoś błąd CP +F0 - liczba całkowita poza zakresem - JR NC,1E9F,REPORT-B dla numerów wierszy większych od '61439' |
Punkt wejścia GO-TO-2 jest używany do określania numeru następnego wiersza, który ma zostać obsłużony w niektórych okolicznościach.
1E73 GO-TO-2 LD (NEWPPC),HL Wprowadź numer wiersza LD (NSPPC),D a następnie numer rozkazu. RET Powróć do STMT-RET. |
Dwa parametry rozkazu OUT są pobierane ze stosu kalkulatora i używane zgodnie z ich przeznaczeniem.
1E7A OUT CALL 1E85,TWO-PARAM Pobranie parametrów. OUT (C),A Właściwa instrukcja OUT. RET Powróć do STMT-RET. |
W podobny sposób zostaje wykonany rozkaz POKE.
1E80 POKE CALL 1E85,TWO-PARAM Pobranie parametrów. LD (BC),A Właściwa operacja POKE. RET Powrót do STMT-RET. |
Parametr na szczycie stosu musi dać się załadować do pojedynczego rejestru. Jeśli jest ujemny, to zostanie poddany negacji z uzupełnieniem do dwóch. Drugi parametr musi dać się załadować do pary rejestrów.
1E85 TWO-PARAM CALL 2DD5,FP-TO-A Pobranie parametru. JR C,1E9F,REPORT-B Zgłoś błąd, jeśli ma zbyt dużą wartość. JR Z,1E8E,TWO-P-1 Skocz naprzód przy dodatnich NEG liczbach, lecz ujemne zaneguj. 1E8E TWO-P-1 PUSH AF Zapamiętaj pierwszy parametr CALL 1E99,FIND-INT2 podczas pobierania drugiego. POP AF Odtwórz pierwszy parametr RET przed powrotem. |
'Ostatnia wartość' na stosie kalkulatora zostaje pobrana odpowiednio do rejestru lub do pary rejestrów w zależności od użytego punktu wejścia FIND-INT1 lub FIND-INT2.
1E94 FIND-INT1 CALL 2DD5,FP-TO-A Pobierz ostatnią wartość. JR 1E9C,FIND-I-1 Skocz naprzód. 1E99 FIND-INT2 CALL 2DA2,FP-TO-BC Pobierz ostatnią wartość. 1E9C FIND-I-1 JR C,1E9F,REPORT-B W obu przypadkach przepełnienie jest oznaczane ustawieniem znacznika przeniesienia. RET Z Wróć ze wszystkimi liczbami dodatnimi, które są w odpowiednim zakresie. |
Raport B - Liczba całkowita poza zakresem
1E9F REPORT-B RST 0008,ERROR-1 Wywołaj procedurę obsługi błędów DEFB +0A |
Parametr rozkazu RUN jest umieszczany w NEWPPC przez wywołanie procedury rozkazu GO TO. Następnie są wykonywane operacje 'RESTORE 0' i 'CLEAR 0' przed powrotem.
1EA1 RUN CALL 1E67,GO-TO Ustaw odpowiednio NEWPPC. LD BC,+0000 Teraz wykonaj 'RESTORE 0'. CALL 1E45,REST-RUN JR 1EAF,CLEAR-1 Powróć poprzez procedurę rozkazu CLEAR. |
Procedura ta czyści obszar zmiennych oraz ekran i przesuwa RAMTOP. W wyniku ostatniej operacji zostaje przebudowany stos maszynowy procesora, co daje efekt wyczyszczenia również stosu GO SUB.
1EAC CLEAR CALL 1E99,FIND-INT2 Pobierz parametr - używając standardowo zera. 1EAF CLEAR-RUN LD A,B Skocz naprzód, jeśli parametr jest różny OR C od zera. Gdy wywołanie nastąpiło z JR NZ,1EB7,CLEAR-1 rozkazu RUN, to nie ma skoku. LD BC,(RAMTOP) Jeśli mamy zero, użyj istniejącej wartości RAMTOP. 1EB7 CLEAR-1 PUSH BC Zapamiętaj tę wartość. LD DE,(VARS) Następnie odzyskaj wszystkie bajty LD HL,(E-LINE) bieżącego obszaru zmiennych. DEC HL CALL 19E5,RECLAIM-1 CALL 0D6B,CLS Wyczyść obszar wyświetlania. |
Wartość w parze rejestrów BC, która zostanie użyta jako RAMTOP, podlega testowi, czy nie jest zbyt mała lub zbyt duża.
LD HL,(STKEND) Bieżąca wartość STKEND. LD DE,+0032 jest zwiększana o 50 przed testowaniem. ADD HL,DE Tworzy to dolną granicę. POP DE SBC HL,DE JR NC,1EDA,REPORT-M RAMTOP jest zbyt małe. LD HL,(P-RAMT) Przy teście górnej granicy dla RAMTOP AND A zostaje ono porównane z SBC HL,DE P-RAMT. JR NC,1EDC,CLEAR-2 Skocz naprzód, jeśli wartość jest akceptowalna. |
Raport M - złe RAMTOP
1EDA REPORT-M RST 0008,ERROR-1 Wywołaj procedurę obsługi błędu. DEFB +15 |
Kontynuuj operację CLEAR.
1EDC CLEAR-2 EX DE,HL Teraz ta wartość może zostać w końcu LD (RAMTOP),HL umieszczona w RAMTOP. POP DE Pobierz adres - STMT-RET. POP BC Pobierz 'adres błędu'. LD (HL),+3E Wprowadź znacznik końca stosu GO SUB. DEC HL Pozostaw jedną komórkę. LD SP,HL Ustaw wskaźnik stosu na pusty stos GO SUB. PUSH BC Następnie przekaż 'adres błędu' LD (ERR-SP),SP na stos i zapisz jego adres w ERR-SP. EX DE,HL Zostaje wykonany pośredni powrót JP (HL) do STMT-RET. |
Uwaga: Gdy procedura ta jest wywoływana z RUN, to wartości NEWPPC i NSPPC zostaną zniszczone i żadne polecenie za rozkazem RUN nigdy nie będzie znalezione przed wykonaniem skoku.
Na stosie GO SUB zostają umieszczone bieżąca wartość PPC oraz zwiększona o 1 wartość SUBPPC.
1EED GO-SUB POP DE Zapisz adres - STMT-RET. LD H,(SUBPPC) Pobierz numer rozkazu w wierszu INC H i zwiększ go. EX (SP),HL Wymień 'adres błędu' z numerem rozkazu. INC SP Zwróć jeden adres. LD BC,(PPC) Teraz zapisz bieżący numer wiersza. PUSH BC PUSH HL Zwróć 'adres błędu' LD (ERR-SP),SP na stos maszynowy i zresetuj ERR-SP, aby wskazywało na niego. PUSH DE Wróć pod adres - STMT-RET. CALL 1E67,GO-TO-1 Teraz ustaw NEWPPC i NSPPC na pożądane wartości. LD BC,+0014 Lecz przed skokiem sprawdź miejsce. |
Wykonane zostaje kilka testów, aby się upewnić, że jest wystarczająca ilość pamięci na wykonywane zadanie.
1F05 TEST-ROOM LD HL,(STKEND) Zwiększ wartość pobraną z ADD HL,BC STKEND o wartość przyniesioną do procedury w parze rejestrów BC. JR C,1F15,REPORT-4 Skocz naprzód, jeśli wynik jest większy od +FFFF. EX DE,HL Spróbuj jeszcze raz, zostawiając LD HL,+0050 kolejne osiemdziesiąt bajtów. ADD HL,DE JR C,1F15,REPORT-4 SBC HL,SP Na koniec sprawdź tę wartość z adresem stosu maszynowego. RET C Jeśli wszystko OK, powróć. |
Raport 4 - Brak pamięci
1F15 REPORT-4 LD L,+03 To jest błąd czasu wykonania JP 0055,ERROR-3 i znacznik błędu nie będzie użyty. |
Nie istnieje rozkaz FRE języka BASIC w SPECTRUM, lecz jest procedura wykonująca takie zadanie.
Oszacowanie ilości wolnej przestrzeni można zawsze uzyskać za pomocą polecenia:
PRINT 65536-USR 7962
1F1A FREE-MEM LD BC,+0000 Nie zwiększaj zajętości pamięci. CALL 1F05,TEST-ROOM Zrób test i przenieś LD B,H wynik do pary rejestrów BC LD C,L przed powrotem. RET |
Numer wiersza oraz numer rozkazu, pod które należy wykonać powrót, zostają pobrane ze stosu GO SUB.
1F23 RETURN POP BC Pobierz adres - STMT-RET. POP HL Pobierz 'adres błędu'. POP DE Pobierz ostatni element ze stosu GO SUB. LD A,D Sprawdzane jest, czy pobrany element CP +3E jest znacznikiem końca stosu GO SUB. JR Z,1F36,REPORT-7 Skocz, jeśli tak. DEC SP Pełny element używa tylko trzech komórek. EX (SP),HL Zamień numer rozkazu z 'adresem błędu'. EX DE,HL Przenieś numer rozkazu. LD (ERR-SP),SP Resetuj wskaźnik błędu. PUSH BC Zastąp adres - STMT-RET. JP 1E73,GO-TO-2 Skocz wstecz, aby zmienić NEWPPC i NSPPC. |
Raport 7 - RETURN bez GOSUB
1F36 REPORT-7 PUSH DE Zamień znacznik końca PUSH HL i 'adres błędu'. RST 0008,ERROR-1 Wywołaj procedurę obsługi błędów. DEFB +06 |
Okres dla rozkazu PAUSE zostaje określony przez zliczanie przerwań maskowanych, które występują co 1/50 sekundy.
Pauza kończy się po wystąpieniu odpowiedniej liczby tych przerwań lub gdy zmienna systemowa FLAGS sygnalizuje naciśnięcie klawisza.
1F3A PAUSE CALL 1E99,FIND-INT2 Pobierz parametr. 1F3D PAUSE-1 HALT Czekaj na przerwanie maskowane. DEC BC Zmniejsz o 1 licznik. LD A,B Jeśli w ten sposób licznik OR C osiągnie wartość zero, to rozkaz PAUSE JR Z,1F4F,PAUSE-END dobiegł do końca. LD A,B Jeśli argument miał wartość 0, AND C to teraz para rejestrów BC będzie zawierać +FFFF INC A i ta wartość zostanie sprowadzona do zera. JR NZ,1F49,PAUSE-2 Skocz przy wszystkich innych wartościach parametru. INC BC Zeruj BC. 1F49 PAUSE-2 BIT 5,(FLAGS) Skocz wstecz o ile nie został JR Z,1F3D,PAUSE-1 naciśnięty klawisz. |
Okres rozkazu PAUSE już minął.
1F4F PAUSE-END RES 5,(FLAGS) Sygnalizuj 'brak naciśniętego klawisza'. RET Teraz powróć do STMT-RET. |
Ta procedura jest wywoływana w kilku przypadkach do odczytu klawisza BREAK. Znacznik przeniesienia jest zwracany w stanie wyzerowanym tylko wtedy, gdy jednocześnie są wciśnięte klawisze SHIFT i BREAK.
1F54 BREAK-KEY LD A,+7F Utwórz adres portu IN A,(+FE) +7FFE i wczytaj z niego bajt. RRA Testuj tylko bit 0, przesuwając go na pozycję znacznika przeniesienia. RET C Wróć, gdy jest naciśnięty klawisz BREAK. LD A,+FE Utwórz adres portu IN A,(+FE) +FEFE i wczytaj z niego bajt. RRA Ponownie sprawdź bit 0. RET Wróć z wyzerowanym przeniesieniem, jeśli oba klawisze są wciśnięte. |
Podczas sprawdzania składni rozkaz DEF FN jest sprawdzany, aby upewnić się, że posiada poprawną postać. Tworzone jest również miejsce na wynik obliczania funkcji.
Lecz w czasie uruchomienia rozkaz DEF FN jest pomijany.
1F60 DEF-FN CALL 2530,SYNTAX-Z Skocz naprzód przy sprawdzaniu składni. JR Z,1F6A,DEF-FN-1 LD A,+CE Inaczej pomiń rozkaz 'DEF FN'. JP 1E39,PASS-BY |
Najpierw rozważ zmienną funkcji.
1F6A DEF-FN-1 SET 6,(FLAGS) Sygnalizuj 'zmienna liczbowa'. CALL 2C8D,ALPHA Sprawdź, czy obecny kod jest literą. JR NC,1F89,DEF-FN-4 Skocz naprzód, jeśli nie jest. RST 0020,NEXT-CHAR Pobierz następny znak. CP +24 Skocz naprzód, jeśli nie jest nim JR NZ,1F7D,DEF-FN-2 znak '$'. RES 6,(FLAGS) Zmień bit 6, ponieważ jest to zmienna łańcuchowa. RST 0020,NEXT-CHAR Pobierz następny znak.. 1F7D DEF-FN-2 CP +28 Znak '(' musi wystąpić za JR NZ,1FBD,DEF-FN-7 nazwą zmiennej. RST 0020,NEXT-CHAR Pobierz następny znak.. CP +29 Skocz naprzód, jeśli jest nim JR Z,1FA6,DEF-FN-6 ')', ponieważ funkcja nie ma parametrów. |
Teraz następuje wejście do pętli, która przetwarza kolejno każdy parametr.
1F86 DEF-FN-3 CALL 2C8D,ALPHA Obecny kod musi być 1F89 DEF-FN-4 JP NC,1C8A,REPORT-C literą. EX DE,HL Zapisz wskaźnik w DE. RST 0020,NEXT-CHAR Pobierz następny znak.. CP +24 Skocz naprzód, jeśli nie jest nim JR NZ,1F94,DEF-FN-5 znak '$'. EX DE,HL Inaczej zapisz nowy wskaźnik w DE. RST 0020,NEXT-CHAR Pobierz następny znak.. 1F94 DEF-FN-5 EX DE,HL Przesuń wskaźnik ostatniego znaku nazwy do pary rejestrów HL. LD BC,+0006 Teraz zarezerwuj sześć komórek CALL 1655,MAKE-ROOM za tym ostatnim znakiem INC HL i umieść 'znacznik liczby' w INC HL pierwszej z zarezerwowanych komórek. LD (HL),+0E CP +2C Jeśli bieżącym znakiem jest JR NZ,1FA6,DEF-FN-6 ',', to skocz wstecz, ponieważ RST 0020,NEXT-CHAR powinien wystąpić kolejny parametr; JR 1F86,DEF-FN-3 inaczej wyjdź z pętli. |
Teraz zostaje rozważona definicja funkcji.
1FA6 DEF-FN-6 CP +29 Sprawdź, że istnieje znak ')'.
JR NZ,1FBD,DEF-FN-7
RST 0020,NEXT-CHAR Zostaje pobrany następny znak.
CP +3D Musi to być znak '='.
JR NZ,1FBD,DEF-FN-7
RST 0020,NEXT-CHAR Pobierz następny znak.
LD A,(FLAGS) Zapamiętaj naturę zmiennej: numeryczna lub znakowa.
PUSH AF
CALL 2F4B,SCANNING Teraz rozważ definicję wyrażenia.
POP AF Pobierz naturę zmiennej
XOR (FLAGS) i sprawdź, czy ma ona ten sam typ
AND +40 jak ten znaleziony dla definicji.
1FBD DEF-FN-7 JP NZ,1C8A,REPORT-C Jeśli trzeba, utwórz raport błędów.
CALL 1BEE,CHECK-END Wyjdź poprzez procedurę CHECK-END.
(W ten sposób nastąpi przejście do
przetwarzania kolejnego rozkazu w wierszu.) |
Ta procedura jest wywoływana w kilku sytuacjach w celu 'wcześniejszego powrotu' z procedury, gdy jest sprawdzana składnia. Powodem jego istnienia jest właściwie unikanie drukowania znaków lub przekazywania wartości z/na stos kalkulatora.
1FC3 UNSTACK-Z CALL 2530,SYNTAX-Z Czy jest sprawdzana składnia? POP HL Pobierz adres powrotu, lecz zignoruj go RET Z 'w czasie sprawdzania składni'. JP (HL) 'W czasie uruchomienia' wykonaj prosty powrót do wywołującej procedury. |
Zostaje otwarty właściwy kanał, a elementy do wydruku zostają kolejno przetworzone.
1FC9 LPRINT LD A,+03 Przygotuj się do otwarcia kanału 'P'. JR 1FCF,PRINT-1 Skocz naprzód. 1FCD PRINT LD A,+02 Przygotuj się do otwarcia kanału 'S'. 1FCF PRINT-1 CALL 2530,SYNTAX-Z Otwórz kanał, o ile nie jest CALL NZ,1601,CHAN-OPEN sprawdzana składnia. CALL 0D4D,TEMPS Ustaw zmienne systemowe kolorów tymczasowych. CALL 1FDF,PRINT-2 Wywołaj procedurę zarządzającą wydrukiem. CALL 1BEE,CHECK-END Przejdź do obsługi następnego rozkazu; RET przy sprawdzaniu składni poprzez CHECK-END. |
Procedura zarządzająca wydrukiem jest wywoływana przez procedury rozkazów PRINT, LPRINT i INPUT.
1FDF PRINT-2 RST 0018,GET-CHAR Pobierz pierwszy znak. CALL 2045,PR-END-Z Skocz naprzód, jeśli jest JR Z,1FF2,PRINT-4 koniec listy elementów. |
Teraz wejdź do pętli, aby przetworzyć znaki sterujące pozycją oraz elementy wydruku.
1FE5 PRINT-3 CALL 204E,PR-POSN-1 Przetwarzaj wszystkie kolejne znaki JR Z,1FE5,PRINT-3 sterujące pozycją. CALL 1FFC,PR-ITEM-1 Przetwórz pojedynczy element wydruku. CALL 204E,PR-POSN-1 Sprawdzaj, czy występują dalsze znaki JR Z,1FE5,PRINT-3 sterujące pozycją oraz elementy wydruku aż nie zostanie żaden z nich. 1FF2 PRINT-4 CP +29 Wróć teraz, jeśli obecnym RET Z znakiem jest ')'; inaczej rozważ wykonanie 'powrotu karetki'. |
1FF5 PRINT-CR CALL 1FC3,UNSTACK-Z Wróć przy sprawdzaniu składni. LD A,+0D Drukuj znak powrotu karetki, RST 0010,PRINT-A-1 a później wróć. RET |
Ta procedura jest wywoływana z procedur rozkazów PRINT, LPRINT i INPUT.
Zostają rozpoznane i wydrukowane różne rodzaje elementów rozkazu PRINT.
1FFC PR-ITEM-1 RST 0018,GET-CHAR Pobierany jest pierwszy znak. CP +AC Skocz naprzód, jeśli JR NZ,200E,PR-ITEM-2 nie jest to 'AT'. |
Teraz zajmij się 'AT'.
CALL 1C79,NEXT-2NUM Na stos kalkulatora zostają przesłane dwa parametry. CALL 1FC3,UNSTACK-Z Wróć teraz przy sprawdzaniu składni. CALL 2307,STK-TO-BC Parametry zostają skompresowane do pary rejestrów BC. LD A,+16 Rejestr A zostaje załadowany znakiem JR 201E,PR-AT-TAB sterującym AT przed wykonaniem skoku. |
Teraz sprawdź 'TAB'.
200E PR-ITEM-2 CP +AD Skocz naprzód, jeśli JR NZ,2024,PR-ITEM-3 nie jest to 'TAB'. |
Zajmij się 'TAB'.
RST 0020,NEXT-CHAR Pobierz następny znak. CALL 1C82,EXPT-1NUM Prześlij jeden parametr na stos kalkulatora. CALL 1FC3,UNSTACK-Z Wróć teraz przy sprawdzaniu składni. CALL 1E99,FIND-INT2 Wartość jest kompresowana do pary rejestrów BC. LD A,+17 Rejestr A zostaje załadowany znakiem 'TAB'. |
Zostają wydrukowane elementy wydruku 'AT' i 'TAB' przez trzy wywołania procedury PRINT-OUT.
201E PR-AT-TAB RST 0010,PRINT-A-1 Drukuj znak sterujący. LD A,C Za nim pierwsza wartość. RST 0010,PRINT-A-1 LD A,B Na końcu druga wartość; RST 0010,PRINT-A-1 RET i powróć. |
Teraz zajmij się osadzonymi elementami koloru.
2024 PR-ITEM-3 CALL 21F2,CO-TEMP-3 Wróć z wyzerowanym przeniesieniem, jeśli został znaleziony element koloru. RET NC Kontynuuj, jeśli nie było żadnego. CALL 2070,STR-ALTER Teraz sprawdź, czy ma zostać zmieniony strumień. RET NC Kontynuuj, chyba że był zmieniony. |
Element wydruku musi teraz być wyrażeniem liczbowym lub łańcuchowym.
CALL 24FB,SCANNING Oblicz wyrażenie, lecz CALL 1FC3,UNSTACK-Z wróć teraz przy sprawdzaniu składni. BIT 6,(FLAGS) Testuj rodzaj wyrażenia. CALL Z,2BF1,STK-FETCH Jeśli jest to łańcuch, to pobierz niezbędne parametry; lecz przy wyrażeniu JP NZ,2DE3,PRINT-FP liczbowym wyjdź poprzez PRINT-FP. |
Zostaje teraz ustawiona pętla do przetworzenia po kolei każdego znaku łańcucha.
203C PR-STRING LD A,B Wróć teraz, jeśli nie pozostały OR C żadne znaki w łańcuchu; DEC BC inaczej zmniejsz licznik. RET Z LD A,(DE) Pobierz kod i zwiększ wskaźnik. INC DE RST 0010,PRINT-A-1 Kod zostaje wydrukowany, po czym jest robiony JR 203C,PR-STRING skok do przetworzenia dalszych znaków. |
Znacznik zera będzie ustawiony, jeśli wydruk jest skończony.
2045 PR-END-Z CP +29 Wróć teraz, jeśli znakiem jest ')'. RET Z 2048 PR-ST-END CP +0D Wróć, jeśli znakiem jest 'powrót karetki'. RET Z CP +3A Przed powrotem zrób ostatni test na ':'. RET |
W procedurze tej są przetwarzane różne znaki sterujące pozycją.
204E PR-POSN-1 RST 0018,GET-CHAR Pobierz bieżący znak. CP +3B Skocz naprzód, jeśli JR Z,2067,PR-POSN-3 jest to ';'. CP +2C Również skocz do przodu przy JR NZ,2061,PR-POSN-2 znaku różnym od ','; CALL 2530,SYNTAX-Z lecz nie drukuj tego znaku, jeśli JR Z,2067,PR-POSN-3 jest sprawdzana składnia. LD A,+06 Załaduj rejestr A znakiem RST 0010,PRINT-A-1 sterującym 'przecinek' JR 2067,PR-POSN-3 i drukuj go; następnie skocz naprzód. 2061 PR-POSN-2 CP +27 Znakiem jest '''? RET NZ Wróć teraz, jeśli brak jakichkolwiek znaków sterujących pozycją. CALL 1FF5,PR-CR Drukuj 'powrót karetki, chyba że jest sprawdzana składnia. 2067 PR-POSN-3 RST 0020,NEXT-CHAR Pobierz następny znak. CALL 2045,PR-END-Z Jeśli nie osiągnietkokońca rozkazu druku, JR NZ,206E,PR-POSN-4 to skocz naprzód; POP BC inaczej powróć do 206E PR-POSN-4 CP A procedury wywołującej. RET Znacznik zera będzie zresetowany, jeśli nie został osiągniety koniec rozkazu druku. |
Procedura jest wywoływania w razie potrzeby określenia, czy użytkownik życzy sobie skorzystać z innego strumienia.
2070 STR-ALTER CP +23 Jeśli bieżący znak nie jest znakiem '#', SCF to powróć z ustawionym znacznikiem RET NZ przeniesienia. RST 0020,NEXT-CHAR Zwiększ CH-ADD. CALL 1C82,EXPT-1NUM Przekaż parametr na stos kalkulatora. AND A Zeruj znacznik przeniesienia. CALL 1FC3,UNSTACK-Z Wróć teraz, jeśli jest sprawdzana składnia. CALL 1E94,FIND-INT1 Wartość jest przekazywana do rejestru A. CP +10 Raport O, jeśli wartość JP NC,160E,REPORT-O przekracza +F. CALL 1601,CHAN-OPEN Użyj tego kanału dla danego strumienia. AND A Wyczyść znacznik przeniesienia RET i powróć. |
Ta procedura pozwala przypisać wartości wprowadzone z klawiatury zmiennym. W rozkazie INPUT można również osadzić elementy rozkazu PRINT, które będą drukowane w dolnej części wyświetlacza.
2089 INPUT CALL 2530,SYNTAX-Z Skocz naprzód przy sprawdzaniu składni. JR Z,2096,INPUT-1 LD A,+01 Otwórz kanał 'K'. CALL 1601,CHAN-OPEN CALL 0D6E,CLS-LOWER Wyczyść spód ekranu. 2096 INPUT-1 LD (TV-FLAG),+01 Sygnalizuj użycie dolnej części ekranu. Resetuj pozostałe bity. CALL 20C1,IN-ITEM-1 Wywołaj procedurę obsługi elementów INPUT. CALL 1BEE,CHECK-END Przejdź do następnego rozkazu przy sprawdzaniu składni. LD BC,(S-POSN) Pobierz bieżącą pozycję druku. LD A,(DF-SZ) Skocz naprzód, jeśli pozycja bieżąca CP B jest ponad dolną częścią JR C,20AD,INPUT-2 ekranu. LD C,+21 Inaczej ustaw pozycję druku LD B,A na szczyt dolnej części ekranu. 20AD INPUT-2 LD (S-POSN),BC Resetuj S-POSN. LD A,+19 Teraz ustaw licznik przewinięć. SUB B LD (SCR-CT),A RES 0,(TV-FLAG) Sygnalizuj 'główny ekran'. CALL 0DD9,CL-SET Ustaw zmienne systemowe JP 0D6E,CLS-LOWER i wyjdź poprzez CLS-LOWER. |
Elementy INPUT oraz osadzone elementy PRINT są kolejno obsługiwane przez poniższą pętlę.
20C1 IN-ITEM-1 CALL 204E,PR-POSN-1 Najpierw zajmij się znakami JR Z,20C1,IN-ITEM-1 sterującymi pozycją. CP +28 Skocz naprzód, jeśli bieżącym znakiem JR NZ,20D8,IN-ITEM-2 nie jest '('. RST 0020,NEXT-CHAR Pobierz następny znak.. CALL 1FDF,PRINT-2 Teraz wywołaj procedurę rozkazu PRINT w celu obsługi elementów w nawiasach. RST 0018,GET-CHAR Pobierz bieżący znak. CP +29 Zgłoś błąd C, jeśli ten znak JP NZ,1C8A,REPORT-C jest różny od ')'. RST 0020,NEXT-CHAR Pobierz następny znak JP 21B2,IN-NEXT-2 i skocz naprzód w celu sprawdzeni, występują dalsze elementy INPUT. |
Teraz sprawdź, czy zastosowano INPUT LINE.
20D8 IN-ITEM-2 CP +CA Skocz naprzód, jeśli znak JR NZ,20ED,IN-ITEM-3 jest różny od 'LINE'. RST 0020,NEXT-CHAR Zwiększ CH-ADD. CALL 1C1F,CLASS-01 Określ adres przeznaczenia dla zmiennej. SET 7,(FLAGX) Sygnalizuj 'używanie INPUT LINE'. BIT 6,(FLAGS) Zgłoś błąd C o ile nie jest JP NZ,1C8A,REPORT-C używana zmienna łańcuchowa. JR 20FA,IN-PROMPT Skocz naprzód w celu wyświetlenia wiadomości ponaglającej. |
Zacznij obsługę prostych zmiennych INPUT.
20ED IN-ITEM-3 CALL 2C8D,ALPHA Skocz w celu sprawdzenia, czy nie będzie JP NC,21AF-IN-NEXT-1 konieczne ponowne obejście pętli, jeśli bieżący znak nie jest literą. CALL 1C1F,CLASS-01 Określ adres przeznaczenia dla zmiennej. RES 7,(FLAGX) Sygnalizuj 'nie INPUT LINE'. |
Teraz w obszarze roboczym zostaje utworzona wiadomość ponaglająca.
20FA IN-PROMPT CALL 2530,SYNTAX-Z Skocz naprzód przy sprawdzaniu składni. JP Z,21B2,IN-NEXT-2 CALL 16BF,SET-WORK Przestrzeń robocza jest ustawiana na pustą. LD HL,+5C71 To jest FLAGX. RES 6,(HL) Sygnalizuj 'wynik łańcuchowy'. SET 5,(HL) Sygnalizuj 'tryb INPUT'. LD BC,+0001 Zezwól wiadomości ponaglającej tylko na jedną komórkę. BIT 7,(HL) Skocz naprzód przy stosowaniu 'LINE'. JR NZ,211C,IN-PR-2 LD A,(FLAGS) Skocz naprzód przy oczekiwaniu AND +40 dane liczbowe. JR NZ,211A,IN-PR-1 LD C,+03 Dane łańcuchowe będą potrzebowały 3 komórek. 211A IN-PR-1 OR (HL) Bit 6 zmiennej FLAGX zostanie ustawiony LD (HL),A przy danych liczbowych. 211C IN-PR-2 RST 0030,BC-SPACES Udostępniane jest wymagane miejsce. LD (HL),+0D Znak 'powrót karetki' idzie do ostatniej komórki. LD A,C Testuj bit 6 rejestru C RRCA i skocz naprzód, jeśli jest potrzebna RRCA tylko jedna komórka. JR NC,2129,IN-PR-3 LD A,+22 Znak 'cudzysłowu' idzie do LD (DE),A pierwszej i drugiej komórki. DEC HL LD (HL),A 2129 IN-PR-3 LD (K-CUR),HL Teraz pozycja kursora może być zapamiętana. |
W przypadku INPUT LINE program EDITORA może zostać wywołany bez dalszych przygotowań, lecz dla innych trybów pracy rozkazu INPUT należy zmienić stos błędów w celu przechwytywania błędów.
BIT 7,(FLAGX) Skocz naprzód przy 'INPUT
JR NZ,215E,IN-VAR-3 LINE'
LD HL,(CH-ADD) Zapamiętaj bieżące wartości
PUSH HL zmiennych CH-ADD i ERR-SP
LD HL,(ERR-SP) na stosie maszynowym.
PUSH HL
213A IN-VAR-1 LD HL,+213A To będzie 'punkt powrotu'
PUSH HL w przypadku błędów.
BIT 4,(FLAGS2) Gdy jest używany kanał 'K',
JR Z,2148,IN-VAR-2 zmień jedynie wskaźnik stosu błędów.
LD (ERR-SP),SP
2148 IN-VAR-2 LD HL,(WORKSP) Ustaw HL na początek wiersza INPUT
CALL 11A7,REMOVE-FP i usuń wszelkie formy zmiennoprzecinkowe.
(Nie powinno ich być, jedynie po błędzie.)
LD (ERR-NR),+FF Sygnalizuj 'jak dotąd bez błędu'.
CALL 0F2C,EDITOR Teraz pobierz rozkaz INPUT i przy
RES 7,(FLAGS) znaczniku FLAGS oznaczającym składnię,
CALL 21B9,IN-ASSIGN sprawdź rozkaz INPUT na błędy;
JR 2161,IN-VAR-4 skocz, jeśli w porządku; powróć
do IN-VAR-1, jeśli nie.
215E IN-VAR-3 CALL 0F2C,EDITOR Pobierz wiersz. |
Wszystkie zmienne systemowe muszą zostać zresetowane przed wykonaniem właściwego przypisania.
2161 IN-VAR-4 LD (K-CUR-hi),+00 Adres kursora jest resetowany. CALL 21D6,IN-CHAN-K Zostaje wykonany skok przy używaniu JR NZ,2174,IN-VAR-5 kanał innego niż 'K'. CALL 111D,ED-COPY Wprowadzany wiersz jest kopiowany LD BC,(ECHO-E) na ekran, a pozycja w ECHO-E staje się CALL 0DD9,CL-SET bieżącą pozycją u dołu ekranu. 2174 IN-VAR-5 LD HL,+5C71 To jest zmienna FLAGX. RES 5,(HL) Sygnalizuj 'tryb edycji'. BIT 7,(HL) RES 7,(HL) JR NZ,219B,IN-VAR-6 Skocz naprzód przy INPUT LINE. POP HL Porzuć adres IN-VAR-1. POP HL Resetuj ERR-SP na LD (ERR-SP),HL pierwotny adres. POP HL Zapamiętaj oryginalny adres CH-ADD LD (X-PTR),HL adres w X-PTR. SET 7,(FLAGS) Teraz przy FLAGS oznaczającym wykonanie CALL 21B9,IN-ASSIGN programu dokonaj przypisania. LD HL,(X-PTR) Odtwórz oryginalny adres LD (X-PTR-hi),+00 w CH-ADD i wyczyść X-PTR. LD (CH-ADD),HL JR 21B2,IN-NEXT-2 Skocz naprzód, aby sprawdzić, czy są dalsze elementy INPUT. 219B IN-VAR-6 LD HL,(STKBOT) Znaleziona zostaje długość wiersza LD DE,(WORKSP) w obszarze roboczym. SCF SBC, HL,DE LD B,H DE wskazuje na start LD C,L BC zawiera długość. CALL 2AB2,STK-ST-$ Parametry te są umieszczane na stosie CALL 2AFF,LET i zostaje wykonane faktyczne przypisanie. JR 21B2,IN-NEXT-2 Skocz naprzód w celu obsługi dalszych elementów. |
Obsługiwane są dalsze elementy rozkazu INPUT.
21AF IN-NEXT-1 CALL 1FFC,PR-ITEM-1 Obsłuż elementy PRINT. 21B2 IN-NEXT-2 CALL 204E,PR-POSN-1 Obsłuż znaki sterujące pozycją. JP Z,20C1,IN-ITEM-1 Wróć ponownie na początek pętli, jeśli są dalsze elementy; RET inaczej powróć. |
Ta procedura jest wywoływana dwukrotnie dla każdej wartości wprowadzonej w rozkazie INPUT. Jeden raz z wyzerowanym znacznikiem składni/uruchomienia (składnia) i raz z ustawionym tym znacznikiem (uruchomienie).
21B9 IN-ASSIGN LD HL,(WORKSP) Ustaw CH-ADD na adres pierwszej LD (CH-ADD),HL komórki obszaru roboczego RST 0018,GET-CHAR i pobierz znak. CP +E2 Czy jest to 'STOP'? JR Z,21D0,IN-STOP Skocz, jeśli tak. LD A,(FLAGX) Inaczej wykonaj przypisanie CALL 1C59,VAL-FET-2 tej 'wartości' zmiennej. RST 0018,GET-CHAR Pobierz bieżący znak CP +0D i sprawdź, czy to 'powrót karetki'. RET Z Jeśli tak, powróć. |
Raport C - Nonsens w BASIC
21CE REPORT-C RST 0008,ERROR-1 Wywołaj procedurę obsługi błędów. DEFB +0B |
Przyjdź tutaj, jeśli wiersz dla rozkazu INPUT zaczyna się od znaku 'STOP'.
21D0 IN-STOP CALL 2530,SYNTAX-Z Lecz nie zgłaszaj błędu w przebiegu RET Z sprawdzającym składnię. |
Raport H - STOP w INPUT
21D4 REPORT-H RST 0008,ERROR-1 Wywołaj procedurę obsługi błędów. DEFB +10 |
Ta procedura zeruje znacznik zera, jeśli jest uzywany kanał 'K'.
21D6 IN-CHAN-K LD HL,(CURCHL) Adres bazowy informacji INC HL o kanałach dla bieżącego INC HL kanału zostaje pobrany, INC HL a kod kanału porównany INC HL z literą 'K'. LD A,(HL) CP +4B RET Po porównaniu powróć. |
Ten zbiór procedur można od razu podzielić na dwie części:
i. Sterownik osadzonych elementów koloru.
ii. Sterownik zmiennych systemowych z kolorem.
i. Osadzone elementy koloru są obsługiwane przez odpowiednie wywołanie
procedury PRINT-OUT.
Następuje wejście do pętli, w której są kolejno przetwarzane elementy
koloru. Punkt wejścia znajduje się pod adresem CO-TEMP-2.
21E1 CO-TEMP-1 RST 0020,NEXT-CHAR Zajmij się następnym znakiem
w wierszu języka BASIC.
21E2 CO-TEMP-2 CALL 21F2,CO-TEMP-3 Skocz naprzód, aby sprawdzić, czy
obecny kod przedstawia 'tymczasowy'
osadzony element koloru.
RET C Wróć z ustawionym znacznikiem przeniesienia,
jeśli tak nie jest.
RST 0018,GET-CHAR Pobierz bieżący znak.
CP +2C Skocz wstecz, jeśli jest to
JR Z,21E1,CO-TEMP-1 ',' lub ';'; inaczej
CP +3B wystąpił błąd.
JR Z,21E1,CO-TEMP-1
JP 1C8A,REPORT-C Wyjdź poprzez 'raport C'.
21F2 CO-TEMP-3 CP +D9 Wróć z ustawionym znacznikiem przeniesienia,
RET C jeśli kod nie jest w zakresie
CP +DF od +D9 do +DE (INK do OVER).
CCF
RET C
PUSH AF Kod elementu koloru jest przechowywany
RST 0020,NEXT-CHAR na czas przesunięcia adresu CH-ADD na
POP AF pozycję parametru, który występuje za kodem. |
Kod elementu koloru i parametr zostają teraz 'wydrukowane' przez wywołanie procedury PRINT-OUT w dwóch przypadkach.
21FC CO-TEMP-4 SUB +C9 Zakres znaków tokenów (+D9 do +DE) jest zmniejszany do zakresu znaków sterujących (+10 do +15). PUSH AF Kod znaku sterującego jest zapamiętywany CALL 1C82,EXPT-1NUM na czas przesyłania parametru POP AF na stos kalkulatora. AND A Jeśli jest sprawdzana składnia, CALL 1FC3,UNSTACK-Z to w tym punkcie następuje powrót. PUSH AF Kod znaku sterującego jest CALL 1E94,FIND-INT1 zapamiętywany na czas przesyłania LD D,A parametru do rejestru D. POP AF RST 0010,PRINT-A-1 Znak kontrolny zostaje wysłany do druku. LD A,D Następnie zostaje pobrany parametr RST 0010,PRINT-A-1 i również wysłany przed RET wykonaniem powrotu. |
ii. Zmienne systemowe koloru - ATTR-T, MASK-T i P-FLAG - są zmieniane według potrzeb. Ta procedura jest wywoływana przez PRINT-OUT. Na wejściu kod znaku sterującego znajduje się w rejestrze A a parametr w rejestrze D.
Zwróć uwagę, że wszystkie zmiany odnoszą się do 'tymczasowych' zmiennych systemowych.
2211 CO-TEMP-5 SUB +11 Zmniejsz zakres i skocz ADC A,+00 naprzód dla INK i PAPER. JR Z,2234,CO-TEMP-7 SUB +02 Zmniejsz ponownie zakres ADC A,+00 i skocz naprzód dla FLASH JR Z,2273,CO-TEMP-C i BRIGHT. |
Teraz kod sterowania kolorem będzie miał wartość +01 dla INVERSE i +02 dla OVER, a zmienna systemowa P-FLAG zostanie odpowiednio zmodyfikowana.
CP +01 Przygotuj się do skoku przy OVER. LD A,D Pobierz parametr. LD B,+01 Przygotuj maskę dla OVER. JR NZ,2228,CO-TEMP-6 Teraz skocz. RLCA Bit 2 rejestru A musi zostać zresetowany RLCA przy INVERSE 0 i ustawiony przy LD B,+04 INVERSE 1; maska musi mieć ustawiony bit 2. 2228 CO-TEMP-6 LD C,A Zapamiętaj rejestr A na czas sprawdzania zakresu. LD A,D Poprawny zakres dla CP +02 INVERSE i OVER wynosi jedynie JR NC,2244,REPORT-K '0-1'. LD A,C Pobierz rejestr A. LD HL,+5C91 To jest zmienna P-FLAG, którą należy zmienić. JR 226C,CO-CHANGE Wyjdź poprzez CO-CHANGE i zmień P-FLAG wykorzystując 'B' jako maskę. Tj. bit 0 przy OVER i bit 2 przy INVERSE. |
PAPER i INK są obsługiwane przez poniższą procedurę. Na wejściu jest ustawiony znacznik przeniesienia dla INK.
2234 CO-TEMP-7 LD A,D Pobierz parametr. LD B,+07 Przygotuj maskę dla INK. JR C,223E,CO-TEMP-8 Skocz naprzód przy INK. RLCA Przy PAPER wymnóż parametr przez 8. RLCA RLCA LD B,+38 Przygotuj maskę dla PAPER. 223E CO-TEMP-8 LD C,A Zapamiętaj parametr w rejestrze C na czas sprawdzania jego zakresu. LD A,D Pobierz wartość pierwotną. CP +0A Dla PAPER/INK zezwól tylko na JR C,2246,CO-TEMP-9 zakres od '0' do '9'. |
Raport K - Zły kolor
2244 REPORT-K RST 0008,ERROR-1 Wywołaj procedurę obsługi błędów. DEFB +13 |
Kontynuuj obsługę PAPER i INK;
2246 CO-TEMP-9 LD HL,+5C8F Przygotuj się do zmiany ATTR-T, MASK-T i P-FLAG. CP +08 Skocz naprzód przy PAPER/INK JR C,2258,CO-TEMP-B w zakresie od '0' do '7'. LD A,(HL) Pobierz bieżącą wartość zmiennej JR Z,2257,CO-TEMP-A ATTR-T i użyj jej bez zmiany przez skok naprzód przy PAPER/INK '8'. OR B Lecz dla PAPER/INK '9' kolory tła i tuszu CPL muszą być czarne i białe. AND +24 JR Z,2257,CO-TEMP-A Skocz przy czarnym tle/tuszu; LD A,B lecz kontynuuj z białym tuszem/tłem. 2257 CO-TEMP-A LD C,A Przenieś tę wartość do rejestru C. |
Maska (B) i wartość (C) są teraz wykorzystywane do zmiany ATTR-T.
2258 CO-TEMP-B LD A,C Przenieś tę wartość. CALL 226C,CO-CHANGE Teraz zmień ATTR-T według potrzeb. |
Następnie zostaje obsłużona zmienna MASK-T.
LD A,+07 Bity zmiennej MASK-T są ustawiane CP D tylko przy używaniu PAPER/INK SBC A,A '8' lub '9'. CALL 226C,CO-CHANGE Teraz zmień MASK-T według potrzeb. |
Następnie zostaje obsłużona zmienna P-FLAG.
RLCA Odpowiednia maska zostaje RLCA zbudowana w rejestrze B AND +50 w celu zmiany bitów 4 LD B,A i 6 według potrzeb. LD A,+08 Bity zmiennej P-FLAG są ustawiane CP D tylko przy używaniu PAPER/INK '9' SBC A,A Przejdź dalej do CO-CHANGE, aby przetworzyć P-FLAG. |
Ta procedura jest używana do 'odciśnięcia' w zmiennej systemowej stanu bitów w rejestrze A. Rejestr B zawiera maskę, która określa bity rejestru A do przekopiowania do (HL).
226C CO-CHANGE XOR (HL) Bity określone przez AND B maskę w rejestrze B ulegają zmianie, XOR (HL) a wynik trafia do zmiennej systemowej. LD (HL),A INC HL Przejdź do zaadresowania kolejnej zmiennej. LD A,B Wróć z maską w rejestrze A. RET |
FLASH i BRIGHT są obsługiwane przez poniższą procedurę.
2273 CO-TEMP-C SBC A,A Znacznik zera zostanie ustawiony dla BRIGHT. LD A,D Parametr jest pobierany RRCA i obracany. LD B,+80 Przygotuj maskę dla FLASH. JR NZ,227D,CO-TEMP-D Skocz naprzód przy FLASH. RRCA Obróć dodatkowy raz LD B,+40 i przygotuj maskę dla BRIGHT. 227D CO-TEMP-D LD C,A Zapamiętaj tę wartość w rejestrze C. LD A,D Pobierz parametr i sprawdź CP +08 jego zakres; dozwolone tylko '0', '1' i '8'. JR Z,2287,CO-TEMP-E CP +02 JR NC,2244,REPORT-K |
Teraz może zostać zmieniona zmienna systemowa ATTR-T.
2287 CO-TEMP-E LD A,C Pobierz tę wartość. LD HL,+5C8F To jest ATTR-T. CALL 226C,CO-CHANGE Teraz zmień zmienną systemową. |
Teraz zostaje rozważona wartość w MASK-T.
LD A,C Wartość zostaje pobrana od nowa. RRCA Ustawiony bit FLASH/BRIGHT RRCA '8' (bit 3) jest przesuwany RRCA na bit 7 (dla FLASH) lub na bit 6 (dla BRIGHT). JR 226C,CO-CHANGE Wyjdź poprzez CO-CHANGE. |
Parametr rozkazu BORDER jest używany w instrukcji OUT w celu faktycznej zmiany koloru brzegu. Następnie parametr ten jest zapamiętywany w zmiennej systemowej BORDCR.
2294 BORDER CALL 1E94,FIND-INT1 Parametr zostaje pobrany CP +08 i jego zakres sprawdzony. JR NC,2244,REPORT-K OUT (+FE),A Następnie jest używana instrukcja OUT do ustawienia koloru brzegu. RLCA Po czym parametr zostaje RLCA przemnożony przez osiem. RLCA BIT 5,A Jeśli kolor brzegu jest 'jasny', to JR NZ,22A6,BORDER-1 kolor tuszu w obszarze edycyjnym staje się czarny - wykonaj skok. XOR +07 Zmień kolor tuszu. 22A6 BORDER-1 LD (BORDCR),A Ustaw odpowiednio zmienną systemową, RET a następnie powróć. |
Procedurę tę wywołują rozkazy POINT i PLOT. Wejście do niej następuje ze współrzędnymi piksela umieszczonymi w parze rejestrów BC, a na wyjściu para rejestrów HL przechowuje adres bajtu w pliku ekranowym, który zawiera ten piksel, a rejestr A wskazuje na pozycję piksela wewnątrz tego bajtu.
22AA PIXEL-ADD LD A,+AF Sprawdź, czy współrzędna y (w B)
SUB B nie jest większa niż 175.
JP C,24F9,REPORT-B
LD B,A B teraz zawiera 175 minus y.
AND A A zawiera b7b6b5b4b3b2b1b0,
RRA czyli bajt z B. A teraz 0b7b6b5b4b3b2b1.
SCF
RRA Teraz 10b7b6b5b4b3b2.
AND A
RRA Teraz 010b7b6b5b4b3.
XOR B
AND +F8 Ostatecznie 010b7b6b2b1b0, zatem
XOR B w H dostajemy 64 + 8*INT (B/64) + B (mod 8),
LD H,A starszy bajt adresu piksela.
LD A,C C zawiera X.
RLCA A zaczyna od c7c6c5c4c3c2c1c0.
RLCA
RLCA Teraz jest c2c1c0c7c6c5c4c3.
XOR B
AND +C7
XOR B Teraz c2c1b5b4b3c5c4c3.
RLCA
RLCA Ostatecznie b5b4b3c7c6c5c4c3, więc
LD L,A L ma wartość 32*INT (B(mod 64)/8) + INT(x/8),
LD A,C czyli młodszy bajt.
AND +07 A zawiera x(mod 8): zatem piksel
RET jest bitem (A - 7) wewnątrz tego bajtu. |
Ta procedura jest wywoływana przez funkcję POINT w procedurze SCANNING. Wejście do niej następuje ze współrzędnymi piksela na stosie kalkulatora. Procedura zwraca na stosie 1, jeśli dany piksel ma kolor tuszu, a 0, jeśli jest koloru tła.
22CB POINT-SUB CALL 2307,STK-TO-BC Współrzędna y do B, x do C. CALL 22AA,PIXEL-ADD Adres piksela do HL. LD B,A B będzie zliczać A+1 pętli w celu INC B ustawienia pożądanego bitu (HL) na LD A,(HL) pozycji bitu 0. 22D4 POINT-LP RLCA Przesunięcia. DJNZ 22D4,POINT-LP AND +01 Bit ma wartość 1 dla tuszu, 0 dla tła. JP 2D28,STACK-A Zostaje wstawiony na stos kalkulatora. |
Ta procedura składa się z głównej części plus jeden wiersz do wywołania
jej oraz jeden wiersz do wyjścia z niej. Główna procedura jest używana
dwukrotnie przez CIRCLE oraz raz przez DRAW. Wejście do
procedury następuje ze współrzędnymi piksela na stosie kalkulatora. Znajduje
adres tego piksela i rysuje go, biorąc pod uwagę stan INVERSE i
OVER przechowywany w zmiennej systemowej
22DC PLOT CALL 2307,STK-TO-BC współrzędna Y do rejestru B, x do C. CALL 22E5,PLOT-SUB Jest wywoływana procedura główna. JP 0D4D,TEMPS Wyjście z ustawieniem kolorów tymczasowych. 22E5 PLOT-SUB LD (COORDS),BC Zostaje ustawiona ta zmienna systemowa. CALL 22AA,PIXEL-ADD Adres piksela do pary rejestrów HL. LD B,A B będzie zliczać A+1 pętli, aby ustawić zero INC B na właściwym miejscu w A. LD A,+FE Zero zostaje wprowadzone. 22F0 PLOT-LOOP RRCA Następnie jest przesuwane na DJNZ 22F0,PLOT-LOOP pozycję piksela w tym bajcie. LD B,A Dalej jest kopiowane do B. LD A,(HL) Bajt piksela zostaje pobrany do A. LD C,(P-FLAG) P-FLAG zostaje pobrane i najpierw BIT 0,C testowane na OVER. JR NZ,22FD,PL-TST-IN Skocz, jeśli OVER 1. AND B OVER 0 najpierw ustawia piksel na zero 22FD PL-TST-IN BIT 2,C Test na INVERSE. JR NZ,2303,PLOT-END INVERSE 1 po prostu zostawia piksel takim jakim był (OVER 1) lub zero (OVER 0). XOR B INVERSE 0 zostawia piksel w stanie CPL zanegowanym (OVER 1) lub 1 (OVER 0). 2303 PLOT-END LD (HL),A Bajt zostaje wstawiony do pamięci. Jego pozostałe bity nie są zmieniane w żadnym wypadku. JP 0BDB,PO-ATTR Wyjście z ustawieniem bajtu atrybutów. |
Ta procedura ładuje dwie liczby zmiennoprzecinkowe do pary rejestrów BC. W ten sposób jest ona wykorzystywana do pobierania parametrów w zakresie +00-+FF. Również wyznacza w parze rejestrów DE wartości 'ruchu po przekątnej' (+/-1,+/-1), które wykorzystuje się w procedurze rysowania linii rozkazu DRAW.
2307 STK-TO-BC CALL 2314,STK-TO-A Pierwsza liczba do A. LD B,A I dalej do B. PUSH BC Zapamiętaj na krótko. CALL 2314,STK-TO-A Druga liczba do A. LD E,C Jej znak do E. POP BC Odtwórz pierwszą liczbę. LD D,C Jej znak do D. LD C,A Druga liczba do C. RET BC, DE mają teraz pożądaną zawartość. |
Ta procedura ładuje rejestr A liczbą zmiennoprzecinkową ze szczytu stosu kalkulatora. Liczba ta musi być w zakresie 00-FF.
2314 STK-TO-A CALL 2DD5,FP-TO-A Moduł zaokrąglonej ostatniej wartości
JP C,24F9,REPORT-B trafia do A, o ile jest to możliwe; inaczej zgłoś błąd.
LD C,+01 Jeden do C dla wartości dodatniej.
RET Z Wróć, jeśli wartość jest dodatnia.
LD C,+FF Inaczej zmień C na +FF (tj. minus jeden)
RET Skończone. |
Ta procedura rysuje przybliżenie koła o środku na współrzędnych X i Y oraz o promieniu Z. Przed użyciem liczby te zostają zaokrąglone do najbliższych wartości całkowitych. Dlatego Z musi być mniejsze od 87,5, nawet jeśli punkt (X,Y) jest na środku ekranu. Użyta metoda polega na rysowaniu ciągu łuków przybliżanych liniami prostymi. Zostało to przedstawione w programie w języku BASIC umieszczonym w dodatku.
CIRCLE składa się z czterech części:
i. Testuje promień. Jeśli jego moduł jest mniejszy od 1, to po prostu rysuje punkt X,Y;
ii. Wywołuje CD-PRMS-1 pod adresem 2470-24B6, które jest wykorzystywane do ustawienia początkowych parametrów zarówno dla CIRCLE jak i dla DRAW;
iii. Ustawia pozostałe parametry dla CIRCLE, łącznie z początkowym przesunięciem pierwszego 'łuku' (będącego w rzeczywistości linią prostą);
iv. Skacze do polecenia DRAW, aby skorzystać z pętli rysowania łuków pod adresem 2420-24FA.
Teraz po kolei wyjaśnimy części od i do iii.
i. 2320-23AA. Promień, powiedzmy Z, zostaje pobrany ze stosu kalkulatora. Tworzy się jego moduł Z, który od teraz będzie używany dalej. Jeśli Z jest mniejsze od 1, to jest usuwane ze stosu kalkulatora, a punkt X,Y zostaje narysowany przez skok do PLOT.
2320 CIRCLE RST 0017,GET-CHAR Pobierz bieżący znak.
CP +2C Test na przecinek.
JP NZ,1C8A,REPORT-C Jeśli go brak, raportuj błąd.
RST 0020,NEXT-CHAR Pobierz następny znak (promień).
CALL 1C82,EXPT-1NUM Promień na stos kalkulatora.
CALL 1BEE,CHECK-END Przy sprawdzaniu składni przesuń się dalej.
RST 0028,FP-CALC Użyj kalkulatora: stos zawiera:
DEFB +2A,abs X, Y, Z
DEFB +3D,re-stack Z zostaje pobrany i umieszczony na stosie.
DEFB +38,end-calc W ten sposób staje się dostępny jego wykładnik.
LD A,(HL) Pobierz wykładnik promienia.
CP +81 Testuj, czy promień jest mniejszy od 1.
JR NC,233B,C-R-GRE-1 Jeśli nie, skocz.
RST 0028,FP-CALC Jeśli tak, usuń go ze stosu.
DEFB +02,delete Stos zawiera X, Y.
DEFB +38,end-calc
JR 22DC,PLOT Po prostu rysuj punkt X, Y. |
ii. 233B-2346 i wywołanie CD-PRMS1. W mem-5 zostaje umieszczone 2*PI i jest wywoływana procedura CD-PRMS1. Procedura ta umieszcza w rejestrze B liczbę łuków wymaganych dla tego koła. Mianowicie A=4*INT (PI*SQR Z/4)+4, stąd 4, 8, 12 ..., do maksymalnej liczby 32. Umieszcza również w mem-0 do mem-4 wartości 2*PI/A, SIN(PI/A), 0, COS (2*PI/A) oraz SIN (2*PI/A).
233B C-R-GRE-1 RST 0028,FP-CALC DEFB +A3,stk-pi/2 X, Y, Z, PI/2. DEFB +38,end-calc Teraz zwiększ wykładnik do 83 szesnastkowo, LD (HL),+83 zmieniając PI/2 na 2*PI. RST 0028,FP-CALC X, Y, Z, 2*PI. DEFB +C5,st-mem-5 2*PI jest zapisywane w mem-5. DEFB +02,delete X, Y, Z DEFB +38,end-calc CALL 247D,CD-PRMS1 Ustaw parametry początkowe. |
iii. 2347-2381: pozostałe parametry i skok do DRAW. Robiony jest test, aby sprawdzić, czy początkowa długość 'łuku' jest mniejsza od 1. Jeśli tak, to następuje po prostu skok do PLOT X,Y. W przeciwnym razie zostają ustawione parametry: X+Z i X-Z*SIN (PI/A) są umieszczane na stosie dwukrotnie jako punkt startowy i końcowy oraz kopiowane również do zmiennej systemowej COORDS; zero i 2*Z*SIN (PI/A) są umieszczane w mem-1 i mem-2 jako początkowe przyrosty, co daje jako początkowy 'łuk' pionową linię prostą łączącą X+Z, y-Z*SIN (PI/A) z X+Z, Y+Z*SIN (PI/A). Procedura rysująca łuki rozkazu DRAW zagwarantuje, że wszystkie kolejne punkty pozostaną na tym samym okręgu co te dwa, z kątem przyrostu 2*PI/A. Lecz jest jasne, że te dwa punkty w rzeczywistości rozpościerają ten kąt od punktu X+Z*(1-COS (PI/A)), Y, a nie od X, Y. Stąd punkty końcowe każdego łuku koła są przesunięte w prawo o 2*(1-COS (PI/A)), co jest wartością mniejszą od połowy piksela i zostanie zaokrąglone co najwyżej do jednego piksela.
2347 PUSH BC Zachowaj licznik łuków w B. RST 0028,FP-CALC X,Y,Z DEFB +31,duplicate X,Y,Z,Z DEFB +E1,get-mem-1 X,Y,Z,Z,SIN (PI/A) DEFB +04,multiply X,Y,Z,Z*SIN (PI/A) DEFB +38,end-calc Z*SIN (PI/A) jest połową początkowej LD A,(HL) długości 'łuku'; sprawdza się, CP +80 czy nie jest to mniejsze od 0.5. JR NC,235A,C-ARC-GE1 Jeśli nie, zostaje wykonany skok. RST 0028,FP-CALC DEFB +02,delete W przeciwnym razie Z jest usuwane ze stosu DEFB +02,delete wraz z tą połową łuku; DEFB +38,end-calc POP BC stos maszynowy zostaje wyczyszczony; JP 22DC,PLOT wykonuje się skok do PLOT X, Y. 235A C-ARC-GE1 RST 0028,FP-CALC X,Y,Z,Z*SIN (PI/A) DEFB +C2,st-mem-2 Z*SIN (PI/A) chwilowo do mem-2 DEFB +01,exchange X,Y,Z*SIN (PI/A),Z DEFB +C0,st-mem-0 X,Y,Z*SIN (PI/A),Z DEFB +02,delete X,Y,Z*SIN (PI/A) DEFB +03,subtract X, Y - Z*SIN (PI/A) DEFB +01,exchange Y - Z*SIN (PI/A), X DEFB +E0,get-mem-0 Y - Z*SIN (PI/A), X, Z DEFB +0F,addition Y - Z*SIN (PI/A), X+Z DEFB +CO,st-mem-0 X+Z jest zapisywane do mem-0 DEFB +01,exchange X+Z, Y - Z*SIN (PI/A) DEFB +31,duplicate X+Z, Y-Z*SIN (PI/A), Y-Z*SIN (PI/A) DEFB +E0,get-mem-0 sa,sb,sb,sa DEFB +01,exchange sa,sb,sa,sb DEFB +31,duplicate sa,sb,sa,sb,sb DEFB +E0,get-mem-0 sa,sb,sa,sb,sb,sa DEFB +A0,stk-zero sa,sb,sa,sb,sb,sa,0 DEFB +C1,st-mem-1 mem-1 jest zerowane DEFB +02,delete sa,sb,sa,sb,sb,sa DEFB +38,end-calc |
(Tutaj sa oznacza X+Z, a sb oznacza Y - Z*SIN (PI/A)).
INC (mem-2-1st) Zwiększenie bajtu wykładnika mem-2 ustawia mem-2 na 2*Z*SIN(PI/A). CALL 1E94,FIND-INT1 Ostatnia wartość X+Z jest przemieszczana LD L,A ze stosu do A i zapisywana w L. PUSH HL Zostaje zachowana w HL. CALL 1E94,FIND-INT1 Y - Z*SIN (PI/A) idzie ze stosu POP HL do A i jest zapisywane H. LD H,A HL teraz zawiera początkowy punkt. LD (COORDS),HL Zostaje on zapisany w COORDS. POP BC Zostaje odtworzony licznik łuków. JP 2420,DRW-STEPS Wykonuje się skok do DRAW. |
(Stos zawiera teraz X+Z, Y - Z*SIN (PI/A), Y - Z*SIN (PI/A), X+Z).
Wejście do tej procedury następuje ze współrzędnymi punktu X0, Y0 w zmiennej systemowej COORDS. Jeśli dane są tylko dwa parametry X, Y dla rozkazu DRAW, to narysuje on przybliżenie linii prostej od punktu X0, Y0 do X0+X, Y0+Y. Jeśli dany jest trzeci parametr G, to narysowane zostanie przybliżenie łuku kołowego od X0, Y0 do X0+X, Y0+Y przy obrocie odwrotnie do ruchu wskazówek zegara o kąt G radianów.
Procedura składa się z czterech części:
i. Jeśli dane są tylko dwa parametry lub średnica łuku jest mniejsza od 1, to rysuje po prostu linię prostą;
ii. Wywołuje CD-PRMS1 pod adresem 247D-24B6 w celu ustawienia początkowych parametrów;
iii. Ustawia pozostałe parametry, łącznie z początkowym przesunięciem dla pierwszego łuku;
iv. Wchodzi w pętlę rysowania łuków i rysuje ciąg mniejszych łuków przybliżanych liniami prostymi, wywołując według potrzeb procedurę ich rysowania pod adresem 24B7-24FA.
Po głównej procedurze występują dwie inne, CD-PRMS1 i DRAW-LINE. Teraz po kolei zajmiemy się czterema powyższymi częściami głównej procedury.
i. Jeśli są tylko 2 parametry, to zostaje wykonany skok do LINE-DRAW pod adresem 2477. Linia jest również rysowana, jeśli wartość Z=(ABS X + ABS Y)/ABS SIN(G/2) jest mniejsza od 1. Z ma wartość od 1 do 1,5 średnicy wynikowego koła. W tej sekcji mem-0 jest ustawiane na SIN (G/2), mem-1 na Y, a mem-5 na G.
2382 DRAW RST 0018,GET-CHAR Pobierz bieżący znak.
CP +2C Jeśli jest nim przecinek,
JR Z,238D,DR-3-PRMS to skocz.
CALL 1BEE,CHECK-END Przy sprawdzaniu składni przesuń się
do następnego rozkazu.
JP 2477,LINE-DRAW Skocz, aby tylko narysować linię.
238D DR-3-PRMS RST 0020,NEXT-CHAR Pobierz następny znak (kąt).
CALL 1C82,EXPT-1NUM Kąt umieść na stosie kalkulatora.
CALL 1BEE,CHECK-END Przy sprawdzaniu składni przesuń się
do następnego rozkazu.
RST 0028,FP-CALC X, Y, G są na stosie
DEFB +C5,st-mem-5 G jest umieszczane w mem-5.
DEFB +A2,stk-half X, Y, G, 0.5
DEFB +04,multiply X, Y, G/2
DEFB +1F,sin X, Y, SIN (G/2)
DEFB +31,duplicate X, Y, SIN (G/2), SIN (G/2)
DEFB +30,not X, Y, SIN (G/2), (0/1)
DEFB +30,not X, Y, SIN (G/2), (1/0)
DEFB +00,jump-true X, Y, SIN (G/2)
DEFB +06,to DR-SIN-NZ Jeśli SIN (G/2)=0 tj. G = 2*N*PI,
DEFB +02,delete to po prostu rysuj linię prostą.
DEFB +38,end-calc X, Y
JP 2477,LINE-DRAW Linia od X0, Y0 do X0+X, Y0+Y.
23A3 DR-SIN-NZ DEFB +C0,st-mem-0 SIN (G/2) jest umieszczane w mem-0.
DEFB +02,delete X, Y są teraz na stosie.
DEFB +C1,st-mem-1 Y jest umieszczane w mem-1.
DEFB +02,delete X
DEFB +31,duplicate X, X
DEFB +2A,abs X, X' (X' = ABS X)
DEFB +E1,get-mem-1 X, X', Y
DEFB +01,exchange X, Y, X'
DEFB +E1,get-mem-1 X, Y, X', Y
DEFB +2A,abs X, Y, X', Y' (Y' = ABS Y)
DEFB +0F,addition X, Y, X'+Y'
DEFB +E0,get-mem-0 X, Y, X'+Y', SIN (G/2)
DEFB +05,division X, Y, (X'+Y')/SIN (G/2)=Z'
DEFB +2A,abs X, Y, Z (Z = ABS Z')
DEFB +E0,get-mem-0 X, Y, Z, SIN (G/2)
DEFB +01,exchange X, Y, SIN (G/2), Z
DEFB +3D,re-stack Z jest pobierane i wstawiane na stos, aby
DEFB +38,end-calc uzyskać dostęp do jego wykładnika.
LD A,(HL) Pobierz wykładnik Z.
CP +81 Jeśli Z jest większe lub równe 1,
JR NC,23C1,DR-PRMS to skocz.
RST 0028,FP-CALC X, Y, SIN (G/2), Z
DEFB +02,delete X, Y, SIN (G/2)
DEFB +02,delete X, Y
DEFB +38,end-calc Tylko rysuj linię od X0, Y0
JP 2477,LINE-DRAW do X0+X, Y0+Y. |
ii. Wywołuje po prostu CD-PRMS1. Procedura ta zapamiętuje w
rejestrze B liczbę krótszych łuków wymaganych do narysowania pełnego łuku,
mianowicie
23C1 DR-PRMS CALL 247D,CD-PRMS1 Procedura zostaje wywołana. |
iii. Ustawia pozostałe parametry następująco: stos będzie zawierał te cztery elementy czytane z dołu do góry: X0+X i Y0+Y jako koniec ostatniego łuku; następnie X0 i Y0 jako początek pierwszego łuku. Mem-0 będzie zawierać X0, a mem-5 Y0. Mem-1 i mem-2 będą zawierały początkowe przesunięcie dla pierwszego łuku, U i V; a mem-3 i mem-4 będą zawierać COS (G/A) i SIN (G/A) do użycia w pętli rysującej łuki.
Wzory na U i V można rozwinąć następująco: zamiast kroczenia wzdłuż
końcowej cięciwy o długości L, powiedzmy, że z przesunięciami X i Y,
będziemy kroczyć wzdłuż początkowej cięciwy (która może
być dłuższa) o długości L*W, gdzie
U = Y*W*SIN (G/2 - G/2*A) + X*W*COS (G/2 -
G/2*A)
Y = Y*W*COS (G/2 - G/2*A) - X*W*SIN (G/2 - G/2*A)
Wzór ten można sprawdzić na wykresie, używając zwykłych wyrażeń COS (P - Q) i SIN (P - Q), gdzie Q = G/2 - G/2*A
23C4 PUSH BC Zapamiętaj na stosie licznik łuków w B. RST 0028,FP-CALC X,Y,SIN(G/2),Z DEFB +02,delete X,Y,SIN(G/2) DEFB +E1,get-mem-1 X,Y,SIN(G/2),SIN(G/2*A) DEFB +01,exchange X,Y,SIN(G/2*A),SIN(G/2) DEFB +05,division X,Y,SIN(G/2*A)/SIN(G/2)=W DEFB +C1,st-mem-1 W jest zapisywane do mem-1. DEFB +02,delete X,Y DEFB +01,exchange Y,X DEFB +31,duplicate Y,X,X DEFB +E1,get-mem-1 Y,X,X,W DEFB +04,multiply Y,X,X*W DEFB +C2,st-mem-2 X*W jest zapisywane do mem-2. DEFB +02,delete Y,X DEFB +01,exchange X,Y DEFB +31,duplicate X,Y,Y DEFB +E1,get-mem-1 X,Y,Y,W DEFB +04,multiply X,Y,Y*W DEFB +E2,get-mem-2 X,Y,Y*W,X*W DEFB +E5,get-mem-5 X,Y,Y*W,X*W,G DEFB +E0,get-mem-0 X,Y,Y*W,X*W,G,G/A DEFB +03,subtract X,Y,Y*W,X*W,G - G/A DEFB +A2,stk-half X,Y,Y*W,X*W,G - G/A, 1/2 DEFB +04,multiply X,Y,Y*W,X*W, G/2 - G/2*A=F DEFB +31,duplicate X,Y,Y*W,X*W, F, F DEFB +1F,sin X,Y,Y*W,X*W, F, SIN F DEFB +C5,st-mem-5 SIN F jest zapisywane do mem-5. DEFB +02,delete X,Y,Y*W,X*W,F DEFB +20,cos X,Y,Y*W,X*W, COS F DEFB +C0,st-mem-0 COS F jest zapisywane do mem-0. DEFB +02,delete X,Y,Y*W,X*W DEFB +C2,st-mem-2 X*W jest zapisywane do mem-2. DEFB +02,delete X,Y,Y*W DEFB +C1,st-mem-1 Y*W jest zapisywane do mem-1. DEFB +E5,get-mem-5 X,Y,Y*W,SIN F DEFB +04,multiply X,Y,Y*W*SIN F DEFB +E0,get-mem-0 X,Y,Y*W*SIN F,X*W DEFB +E2,get-mem-2 X,Y,Y*W*SIN F,X*W, COS F DEFB +04,multiply X,Y,Y*W*SIN F,X*W*COS F DEFB +0F,addition X,Y,Y*W*SIN F+X*W*COS F=U DEFB +E1,get-mem-1 X,Y,U,Y*W DEFB +01,exchange X,Y,Y*W,U DEFB +C1,st-mem-1 U jest zapisywane do mem-1 DEFB +02,delete X,Y,Y*W DEFB +E0,get-mem-0 X,Y,Y*W, COS F DEFB +04,multiply X,Y,Y*W*COS F DEFB +E2,get-mem-2 X,Y,Y*W*COS F,X*W DEFB +E5,get-mem-5 X,Y,Y*W*COS F,X*W, SIN F DEFB +04,multiply X,Y,Y*W*COS F,X*W*SIN F DEFB +03,subtract X,Y,Y*W*COS F - X*W*SIN F = V DEFB +C2,st-mem-2 V jest zapisywane do mem-2. DEFB +2A,abs X, Y, V' (V' = ABS V) DEFB +E1,get-mem-1 X, Y, V', U DEFB +2A,abs X, Y, V', U' (U' = ABS U) DEFB +0F,addition X, Y, U' + V' DEFB +02,delete X, Y DEFB +38,end-calc DE teraz wskazuje U' + V'. LD A,(DE) Pobierz wykładnik U' + V' CP +81 Jeśli U' + V' jest mniejsze od 1, to POP BC tylko uporządkuj stos i narysuj linię JP C,2477,LINE-DRAW od X0, Y0 do X0+X, Y0+Y. PUSH BC W przeciwnym razie kontynuuj RST 0028,FP-CALC z parametrami: X, Y na stosie. DEFB +01,exchange Y, X DEFB +38,end-calc LD A,(COORDS-lo) Pobierz X0 do A i umieść CALL 2D28,STACK-A na stosie. RST 0028,FP-CALC Y, X, X0 DEFB +C0,st-mem-0 X0 jest zapisywane w mem-0. DEFB +0F,addition Y, X0 + X DEFB +01,exchange X0+X, Y DEFB +38,end-calc LD A,(COORDS-hi) Pobierz Y0 do A i umieść CALL 2D28,STACK-A na stosie. RST 0028,FP-CALC X0+X, Y, Y0 DEFB +C5,st-mem-5 Y0 jest zapisywane do mem-5. DEFB +0F,addition X0+X, Y0+Y DEFB +E0,get-mem-0 X0+X, Y0+Y, X0 DEFB +E5,get-mem-5 X0+X, Y0+Y, X0, Y0 DEFB +38,end calc POP BC Odtwórz licznik łuków w B. |
iv. Pętla rysowania łuków. Wchodzi się do niej pod adresem 2439 ze
współrzędnymi punktu początkowego na szczycie stosu, a początkowymi
przesunięciami dla pierwszego łuku w mem-1 i mem-2. Wykorzystuje ona proste
zasady geometrii, aby zagwarantować, że wszystkie kolejne łuki zostaną
narysowane do punktów, które leżą na tym samym okręgu co pierwsze dwa,
opisując ten sam kąt w środku koła. Można pokazać, że jeśli dwa punkty X1,
Y1 i X2, Y2 leżą na okręgu i należą do kąta N ze środka, który jest również
początkiem układu współrzędnych, to
2420 DRW-STEPS DEC B B zlicza obiegi pętli. JR Z,245F,ARC-END Skocz, gdy B osiągnęło zero. JR 2439,ARC-START Skocz do pętli, aby zacząć. 2425 ARC-LOOP RST 0028,FP-CALC (Przeczytaj powyższy opis zawartości stosu). DEFB +E1,get-mem-1 Un-1 DEFB +31,duplicate Un-1,Un-1 DEBF +E3,get-mem-3 Un-1,Un-1,COS(G/A) DEFB +04,multiply Un-1,Un-1*COS(G/A) DEFB +E2,get-mem-2 Un-1,Un-1*COS(G/A),Vn-1 DEFB +E4,get-mem-4 Un-1,Un-1*COS(G/A),Vn-1,SIN(G/A) DEFB +04,multiply Un-1,Un-1*COS(G/A),Vn-1*SIN(G/A) DEFB +03,subtract Un-1,Un-1*COS(G/A)-Vn-1*SIN(G/A)=Un DEFB +C1,st-mem-1 Un jest zapisywane do mem-1. DEFB +02,delete Un-1 DEFB +E4,get-mem-4 Un-1,SIN(G/A) DEFB +04,multiply Un-1*SIN(G/A) DEFB +E2,get-mem-2 Un-1*SIN(G/A),Vn-1 DEFB +E3,get-mem-3 Un-1*SIN(G/A),Vn-1,COS(G/A) DEFB +04,multiply Un-1*SIN(G/A),Vn-1*COS(G/A) DEFB +0F,addition Un-1*SIN(G/A)+Vn-1*COS(G/A)=Vn DEFB +C2,st-mem-2 Vn jest zapisywane do mem-2. DEFB +02,delete (Jak zanotowano w tekście, stos zawiera DEFB +38,end-calc w rzeczywistości X0+X,Y0+Y, Xn i Yn). 2439 ARC-START PUSH BC Zachowaj licznik łuków. RST 0028,FP-CALC X0+X, Y0+y, Xn, Yn DEFB +C0,st-mem-0 Yn jest zapisywane do mem-0. DEFB +02,delete X0+X, Y0+Y, Xn DEFB +E1,get-mem-1 X0+X, Y0+Y, Xn, Un DEFB +0F,addition X0+X, Y0+Y, Xn+Un = Xn+1 DEFB +31,duplicate X0+X, Y0+Y, Xn+1, Xn+1 DEFB +38,end-calc Następne Xn', przybliżona wartość Xn osiągnięta przez procedurę rysowania linii, LD A,(COORDS-lo) jest zapisywane do A CALL 2D28,STACK-A a także na stos. RST 0028,FP-CALC X0+X,Y0+Y,Xn+1,Xn' DEFB +03,subtract X0+X,Y0+Y,Xn+1,Xn+1,Xn' - Xn' = Un' DEFB +E0,get-mem-0 X0+X,Y0+Y,Xn+1,Un',Yn DEFB +E2,get-mem-2 X0+X,Y0+Y,Xn+1,Un',Yn,Vn DEFB +0F,addition X0+X,Y0+Y,Xn+1,Un',Yn + Vn = Yn+1 DEFB +C0,st-mem-0 Yn+1 jest zapisywane do mem-0. DEFB +01,exchange X0+X,Y0+Y,Xn+1,Yn+1,Un' DEFB +E0,get-mem-0 X0+X,Y0+Y,Xn+1,Yn+1,Un',Yn+1 DEFB +38,end-calc LD A,(COORDS-hi) Yn', przybliżenie jak dla Xn', jest CALL 2D28,STACK-A zapisywane w A i na stosie. RST 0028,FP-CALC X0+X,Y0+Y,Xn+1,Yn+1,Un',Yn+1,Yn' DEFB +03,subtract X0+X,Y0+Y,Xn+1,Yn+1,Un',Vn' DEFB +38,end-calc CALL 24B7,DRAW-LINE Jest rysowany następny 'łuk'. POP BC Licznik łuków zostaje odtworzony. DJNZ 2425,ARC-LOOP Skocz, jeśli trzeba narysować więcej łuków. 245F ARC-END RST 0028,FP-CALC DEFB +02,delete Współrzędne końca ostatnio narysowanego DEFB +02,delete łuku zostaję teraz usunięte ze stosu. DEFB +01,exchange Y0+Y, X0+X DEFB +38,end-calc LD A,(COORDS-lo) Współrzędna X końca ostatniego CALL 2D28,STACK-A łuku, który został narysowany, powiedzmy RST 0028,FP-CALC Xz', jest zapisywana na stosie. DEFB +03,subtract Y0+Y, X0+X - Xz' DEFB +01,exchange X0+X - Xz', Y0+Y DEFB +38,end-calc LD A,(COORDS-hi) Pobrana zostaje współrzędna Y. CALL 2D28,STACK-A RST 0028,FP-CALC X0+X - Xz', Y0+Y, Yz' DEFB +03,subtract X0+X - Xz', Y0+Y - Yz' DEFB +38,end-calc 2477 LINE-DRAW CALL 24B7,DRAW-LINE Końcowy łuk jest rysowany, aby osiągnąć punkt X0+X, Y0+Y (lub zamknąć okrąg). JP 0D4D,TEMPS Wyjście z ustawieniem kolorów tymczasowych. |
Ta procedura jest wywoływana zarówno przez CIRCLE jak i DRAW w celu ustawienia ich parametrów początkowych. Przez CIRCLE jest wywoływana z X, Y i promieniem Z na szczycie stosu, czytając z dołu do góry. Przez DRAW jest wywoływana z własnymi danymi na szczycie stosu X, Y, SIN (G/2) i Z, jak opisano powyżej. W opisie pokazujemy tylko zawartość stosu od Z w górę.
Procedura zwraca w B liczbę łuków A, jak opisano w CIRCLE i DRAW powyżej, a w mem-0 do mem-5 wartości G/A, SIN (G/2*A), 0, COS (G/A), SIN (G/A) i G. Dla okręgu G musi przyjąć wartość równą 2*PI.
247D CD-PRMS1 RST 0028,FP-CALC Z DEFB +31,duplicate Z, Z DEFB +28,sqr Z, SQR Z DEFB +34,stk-data Z, SQR Z, 2 DEFB +32,exponent +82 DEFB +00,(+00,+00,+00) DEFB +01,exchange Z, 2, SQR Z DEFB +05,division Z, 2/SQR Z DEFB +E5,get-mem-5 Z, 2/SQR Z, G DEFB +01,exchange Z, G, 2/SQR Z DEFB +05,division Z, G*SQR Z/2 DEFB +2A,abs Z, G'*SQR Z/2 (G' = mod G) DEFB +38,end-calc Z, G'*SQR Z/2 = A1 CALL 2DD5,FP-TO-A A1 do A ze stosu, jeśli jest to możliwe. JR C,2495,USE-252 Jeśli A1 zaokrągla się do 256 lub więcej, użyj 252. AND +FC 4*INT (A1/4) do A. ADD A,+04 Dodaj 4, dostając liczbę łuków A. JR NC,2497,DRAW-SAVE Skocz, jeśli wciąż mniej niż 256. 2495 USE-252 LD A,+FC Tutaj po prostu użyj 252 dziesiętnie. 2497 DRAW-SAVE PUSH AF Teraz zachowaj licznik łuków. CALL 2D28,STACK-A Zapisz go również na stosie. RST 0028,FP-CALC Z, A DEFB +E5,get-mem-5 Z, A, G DEFB +01,exchange Z, G, A DEFB +05,division Z, G/A DEFB +31,duplicate Z,G/A, G/A DEFB +1F,sin Z, G/A, SIN (G/A) DEFB +C4,st-mem-4 SIN (G/A) jest zapisywane do mem-4. DEFB +02,delete Z, G/A DEFB +31,duplicate Z, G/A, G/A DEFB +A2,stk-half Z, G/A, G/A, 0.5 DEFB +04,multiply Z, G/A, G/2*A DEFB +1F,sin Z, G/A, SIN (G/2*A) DEFB +C1,st-mem-1 SIN (G/2*A) jest zapisywane do mem-1. DEFB +01,exchange Z, SIN (G/2*A), G/A DEFB +C0,st-mem-0 G/A jest zapisywane do mem-0. DEFB +02,delete Z, SIN (G/2*A) = S DEFB +31,duplicate Z, S, S DEFB +04,multiply Z, S*S DEFB +31,duplicate Z, S*S, S*S DEFB +0F,addition Z, 2*S*S DEFB +A1,stk-one Z, 2*S*S, 1 DEFB +03,subtract Z, 2*S*S - 1 DEFB +1B,negate Z, 1 - 2*S*S = COS (G/A) DEFB +C3,st-mem-3 COS (G/A) jest zapisywane do mem-). DEFB +02,delete Z DEFB +38,end-calc POP BC Odtwórz licznik łuków w B. RET Skończone. |
Procedura ta jest wywoływana przez DRAW do narysowania przybliżenia odcinka prostego od punktu X0, Y0 przechowywanego w COORDS do punktu X0+X, Y0+Y, gdzie przyrosty X i Y są na szczycie stosu kalkulatora. Procedura została pierwotnie opracowana dla komputerów ZX80 oraz ZX81 z 8K ROM, a opisano ją za pomocą programu w języku BASIC w instrukcji dla ZX81. Również tutaj zilustrowana jest w dodatku w programie rysującym koło.
Metoda polega na wykonywaniu wymaganej liczby przeplatanych kroków w poziomie lub w pionie przy ruchu wzdłuż przekątnej, wykorzystując algorytm, który rozkłada te kroki w sposób najbardziej równomierny.
24B7 DRAW-LINE CALL 2307,STK-TO-BC ABS Y do B; ABS X do C; SGN Y do D; SGN X do E. LD A,C Skocz, jeśli ABS X jest większe CP B lub równe ABS Y, aby mniejsza wartość JR NC,24C4,DL-X-GE-Y trafiła do L, a większa LD L,C do H. PUSH DE Zachowaj krok przekątny (+/-1,+/-1) w DE. XOR A Wstaw krok pionowy (+/-1, 0) LD E,A do DE (D przechowuje SGN Y). JR 24CB,DL-LARGER Teraz skocz, aby ustawić H. 24C4 DL-X-GE-Y OR C Wróć, jeśli ABS X i ABS Y RET Z są oba równe zero. LD L,B Mniejsze (tutaj ABS Y) trafia do L. LD B,C Tutaj ABS X do B. PUSH DE Również tutaj zachowaj krok przekątny. LD D,+00 Krok poziomy (0, +/-1) tutaj do DE. 24CB DL-LARGER LD H,B Większe z ABS X, ABS Y teraz do H. |
Algorytm rozpoczyna się tutaj. Większe z ABS X i ABS Y, powiedzmy H, jest wstawiane do A i zmniejszane do INT (H/2). H - L poziomych lub pionowych kroków oraz L kroków przekątnych (gdzie L jest mniejszą wartością z ABS X i ABS Y) jest wykonywane w ten sposób: L jest dodawane do A; jeśli teraz A jest równe lub większe od H, to zostaje pomniejszone o H i wykonany zostaje krok przekątny; w przeciwnym razie jest wykonywany krok poziomy lub pionowy. Powtarza się to H razy (B również zawiera H). Zauważ, że w międzyczasie rejestry zapasowe H' i L' są wykorzystywane do przechowywania wartości COORDS.
LD A,B B do A oraz do H. RRA A zaczyna od INT (H/2). 24CE D-L-LOOP ADD A,L L jest dodawane do A. JR C,24D4,D-L-DIAG Jeśli 256 lub więcej, skocz do kroku przekątnego. CP H Jeśli A jest mniejsze od H, skocz do JR C,24DB,D-L-HR-VT kroku poziomego lub pionowego. 24D4 D-L-DIAG SUB H Zmniejsz A o wartość H. LD C,A Odtwórz to w C. EXX Teraz użyj rejestrów zapasowych. POP BC Krok przekątny do B'C'. PUSH BC Również zapamiętaj go na stosie. JR 24DF,D-L-STEP Skocz, aby wykonać ten krok. 24DB D-L-HR-VT LD C,A Zachowaj A (zmniejszone) w C. PUSH DE Krok na chwilę na stos. EXX Zmień rejestry na zestaw zapasowy. POP BC Teraz krok do B'C'. 24DF D-L-STEP LD HL,(COORDS) Teraz wykonaj krok: najpierw COORDS do H'L' jako punkt startowy. LD A,B krok Y z B' do A. ADD A,H Dodaj H'. LD B,A Wynik do B' . LD A,C Teraz krok X; zostanie sprawdzony zakres INC A (Y będzie testowane w PLOT). ADD A,L Dodaj L' do C' w A, skocz przy JR C,24F7,D-L-RANGE przeniesieniu dla dalszych testów. JR Z,24F9,REPORT-B Zero bez przeniesienia oznacza pozycja X-1 jest poza zakresem. 24EC D-L-PLOT DEC A Odtwórz prawdziwą wartość w A. LD C,A Przenieś ją do C' dla rysowania punktu. CALL 22E5,PLOT-SUB Narysuj punkt. EXX Przełącz na główne rejestry. LD A,C C z powrotem do A, aby kontynuować algorytm. DJNZ 24CE,D-L-LOOP Skocz wstecz na początek pętli B razy. POP DE Wyczyść stos maszynowy. RET Skończone. 24F7 D-L-RANGE JR Z,24EC,D-L-PLOT Zero po przeniesieniu oznacza X w zakresie. |
Raport B - Liczba całkowita poza zakresem
24F9 REPORT-B RST 0008,ERROR-1 Wywołaj procedurę obsługi błędów. DEFB +0A |
Zespół Przedmiotowy Chemii-Fizyki-Informatyki w I Liceum Ogólnokształcącym im. Kazimierza Brodzińskiego w Tarnowie ul. Piłsudskiego 4 ©2024 mgr Jerzy Wałaszek |
Materiały tylko do użytku dydaktycznego. Ich kopiowanie i powielanie jest dozwolone
pod warunkiem podania źródła oraz niepobierania za to pieniędzy.
Pytania proszę przesyłać na adres email:
Serwis wykorzystuje pliki cookies. Jeśli nie chcesz ich otrzymywać, zablokuj je w swojej przeglądarce.
Informacje dodatkowe.