Ta pierwsza tablica zawiera pięć użytecznych i często potrzebnych liczb:
zero, jeden, połowę, połowę π oraz dziesięć. Liczby są zapisane w postaci
upakowanej, która zostaje rozpakowana przez procedurę UMIESZCZANIA NA STOSIE
LITERAŁÓW, zobacz poniżej, aby otrzymać pożądaną postać zmiennoprzecinkową.
dane: stała po rozpakowaniu:
wykładnik mantysa (szesnastkowo)
32C5 stk-zero DEFB +00 zero 00 00 00 00 00
DEFB +B0
DEFB +00
32C8 stk-one DEFB +40 jeden 00 00 01 00 00
DEFB +B0
DEFB +00
DEFB +01
32CC stk-half DEFB +30 pół 80 00 00 00 00
DEFB +00
32CE stk-pi/2 DEFB +F1 połowa pi 81 49 0F DA A2
DEFB +49
DEFB +0F
DEFB +DA
DEFB +A2
32D3 stk-ten DEFB +40 dziesięć 00 00 0A 00 00
DEFB +B0
DEFB +00
DEFB +0A
Ta druga tablica jest tablicą adresową sześćdziesięciu sześciu procedur
operacyjnych kalkulatora. Przesunięcia używane do indeksowania tablicy są
wyprowadzane albo z kodów operacyjnych w SKANOWANIU, zobacz na
2734, itp., albo z literałów następujących po
instrukcji RST 0028.
indeks etykieta adres indeks etykieta adres
32D7 00 jump-true 8F 3319 21 tan DA
36 37
32D9 01 exchange 3C 331B 22 asn 33
34 38
32DB 02 delete A1 331D 23 acs 43
33 38
32DD 03 subtract 0F 331F 24 atn E2
30 37
32DF 04 multiply CA 3321 25 ln 13
30 37
32E1 05 division AF 3323 26 exp C4
31 36
32E3 06 to-power 51 3325 27 int AF
38 36
32E5 07 or 1B 3327 28 sqr 4A
35 38
32E7 08 no-&-no 24 3329 29 sgn 92
35 34
32E9 09 no-l-eql 3B 332B 2A abs 6A
35 34
32EB 0A no-gr-eq 3B 332D 2B peek AC
35 34
32ED 0B nos-neql 3B 332F 2C in A5
35 34
32EF 0C no-grtr 3B 3331 2D usr-no B3
35 34
32F1 0D no-less 3B 3333 2E str$ 1F
35 36
32F3 0E nos-eql 3B 3335 2F chr$ C9
35 35
32F5 0F addition 14 3337 30 not 01
30 35
32F7 10 str-&-no 2D 3339 31 duplicate C0
35 33
32F9 11 str-l-eql 3B 333B 32 n-mod-m A0
35 36
32FB 12 str-gr-eq 3B 333D 33 jump 86
35 36
32FD 13 strs-neql 3B 333F 34 stk-data C6
35 33
32FF 14 str-grtr 3B 3341 35 dec-jr-nz 7A
35 36
3301 15 str-less 3B 3343 36 less-0 06
35 35
3303 16 strs-eql 3B 3345 37 greater-0 F9
35 34
3305 17 strs-add 9C 3347 38 end-calc 9B
35 36
3307 18 val$ DE 3349 39 get-argt 83
35 37
3309 19 usr-$ BC 334B 3A truncate 14
34 32
330B 1A read-in 45 334D 3B fp-calc-2 A2
36 33
330D 1B negate 6E 334F 3C e-to-fp 4F
34 2D
330F 1C code 69 3351 3D re-stack 97
36 32
3311 1D val DE 3353 3E series-06 49
45 34
3313 1E len 74 3355 3F stk-zero 1B
36 34
3315 1F sin B5 3357 40 st-mem-0 2D
37 34
3317 20 cos AA 3359 41 get-mem-0 0F
37 34
Uwaga: ostatnie cztery procedury są wielofunkcyjne i wejście do nich
następuje z parametrem będącym kopią pięciu bitów od prawej strony
pierwotnego literału. Pełny zestaw jest następujący:
Przesunięcie 3E: series-06, series-08 i series-0C ; literały 86,88 i 8C.
Przesunięcie 3F: stk-zero, stk-one, stk-half, stk-pi/2 i stk-ten ; literały od A0 do A4.
Przesunięcie 40: st-mem-0, st-mem-1, st-mem-2, st-mem-3, st-mem-4 i st-mem-5 ; literały od C0 do C5.
Przesunięcie 41: get-mem-0, get-mem-1, get-mem-2, get-mem-3, get-mem-4 i get-mem-5 ; literały od E0 do E5.
Ta procedura jest wykorzystywana do wykonywania obliczeń
zmiennoprzecinkowych. Można je traktować jako trzy typy:
i. Operacje dwuargumentowe, np. dodawanie, gdzie dwie liczby
w postaci zmiennoprzecinkowej są dodawane razem w celu otrzymania jednej
'ostatniej wartości'.
ii. Operacje jednoargumentowe, np. sin, gdzie 'ostatnia wartość'
jest wymieniana z wynikiem odpowiedniej funkcji..
iii. Operacje manipulacyjne, np. st-mem-0, gdzie 'ostatnia wartość' jest
kopiowana do pierwszych pięciu bajtów w obszarze pamięci kalkulatora.
Operacje do wykonania są określane jako ciąg bajtów danych, literałów,
które następują po instrukcji RST 0028 wywołującej tę procedurę. Ostatnim
literałem na liście jest zawsze '38', który prowadzi do zakończenia całej
operacji.
W przypadku konieczności wykonania pojedynczej operacji, jej przesunięcie
można przekazać do procedury CALCULATOR w rejestrze B, a '3B' do procedury
SINGLE CALCULATION.
Jest możliwe również rekursywne wywoływanie tej procedury, tj. z niej
samej, a w takim przypadku można korzystać ze zmiennej systemowej BREG w
charakterze licznika, który kontroluje ilość wykonywanych operacji przed
powrotem.
Pierwsza część tej procedury jest skomplikowana, lecz głównie wykonuje
ona dwa zadania ustawiania rejestrów, aby zawierały pożądane wartości, oraz
tworzenia przesunięcia wraz z możliwym parametrem z przetwarzanego w danej
chwili literału.
Przesunięcie jest wykorzystywane do indeksowania tablicy adresów
kalkulatora, zobacz powyżej, w celu znalezienia adresu pożądanej procedury.
Parametr jest wykorzystywany przy odwoływaniu się do procedur
wielofunkcyjnych.
Uwaga: Liczba zmiennoprzecinkowa może w rzeczywistości być zbiorem
parametrów łańcuchowych.
335B CALCULATE CALL 35BF,STK-PNTRS Załóż operację jednoargumentową i dlatego
ustaw HL na wskazywanie początku
"ostatniej wartości" na stosie kalkulatora,
a DE na adres o jeden więcej od
od końca tej liczby zmiennoprzecinkowej (STKEND).
335E GEN-ENT-1 LD A,B Albo przekaż indeks pojedynczej
operacji tymczasowo
LD (BREG),A do BREG, albo przy rekurencyjnym użyciu tej
procedury przekaż parametr
do BREG, który ma być użyty jako licznik.
3362 GEN-ENT-2 EXX Adres powrotny z procedury zostaje umieszczony
w H'L'. Zachowuje to
EX (SP),HL wskaźnik do pierwszego literału. Wejście do
kalkulatora poprzez GEN-ENT-2
używane jest zawsze, gdy BREG ma jest licznikiem
i nie wolno go zmieniać.
3365 RE-ENTRY LD (STKEND),DE Teraz w pętli zostaną przetworzone po kolei
wszystkie literały na liście,
która występuje po wywołaniu tego polecenia;
zatem najpierw zawsze ustaw STKEND.
EXX Przejdź do zapasowych rejestrów
LD A,(HL) i pobierz literał dla tego obiegu pętli.
INC HL Ustaw H'L' na kolejny literał.
336C SCAN-ENT PUSH HL Wskaźnik ten zostaje na krótko zapisany na
stosie maszynowym. SCAN-ENT
jest używane przez procedurę SINGLE CALCULATION
do znalezienia potrzebnej procedury.
AND A Testuj rejestr A.
JP P,3380,FIRST-3D Oddziel proste literały od literałów wielozadaniowych.
Skocz z literałami 00 - 3D.
LD D,A Zapamiętaj literał w D.
AND +60 Kontynuuj tylko z bitami 5 i 6.
RRCA Cztery przesuwy w lewo robi je
RRCA teraz bitami 1 i 2.
RRCA
RRCA
ADD A,+7C Potrzebnymi indeksami są 3E-41,
LD L,A a L będzie teraz przechowywało podwojony indeks.
LD A,D Teraz utwórz parametr z bitów
AND +1F 0,1,2,3 & 4 literału; trzymaj parametr w A.
JR 338E,ENT-TABLE Skocz naprzód, aby znaleźć adres wymaganej procedury.
3380 FIRST-3D CP +18 Skocz naprzód przy wykonywaniu operacji jednoargumentowej.
EXX Wszystkie procedury dwuargumentowe wymagają, aby
LD BC,+FFFB HL wskazywało na pierwszy czynnik, a DE na drugi
LD D,H ('ostatnia wartość') w takiej kolejności, jak występują
LD E,L na stosie kalkulatora.
ADD HL,BC
EXX
338C DOUBLE-A RLCA Ponieważ każda pozycja w tablicy
LD L,A adresów zajmuje dwa bajty, to utworzony indeks
zostaje podwojony.
338E ENT-TABLE LD DE,+32D7 Adres początku tej tablicy.
LD H,+00 Adres pożądanego elementu tablicy jest tworzony w HL;
ADD HL,DE a pożądany adres procedury zostaje załadowany do DE.
LD E,(HL)
INC HL
LD D,(HL)
LD HL,+3365 Adres punktu ponownego wejścia 3365
EX (SP),HL zostaje umieszczony na stosie maszynowym
PUSH DE pod adresem procedury.
EXX Powróć do głównego zestawu rejestrów.
LD BC,(STKEND-hi) Bieżąca wartość BREG jest umieszczana w rejestrze B,
zwracając w ten sposób indeks pojedynczej operacji.
(Zobacz na operacje porównań pod adresem 353B).
PROCEDURA 'USUNIĘCIA ZE STOSU'
(Indeks 02: 'delete)
Procedura ta zawiera jedynie pojedynczą instrukcję RET pod adresem 33A1
powyżej. Literał '02' w tej procedurze traktowanej jako operacja
dwuargumentowa, którą należy wywołać z pierwszą liczbą adresowaną przez parę
rejestrów HL, a drugą liczba adresowaną przez parę rejestrów DE i wynik
adresowany ponownie przez parę rejestrów HL.
Stąd pojedyncza instrukcja RET prowadzi do potraktowania pierwszej liczby
jako wynikowej 'ostatniej wartości', a drugiej wartości do potraktowania
jako usuniętej. Oczywiście liczba ta nie została usunięta z pamięci, lecz
pozostaje nieaktywna i zostanie prawdopodobnie wkrótce nadpisana.
33A1 delete RET Skok pośredni do pożądanej procedury.
PROCEDURA 'OPERACJI POJEDYNCZEJ'
(Indeks 3B: 'fp-calc-2')
Procedura ta jest wywoływana tylko ze SCANNING pod adresem 2757
szesnastkowo i używa się jej do wykonania pojedynczej operacji
arytmetycznej. Indeks określający rodzaj operacji do wykonania jest
dostarczany kalkulatorowi w rejestrze B i dalej przekazywany do
zmiennej systemowej BREG.
Efektem wykonania tej procedury jest głównie wykonanie skoku do
odpowiedniej procedury w celu wykonania pojedynczej operacji.
33A2 fp-calc-2 POP AF Usuń adres ponownego wejścia.
LD A,(BREG) Przenieś indeks do A.
EXX Wybierz alternatywny zestaw rejestrów.
JR 336C,SCAN-ENT Skocz wstecz, aby znaleźć pożądany adres;
umieść na stosie adres ponownego wejścia i skocz
do procedury wykonującej operację.
PROCEDURA 'TESTU NA 5-BAJTÓW'
Ta procedura sprawdza, czy w pamięci znajduje się wystarczające miejsce
na kolejną liczbę zmiennoprzecinkową, która ma zostać umieszczona na stosie
kalkulatora.
33A9 TEST-5-SP PUSH DE Zapamiętaj chwilowo DE
PUSH HL i HL.
LD BC,+0005 Test będzie na pięć bajtów.
CALL 1F05,TEST-ROOM Wykonaj test.
POP HL Odtwórz HL
POP DE i DE.
RET Zrobione.
PROCEDURA 'UMIESZCZENIA LICZBY NA STOSIE'
Procedura ta jest wywoływana przez BEEP i dwukrotnie przez SCANNING, aby
skopiować STKEND do DE, umieścić liczbę zmiennoprzecinkową na stosie
kalkulatora oraz zresetować STKEND z DE. Do wykonania faktycznego
umieszczenia procedura wywołuje MOVE-FP.
33B4 STACK-NUM LD DE,(STKEND) Skopiuj STKEND do DE jako adres przeznaczenia.
CALL 33C0,MOVE-FP Przemieść liczbę.
LD (STKEND),DE Odtwórz STKEND z DE.
RET Zrobione.
PROCEDURA 'PRZENIESIENIA LICZBY ZMIENNOPRZECINKOWEJ'
(Indeks 31: 'duplicate')
Procedura przenosi liczbę zmiennoprzecinkową na szczyt stosu kalkulatora
(3 przypadki) oraz ze szczytu stosu do obszaru
pamięci kalkulatora (1 przypadek). Jest również
wywoływana przez kalkulator, gdy po prostu tworzy duplikat liczby na
szczycie stosu kalkulatora jako 'ostatnią wartość', powiększając w ten
sposób ten stos o pięć bajtów.
33C0 MOVE-FP CALL 33A9,TEST-5-SP Sprawdzanie dostępności miejsca.
LDIR Przesuń te pięć bajtów.
RET Zrobione.
PROCEDURA 'UMIESZCZENIA NA STOSIE LITERAŁÓW'
(Indeks 34: 'stk-data')
Ta procedura umieszcza na stosie kalkulatora, jako 'ostatnią wartość',
liczbę zmiennoprzecinkową dostarczoną do niej jako literały 2, 3, 4 lub 5.
Jeśli zostanie wywołana przy pomocy indeksu '34', to literały te
następują za '34' na liście literałów; przy wywołaniu przez GENERATOR
CIĄGÓW, zobacz niżej, literały są dostarczane przez podprocedurę wywołaną
dla ciągów do wygenerowania, a kiedy zostanie wywołana przez
POMINIĘCIE STAŁYCH lub
UMIESZCZENIE NA STOSIE
STAŁEJ, to literały zostaną pobrane z tablicy stałych kalkulatora
(32C5-32D6).
W każdym przypadku pierwszy z dostarczonych literałów jest dzielony przez
40 szesnastkowo, a wynik całkowity plus 1 określa, czy ze źródła zostanie
pobrane 1, 2, 3 lub 4 dalsze literały w celu utworzenia mantysy liczby.
Niewypełnione bajty z 5 bajtów, które mają utworzyć liczbę
zmiennoprzecinkową, zostają ustawione na 0. Pierwszy literał jest również
używany do określenia cechy, po zredukowaniu przez modulo 40 szesnastkowo, o
ile reszta nie jest równa zero, w którym to przypadku użyty zostaje drugi
literał w takiej postaci, w jakiej jest, bez redukowania modulo 40
szesnastkowo. W pozostałych przypadkach do literału jest dodawane 50
szesnastkowo, co daje rozszerzony bajt cechy, e (prawdziwa
cecha e' plus 80 szesnastkowo). Reszta z tych 5 bajtów zostaje
umieszczona na stosie łącznie z zerami i procedura kończy działanie.
33C6 STK-DATA LD H,D Ta procedura dokonuje operacji manipulacyjnych
dodawania 'ostatniej wartości'
LD L,E do stosu kalkulatora; stąd HL jest ustawiany na
adres o 1 większy niż
koniec bieżącej 'ostatniej wartości', co w efekcie
powoduje wskazanie wyniku.
33C8 STK-CONST CALL 33A9,TEST-5-SP Teraz sprawdź, czy rzeczywiście jest miejsce.
EXX Przełącz na rejestry zapasowe
PUSH HL i umieść na stosie wskaźnik następnego literału.
EXX
EX (SP),HL Wymień ze sobą wskaźnik wyniku ze wskaźnikiem
następnego literału.
PUSH BC Na krótko zachowaj BC.
LD A,(HL) Umieść pierwszy literał w A
AND +C0 i podziel go przez 40 szesnastkowo, aby otrzymać
RLCA wartości całkowite 0, 1, 2 lub 3.
RLCA
LD C,A Część całkowita jest przenoszona do C
INC C i zwiększana o 1, dając w wyniku 1, 2, 3 lub 4
jako liczbę potrzebnych literałów.
LD A,(HL) Literał zostaje ponownie pobrany,
AND +3F zredukowany przez modulo 40 szesnastkowo i pominięty,
JR NZ,33DE,FORM-EXP jeśli reszta jest równa zero;
INC HL w którym to przypadku zostanie pobrany następny literał
LD A,(HL) i użyty bez redukowania.
33DE FORM-EXP ADD A,+50 Zostaje utworzona cecha, e, przez dodanie 50 szesnastkowo
LD (DE),A i umieszczenie jej na stosie kalkulatora jako pierwszy
z pięciu bajtów wyniku.
LD A,+05 Liczba literałów określona przez
SUB C C zostaje pobrana ze źródła
INC HL i umieszczona w bajtach wyniku.
INC DE
LD B,+00
LDIR
POP BC Przywróć BC.
EX (SP),HL Zwróć wskaźnik wyniku do HL,
EXX a wskaźnik następnego literału do jego zwykłego miejsca
POP HL w H'L'.
EXX
LD B,A Liczba bajtów zerowych, które będą potrzebne na tym etapie,
XOR A jest otrzymywana jako 5 - C - 1;
33F1 STK-ZEROS DEC B 5-C-1; a bajty te są dodawane do wyniku, aby utworzyć
RET Z potrzebne pięć bajtów liczby zmiennoprzecinkowej.
LD (DE),A
INC DE
JR 33F1,STK-ZEROS
PROCEDURA 'POMINIĘCIA STAŁYCH'
Do procedury tej wchodzi się z parą rejestrów HL przechowującą adres
bazowy tablicy stałych kalkulatora i z rejestrem A zawierającym parametr
określający, która z pięciu stałych jest potrzebna.
Procedura wykonuje puste operacje ładowania pięciu bajtów każdej z
niepożądanych stałych do adresów 0000, 0001, 0002, 0003 i 0004 na początku
obszaru ROM aż do osiągnięcia zadanej stałej.
Powrót następuje z parą rejestrów HL zawierającą adres bazowy pożądanej
stałej wewnątrz tablicy stałych.
33F7 SKIP-CONS AND A Procedura kończy działanie, jeśli
33F8 SKIP-NEXT RET Z parametrem jest zero lub
zostanie osiągnięta pożądana stała.
PUSH AF Zapamiętaj parametr.
PUSH DE Zapamiętaj wskaźnik wyniku.
LD DE,+0000 Pusty adres.
CALL 33C8,STK-CONST Wykonaj ładowanie na niby rozwiniętej stałej.
POP DE Odtwórz wskaźnik wyniku.
POP AF Odtwórz parametr.
DEC A Zlicz obiegi pętli.
JR 33F8,SKIP-NEXT Wróć do rozpatrzenia wartości licznika.
PROCEDURA 'POZYCJA W PAMIĘCI'
Ta procedura znajduje adres bazowy każdej grupy pięciu bajtów w obszarze
pamięci kalkulatora, do której lub z której zostanie przesłana liczba
zmiennoprzecinkowa z lub na stos kalkulatora. Wykonuje to dodając pięć razy
dostarczony parametr do adresu bazowego obszaru przechowywanego w parze
rejestrów HL.
Zwróć uwagę, że przy obsłudze zmiennej sterującej pętli FOR-NEXT
wskaźniki zostają tak zmienione, że zmienna jest traktowana jakby była
obszarem pamięci kalkulatora (zobacz pod adres
1D20).
3406 LOC-MEM LD C,A Skopiuj parametr do C.
RLCA Podwój parametr.
RLCA Podwój wynik.
ADD A,C Dodaj wartość parametru, aby otrzymać
pięciokrotność pierwotnej wartości.
LD C,A Wynik jest potrzebny w parze rejestrów BC.
LD B,+00
ADD HL,BC Utwórz adres bazowy.
RET Skończone.
PROCEDURA 'POBRANIA Z OBSZARU PAMIĘCI'
(Indeksy E0 do E5: 'get-mem-0' do 'get-mem-5')
Procedura jest wywoływana z literałami E0 do E5, a parametr pobrany z
tych literałów znajduje się w rejestrze A. Procedura wywołuje POZYCJĘ W
PAMIĘCI, aby umieścić pożądany adres źródłowy w parze rejestrów HL oraz
PRZENIESIENIE LICZBY ZMIENNOPRZECINKOWEJ, aby przenieść powiązane pięć
bajtów z obszaru pamięci kalkulatora na szczyt stosu kalkulatora, gdzie
utworzą 'ostatnią wartość'.
340F get-mem-0 PUSH DE Zachowaj wskaźnik wyniku.
etc. LD HL,(MEM) Pobierz wskaźnik bieżącego obszaru pamięci (zobacz wyżej).
CALL 3406,LOC-MEM Znajdowany jest adres bazowy.
CALL 33C0,MOVE-FP Przesłane zostaje pięć bajtów.
POP HL Odtwórz wskaźnik wyniku.
RET Skończone.
PROCEDURA 'UMIESZCZENIA NA STOSIE STAŁEJ'
(Indeksy A0 do A4:
'stk-zero','stk-one','stk-half','stk-pi/2' i 'stk-ten')
Procedura używa POMINIĘCIA STAŁYCH do znalezienia adresu bazowego
pożądanej stałej w tablicy stałych kalkulatora, a następnie wywołuje
UMIESZCZENIE NA STOSIE LITERAŁÓW, aby uczynić rozwiniętą postać stałej
'ostatnią wartością' na stosie kalkulatora.
341B stk-zero LD H,D Umieść w HL wskaźnik wyniku.
LD L,E
EXX Przejdź do zapasowego zestawu rejestrów
PUSH HL i zachowaj wskaźnik następnego literału.
LD HL,+32C5 Adres bazowy tablicy stałych kalkulatora.
EXX Wróć do głównego zestawu rejestrów.
CALL 33F7,SKIP-CONS Znajdź pożądany adres bazowy.
CALL 33C8,STK-CONST Rozwiń stała.
EXX
POP HL Odtwórz wskaźnik następnego literału.
EXX
RET Skończone.
PROCEDURA 'ZAPAMIĘTANIA W OBSZARZE PAMIĘCI'
(Indeksy C0 do C5: 'st-mem-0' do 'st-mem-5')
Tę procedurę wywołuje się używając literałów C0 to C5 z parametrem
odczytanym z nich i przechowywanym w rejestrze A. Procedura jest bardzo
podobna do POBRANIA Z PAMIĘCI, jednak wskaźniki źródła i przeznaczenia są
zamienione.
342D st-mem-0 PUSH HL Zapamiętaj wskaźnik wyniku.
etc. EX DE,HL Chwilowo źródło do DE.
LD HL,(MEM) Pobierz wskaźnik do bieżącego obszaru pamięci.
CALL 3406,LOC-MEM Znajdź adres bazowy.
EX DE,HL Zamień ze sobą wskaźniki źródła i przeznaczenia.
CALL 33C0,MOVE-FP Przemieść pięć bajtów.
EX DE,HL 'Ostatnia wartość' +5, tj. STKEND do DE.
POP HL Wynik do HL.
RET Skończone.
Zwróć uwagę, że wskaźniki HL i DE pozostają bez zmian, wskazując
odpowiednio na STKEND-5 i STKEND, zatem 'ostatnia wartość' pozostaje na
stosie kalkulatora. Jeśli będzie konieczne, można ją usunąć za pomocą
'delete'.
(Indeks 01: 'exchange')
Ta dwuargumentowa operacja 'wymienia' ze sobą pierwszą liczbę i drugą
liczbę, tj. dwie liczby na szczycie stosu kalkulatora zostają zamienione
miejscami.
343C EXCHANGE LD B,+05 Należy operować na pięciu bajtach.
343E SWAP-BYTE LD A,(DE) Każdy bajt pierwszej liczby.
LD C,(HL) Każdy bajt drugiej liczby.
EX DE,HL Zamień miejscami wskaźniki źródła i przeznaczenia.
LD (DE),A Teraz bajt pierwszej liczby zostaje umieszczony
w bajcie drugiej.
LD (HL),C Bajt drugiej liczby trafia do bajtu pierwszej.
INC HL Wskaźniki są przesuwane na następne pary bajtów.
INC DE
DJNZ 343E,SWAP-BYTE Zamień miejscami pięć bajtów.
EX DE,HL Odtwórz poprawny stan wskaźników, ponieważ 5
jest nieparzyste.
RET Skończone.
(Indeksy 86,88 i 8C: 'series-06','series-08' i
'series-0C')
Ta ważna procedura generuje szeregi wielomianów Czebyszewa, które
wykorzystuje się do przybliżania wartości funkcji SIN, ATN, LN i
EXP, a stąd
do wyliczania innych funkcji arytmetycznych, które zależą od nich
(COS, TAN, ASN, ACS, ** i
SQR).
Wielomiany są tworzone, dla n=1,2,..., za pomocą wyrażenia
rekurencyjnego:
Tn+1(z) = 2zTn(z) - Tn-1(z), gdzie Tn(z)
jest n-tym wielomianem Czebyszewa w z.
W rzeczywistości szereg ten generuje:
T0, 2T1, 2T2,.... ,2Tn-1,
gdzie n wynosi 6 dla SIN, 8 dla EXP i 12 dla LN oraz ATN.
Współczynniki potęg z w tych wielomianach można znaleźć w Podręczniku
Funkcji Matematycznych, napisanym przez M. Abramowitza i I.A. Steguna
(Dover 1965), na stronie 795.
Programy w języku BASIC pokazujące obliczanie każdej z tych funkcji są
tutaj podane w Załączniku.
Mówiąc prosto, procedura ta jest wywoływana z 'ostatnią wartością' na
stosie kalkulatora, powiedzmy Z, będącą liczbą odnoszącą się do argumentu,
powiedzmy X, gdy zadanie polega przykładowo na obliczeniu SIN X. Wywołująca
procedura również dostarcza listę stałych, które będą potrzebne
(sześć stałych dla SIN). GENERATOR SZEREGÓW
następnie przetwarza swoje dane i zwraca do wywołującej go procedury
'ostatnią wartość', która jest w prostej zależności do pożądanej funkcji, na
przykład SIN X.
Można uważać, że procedura składa się z czterech głównych części:
i. Ustawienie licznika pętli:
Procedura wywołująca przekazuje informację o liczbie argumentów w
rejestrze A, który ma pełnić rolę licznika. Następuje ponowne wywołanie
kalkulatora pod adresem GEN-ENT-1, gdzie zostaje
ustawiony licznik.
3449 series-06 LD B,A Przenieś parametr do B.
etc. CALL 335E,GEN-ENT-1 W zasadzie jest to instrukcja RST 0028,
lecz z ustawieniem licznika
ii. Obsługa 'ostatniej wartości', Z:
Pętla generatora wymaga, aby 2*Z zostało umieszczone w mem-0, zero w
mem-2, a 'ostatnia wartość' wyzerowana.
stos kalkulatora
DEFB +31,duplicate Z,Z
DEFB +0F,addition 2*Z
DEFB +C0,st-mem-0 2*Z mem-0 zawiera 2*Z
DEFB +02,delete -
DEFB +A0,stk-zero 0
DEFB +C2,st-mem-2 0 mem-2 zawiera 0
iii. Pętla główna:
Szereg jest tworzony w pętli przy wykorzystywaniu BREG jako licznika;
stałe w wywołującej procedurze są kolejno umieszczane na stosie przez
wywołanie STK-DATA; ponowne wejście do kalkulatora
wykonywane jest w punkcie GEN-ENT-2, aby nie zaburzyć
wartości BREG, a szereg przyjmuje następująca postać:
B(R) = 2*Z*B(R-1) - B(R-2) + A(R), dla R = 1,2,...,N, gdzie A(1),
A(2),..., A(N) są stałymi dostarczonymi przez wywołującą procedurę
(SIN, ATN, LN i EXP), a B(0) = 0 = B(-1).
Obieg pętli o numerze (R+1) rozpoczyna się z B(R) na stosie i z
2*Z,
B(R-2) i B(R-1) odpowiednio w mem-0, mem-1 i mem-2.
3453 G-LOOP DEFB +31,duplicate B(R),B(R)
DEFB +E0,get-mem-0 B(R),B(R),2*Z
DEFB +04,multiply B(R),2*B(R)*Z
DEFB +E2,get-mem-2 B(R),2*B(R)*Z,B(R-1)
DEFB +C1,st-mem-1 mem-1 zawiera B(R-1)
DEFB +38,end-calc DEFB +03,subtract B(R),2*B(R)*Z-B(R-1)
Na stosie kalkulatora umieszczana jest kolejna stała.
CALL 33C6,STK-DATA B(R),2*B(R)*Z-B(R-1),A(R+1)
Kalkulator jest wywoływany bez niszczenia BREG.
CALL 3362,GEN-ENT-2
DEFB +0F,addition B(R),2*B(R)*Z-B(R-1)+A(R+1)
DEFB +01,exchange 2*B(R)*Z-B(R-1)+A(R+1),B(R)
DEFB +C2,st-mem-2 mem-2 zawiera B(R)
DEFB +02,delete 2*B(R)*Z-B(R-1)+A(R!1) = (R!1)
DEFB +35,dec-jr-nz B(R+1)
DEFB +EE, do 3453,G-LOOP
iv. Odjęcie B(N-2):
Powyższa pętla zostawia B(N) na stosie, a pożądany wynik jest otrzymywany
przez B(N) - B(N-2).
DEFB +E1,get-mem-1 B(N),B(N-2)
DEFB +03,subtract B(N)-B(N-2)
DEFB +38,end-calc
RET Skończone.
FUNKCJA 'WARTOŚCI BEZWZGLĘDNEJ'
(Indeks 2A: 'abs')
Procedura ta wykonuje swoją operację jednoargumentową przez wyzerowanie
bitu znakowego liczby zmiennoprzecinkowej.
'Małe liczby całkowite' muszą być traktowane oddzielnie. Większość pracy
jest współdzielona z operacją 'minusa jednoargumentowego'.
346A abs LD B,+FF B jest ustawiane na FF szesnastkowo.
JR 3474,NEG-TEST Skok do procedury 'minusa jednoargumentowego'.
OPERACJA 'MINUSA JEDNOARGUMENTOWEGO'
(Indeks 1B: 'negate')
Procedura wykonuje swoją operację jednoargumentową przez zmianę znaku
'ostatniej wartości' na stosie kalkulatora.
Zero jest po prostu zwracane bez zmian. Pełne, pięciobajtowe liczby
zmiennoprzecinkowe mają modyfikowany bit znaku tak, iż w efekcie zostaje on
zresetowany (dla 'abs') lub zmieniony
(dla 'negate'). 'Małe liczby całkowite' mają
zerowany bit znaku (dla 'abs') lub negowany
(dla 'negate').
346E NEGATE CALL 34E9,TEST-ZERO Jeśli liczba jest zerem, to procedura pozostawia je bez zmian.
RET C
LD B,+00 B jest ustawiane na +00 szesnastkowo dla'negate'.
'ABS' wchodzi tutaj.
3474 NEG-TEST LD A,(HL) Jeśli pierwszy bajt jest zerem, to
AND A wykonywany jest skok do obsługi 'małych liczb całkowitych'.
INC HL Wskaż drugi bajt.
LD A,B +FF dla 'abs', +00 dla 'negate' do A.
AND +80 Teraz +80 dla 'abs', +00 dla 'negate'.
OR (HL) To ustawia 7 w A dla 'abs', lecz nic nie zmienia dla 'negate'.
RLA Teraz bit 7 jest zmieniany, prowadząc do
CCF wyzerowania bitu 7 bajtu 2 dla 'abs'
RRA lub prostej negacji dla 'negate'.
LD (HL),A Nowy bajt 2 trafia do liczby.
DEC HL HL wskazuje ponownie pierwszy bajt.
RET Skończone.
W przypadku liczb całkowitych wykonywana jest podobna operacja na bajcie
znakowym.
3483 INT-CASE PUSH DE Zachowaj STKEND z DE.
PUSH HL Zachowaj wskaźnik liczby z HL.
CALL 2D7F,INT-FETCH Pobierz znak do C, liczbę do DE.
POP HL Odtwórz wskaźnik do liczby w HL.
LD A,B +FF dla 'abs', +00 dla 'negate' do A.
OR C Teraz +FF dla 'abs', bez zmiany dla 'negate'
CPL Teraz +00 dla 'abs' lub zanegowany bajt dla 'negate'.
LD C,A Umieszczamy go w C.
CALL 2D8E,INT-STORE Zapisz wynik na stosie.
POP DE Przywróć STKEND w DE.
RET
(Indeks 29: 'sgn')
Ta procedura obsługuje funkcję SGN X i dlatego zwraca w 'ostatniej
wartości' 1, jeśli X jest dodatnie, 0, jeśli X jest zerem i -1, jeśli X jest
ujemne.
3492 sgn CALL 34E9,TEST-ZERO Jeśli liczba X jest zerem, to po prostu wróć
RET C z zerem jako 'ostatnią wartością'.
PUSH DE Zachowaj wskaźnik do STKEND.
LD DE,+0001 W DE umieść 1.
INC HL Wskaż drugi bajt liczby X.
RL (HL) Wprowadź bit 7 do znacznika przeniesienia.
DEC HL Wskaż ponownie przeznaczenie.
SBC A,A Ustaw C na zero dla X dodatniego,
LD C,A FF szesnastkowo dla X ujemnego.
CALL 2D8E,INT-STORE Umieść na stosie odpowiednio 1 lub -1.
POP DE Odtwórz wskaźnik do STKEND.
RET Skończone.
(Indeks 2C: 'in')
Procedura obsługuje funkcję IN X. Na poziomie procesora odczytuje stan
portu X, ładując BC wartością X i wykonując instrukcję maszynową
IN A,(C).
34A5 in CALL 1E99,FIND-INT2 'Ostatnia wartość', X, jest kompresowana do BC.
IN A,(C) Pobierana jest zawartość portu X.
JR 34B0,IN-PK-STK Skocz w celu umieszczenia wyniku na stosie.
(Indeks 2B: 'peek')
Procedura obsługuje funkcję PEEK X. 'Ostatnia wartość' zostaje pobrana ze
stosu przez wywołanie FIND-INT2 i zastąpienie
jej zawartością komórki pamięci o tym adresie.
34AC peek CALL 1E99,FIND-INT2 Pobierz 'ostatnią wartość' zaokrągloną
do najbliższej liczby całkowitej; sprawdź jej zakres
i zwróć ją w parze rejestrów BC.
LD A,(BC) Pobierz bajt z tego adresu.
34B0 IN-PK-STK JP 2D28,STACK-A Wyjdź przez skok do STACK-A.
(Indeks 2D: 'usr-no')
Procedura ta ('USR liczba' w odróżnieniu od 'USR
łańcuch') obsługuje funkcję USR X, gdzie X jest liczbą. Wartość X
zostaje pobrana do BC, adres powrotny jest umieszczany na stosie i następuje
wywołanie procedury w kodzie maszynowym pod adresem X.
34B3 usr-no CALL 1E99,FIND-INT2 Pobierz 'ostatnią wartość' zaokrągloną
do najbliższej liczby całkowitej; sprawdź jej zakres
i zwróć ją w parze rejestrów BC.
LD HL,+2D2B Ustaw adres powrotu na procedurę STACK-BC.
PUSH HL
PUSH BC Wykonaj skok pośredni pod pożądany adres.
RET
Uwaga: Interesujące jest, że para rejestrów
IY zostaje ponownie
zainicjowana przy wykonaniu powrotu do STACK-BC,
lecz ważne rejestry H'L', które przechowują wskaźnik do następnego literału,
nie zostają odtworzone w przypadku zakłócenia ich zawartości. Aby powrót do
BASIC'a się powiódł, przy wyjściu z kodu maszynowego użytkownika
H'L' musi
zawierać wewnątrz procedury SCANNING adres instrukcji 'end-calc', 2758
szesnastkowo (10072 dziesiętnie).
(Indeks 19: 'usr-$')
Ta procedura obsługuje funkcję USR X$, gdzie X$ jest łańcuchem znakowym.
Procedura zwraca w BC adres wzoru bitowego grafiki zdefiniowanej przez
użytkownika, który odpowiada zawartości X$. Zgłaszany jest błąd A, jeśli X$
nie jest pojedynczym znakiem pomiędzy a i u lub grafiką zdefiniowaną przez
użytkownika.
34BC usr-$ CALL 2BF1,STK-FETCH Pobierz parametry łańcucha X$.
DEC BC Zmniejsz długość o 1, aby ją przetestować.
LD A,B Jeśli długość nie wynosi 1, to skocz
OR C do raportu błędu A.
JR NZ,34E7,REPORT-A
LD A,(DE) Pobierz kod pojedynczego znaku z łańcucha.
CALL 2C8D,ALPHA Czy jest on literą?
JR C,34D3,USR-RANGE Jeśli tak, skocz w celu pobrania jej adresu.
SUB +90 Zmniejsz zakres grafik użytkownika
do 0 - 20 dziesiętnie.
JR C,34E7,REPORT-A Błąd A, jeśli przekracza zakres.
CP +15 Jeszcze raz sprawdź zakres.
JR NC,34E7,REPORT-A Błąd A przy przekroczeniu zakresu.
INC A Przesuń zakres grafik definiowanych przez
użytkownika na 1 to 21, jako a do u.
34D3 USR-RANGE DEC A Teraz utwórz zakres 0 do 20 dla każdego przypadku.
ADD A,A Pomnóż przez 8, aby otrzymać przesunięcie adresu.
ADD A,A
ADD A,A
CP +A8 Sprawdź zakres przesunięcia.
JR NC,34E7,REPORT-A Błąd A, jeśli poza zakresem.
LD BC,(UDG) Pobierz adres pierwszej grafiki użytkownika do BC.
ADD A,C Dodaj C do przesunięcia.
LD C,A Wynik umieść z powrotem w C.
JR NC,34E4,USR-STACK Skocz, jeśli nie ma przeniesienia.
INC B Zwiększ B, aby otrzymać kompletny adres.
34E4 USR-STACK JP 2D2B,STACK-BC Skocz, aby umieścić ten adres na stosie.
Raport A - Błędny argument.
34E7 REPORT-A RST 0008,ERROR-1 Wywołaj procedurę obsługi błędów.
DEFB +09
PROCEDURA 'TESTU NA ZERO'
Ta procedura jest wywoływana przynajmniej dziewięć razy, aby sprawdzić,
czy liczba zmiennoprzecinkowa jest równa zero. Test wymaga, aby pierwsze
cztery bajty liczby były równe zero. Jeśli liczba rzeczywiście jest zerem,
to procedura wraca z ustawionym znacznikiem przeniesienia.
34E9 TEST-ZERO PUSH HL Zapamiętaj HL na stosie.
PUSH BC Zapamiętaj BC na stosie.
LD B,A Zapamiętaj wartość A w B.
LD A,(HL) Pobierz pierwszy bajt.
INC HL Wskaż na drugi bajt.
OR (HL) Wykonaj OR (alternatywa) na bitach pierwszego
i drugiego bajtu.
INC HL Wskaż na trzeci bajt.
OR (HL) Wykonaj OR wyniku i trzeciego bajtu..
INC HL Wskaż czwarty bajt.
OR (HL) OR wyniku i czwartego bajtu.
LD A,B Przywróć oryginalną wartość rejestru A.
POP BC Oraz pary rejestrów BC.
POP HL Przywróć wskaźnik liczby w HL.
RET NZ Wróć z wyzerowanym znacznikiem przeniesienia,
jeśli jeden z bajtów nie był zerem.
SCF Ustaw znacznik przeniesienia, co oznacza liczbę
równą zero
RET i wróć.
OPERACJA 'WIĘKSZE OD ZERA'
(Indeks 37: 'greater-0')
Procedura zwraca w 'ostatniej wartości' 1, jeśli bieżąca 'ostatnia
wartość' jest większa od 0, w przeciwnym razie zwraca 0. Jest również
używana przez inne procedury do 'skoku przy plusie'.
34F9 GREATER-0 CALL 34E9,TEST-ZERO Czy 'ostatnia wartość' jest zerem?
RET C Jeśli tak, wróć.
LD A,+FF Skocz naprzód do MNIEJSZE OD ZERA,
JR 3507,SIGN-TO-C lecz sygnalizuj potrzebę wykonania akcji odwrotnej.
(Indeks 30: 'not')
Procedura ta zwraca 'ostatnią wartość' równą 1, jeśli bieżąca 'ostatnia
wartość' jest zerem, w przeciwnym razie zwraca 0. Jest również używana przez
inne procedury do 'skoku przy zerze'.
3501 NOT CALL 34E9,TEST-ZERO Znacznik przeniesienia będzie ustawiony tylko wtedy,
jeśli 'ostatnia wartość' jest zerem, to daje
poprawny wynik.
JR 350B,FP-0/1 Skocz naprzód.
OPERACJA 'MNIEJSZE OD ZERA'
(Indeks 36: 'less-0')
Ta procedura zwraca 'ostatnią wartość' równą 1, jeśli bieżąca 'ostatnia
wartość' jest mniejsza od zera, w przeciwnym razie zwraca zero. Jest również
używana przez inne procedury do 'skoku przy minusie'.
3506 less-0 XOR A Wyczyść rejestr A.
3507 SIGN-TO-C INC HL Wskaż na bajt znakowy.
XOR (HL) Znacznik przeniesienia jest zerowany dla
liczby dodatniej,
DEC HL a ustawiany dla liczby ujemnej; przy wejściu
z WIĘKSZE OD 0, do
znacznika przeniesienia trafi przeciwny znak.
PROCEDURA 'ZERO LUB JEDEN'
Ta procedura ustawia 'ostatnią wartość' na 0, jeśli znacznik
przeniesienia jest wyzerowany, a na 1, jeśli jest ustawiony. Jednakże, przy
wywołaniu z 'E-TO-FP' tworzy ona 0 lub 1 nie na stosie, lecz w mem-0.
350B FP-0/1 PUSH HL Zapamiętaj wskaźnik wyniku.
LD A,+00 Wyczyść A bez niszczenia znacznika przeniesienia.
LD (HL),A Ustaw pierwszy bajt na zero.
INC HL Wskaż drugi bajt.
LD (HL),A Ustaw drugi bajt na zero.
INC HL Wskaż trzeci bajt.
RLA Wprowadź obrotem przeniesienie do A,
otrzymując w A 1, jeśli znacznik przeniesienia
był ustawiony, 0 jeśli nie był.
LD (HL),A Ustaw trzeci bajt na 1 lub 0.
RRA Upewnij się, że A ma ponownie wartość zero.
INC HL Wskaż czwarty bajt.
LD (HL),A Ustaw czwarty bajt na zero.
INC HL Wskaż piąty bajt.
LD (HL),A Ustaw piaty bajt na zero.
POP HL Przywróć wskaźnik wyniku.
RET
(Indeks 07: 'or')
Procedura ta wykonuje dwuargumentową operację 'X OR Y' i zwraca X, jeśli
Y jest zerem lub 1 w przypadku przeciwnym.
351B or EX DE,HL Ustaw HL na wskazywanie Y, drugiej liczby.
CALL 34E9,TEST-ZERO Sprawdź, czy Y jest zerem.
EX DE,HL Odtwórz wskaźniki.
RET C Wróć, jeśli Y było zerem; X jest teraz
'ostatnią wartością'.
SCF Ustaw znacznik przeniesienia i skocz w tył
JR 350B,FP-0/1 do ustawienia 'ostatniej wartości' na 1.
OPERACJA 'LICZBA AND LICZBA'
(Indeks 08: 'no-&-no')
Procedura wykonuje dwuargumentową operację 'X AND Y' i zwraca X, jeśli Y
jest różne od zera lub 0 w przypadku przeciwnym.
3524 no-&-no EX DE,HL Ustaw HL na Y, DE na X.
CALL 34E9,TEST-ZERO Sprawdź, czy Y jest zerem.
EX DE,HL Zamień z powrotem wskaźniki.
RET NC Wróć z X jako 'ostatnią wartością',
jeśli Y było różne od 0.
AND A Zeruj znacznik przeniesienia i skocz w tył
JR 350B,FP-0/1 do ustawienia 'ostatniej wartości' na 0.
OPERACJA 'ŁAŃCUCH AND LICZBA'
(Indeks 10: 'str-&-no')
Ta procedura wykonuje dwuargumentową operację 'X$ AND Y' i zwraca X$,
jeśli Y jest różne od 0 lub pusty łańcuch w przypadku przeciwnym.
352D str-&-no EX DE,HL Ustaw HL na Y, DE na X$
CALL 34E9,TEST-ZERO Sprawdź, czy Y jest zerem.
EX DE,HL Zamień ze sobą wskaźniki.
RET NC Wróć z X$ jako 'ostatnią wartością',
jeśli Y było różne od 0.
PUSH DE Zapamiętaj wskaźnik do liczby.
DEC DE Wskaż na piaty bajt parametrów łańcucha,
tj. MSB długości.
XOR A Zeruj rejestr A.
LD (DE),A Ustaw MSB długości na zero.
DEC DE Wskaż LSB.
LD (DE),A Ustaw go na zero.
POP DE Przywróć wskaźnik.
RET Wróć z parametrami łańcucha jako 'ostatnią wartością'.
(Indeksy 09 do 0E i 11 do 16: 'no-l-eql', 'no-gr-eq',
'nos-neql', 'no-grtr', 'no-less', 'nos-eql', 'str-l-eql', 'str-gr-eq',
'strs-neql', 'str-grtr', 'str-less' i 'strs-eql')
Ta procedura używana jest do wykonywania dwunastu możliwych operacji
porównań. Na początku procedury pojedynczy indeks operacji znajduje się w
rejestrze B.
353B no-l-eql LD A,B Pojedynczy indeks idzie do rejestru A.
SUB +08 Obecny zakres: 01-06 i 09-0E.
BIT 2,A Ten zakres jest zmieniany na:
JR NZ,3543,EX-OR-NOT 00-02, 04-06, 08-0A i 0C-0E.
DEC A
3543 EX-OR-NOT RRCA A dalej redukowany do 00-07 z ustawionym znacznikiem
przeniesienia dla dla 'większego lub równego'
i 'mniejszego niż'; następnie operacje z ustawionym
przeniesieniem są traktowane jako ich przeciwieństwa
po wymianie ich wartości.
JR NC,354E,NU-OR-STR
PUSH AF
PUSH HL
CALL 343C,EXCHANGE
POP DE
EX DE,HL
POP AF
354E NU-OR-STR BIT 2,A Teraz porównania liczbowe są oddzielone od porównań
JR NZ,3559,STRINGS łańcuchowych przez testowanie bitu 2.
RRCA Teraz operacje liczbowe mają zakres
00-01 z ustawionym przeniesieniem dla 'równego'
i 'różnego'.
PUSH AF Zapamiętaj indeks.
CALL 300F,SUBTRACT Liczby zostają odjęte dla końcowych testów.
JR 358C,END-TESTS
3559 STRINGS RRCA Porównania łańcuchowe mają teraz zakres
02-03 z ustawionym przeniesieniem dla 'równego'
i 'różnego'.
PUSH AF Zapamiętaj indeks.
CALL 2BF1,STK-FETCH Długość i adresy początkowe łańcuchów są pobierane
PUSH DE ze stosu kalkulatora.
PUSH BC
CALL 2BF1,STK-FETCH
POP HL Długość drugiego łańcucha.
3564 BYTE-COMP LD A,H
OR L
EX (SP),HL
LD A,B
JR NZ,3575,SEC-PLUS Skocz, jeśli drugi łańcuch nie jest pusty.
OR C
356B SECND-LOW POP BC Tutaj drugi łańcuch jest albo pusty, albo mniejszy
od pierwszego.
JR Z,3572,BOTH-NULL
POP AF
CCF Przeniesienie jest negowane, aby dać poprawny wynik.
JR 3588,STR-TEST
3572 BOTH-NULL POP AF Tutaj przeniesienie jest używane takie, jakie jest.
JR 3588,STR-TEST
3575 SEC-PLUS OR C
JR Z,3585,FRST-LESS Teraz pierwszy łańcuch jest pusty, a drugi nie.
LD A,(DE) Żaden z łańcuchów nie jest pusty, więc ich
kolejne bajty
SUB (HL) są porównywane.
JR C,3585,FRST-LESS Bajt pierwszego jest mniejszy.
JR NZ,356B,SECND-LOW Bajt drugiego jest mniejszy.
DEC BC Bajty są równe; więc
INC DE długości są zmniejszane i wykonywany jest
skok wstecz do
INC HL BYTE-COMP, aby porównać kolejne bajty
skróconych łańcuchów.
EX (SP),HL
DEC HL
JR 3564,BYTE-COMP
3585 FRST-LESS POP BC
POP AF
AND A Tutaj przeniesienie jest zerowane dla
poprawnych wyników.
3588 STR-TEST PUSH AF Dla testów łańcuchowych na stosie kalkulatora
RST 0028,FP-CALC jest umieszczane zero.
DEFB +A0,stk-zero
DEFB +38,end-calc
358C END-TESTS POP AF Te trzy testy, wywoływane w razie potrzeby,
PUSH AF dają poprawne wyniki dla wszystkich dwunastu porównań.
CALL C,3501,NOT
POP AF Początkowe przeniesienie jest ustawiane dla 'różnego'
PUSH AF i 'równego', a końcowe przeniesienie jest ustawiane
CALL NC,34F9,GREATER-0 dla 'większego niż', 'mniejszego niż' i 'równego'.
POP AF
RRCA
CALL NC,3501,NOT
RET Skończone.
OPERACJA 'ŁĄCZENIA ŁAŃCUCHÓW'
(Indeks 17: 'strs-add')
Ta procedura wykonuje dwuargumentową operację 'A$+B$'. Parametry tych
łańcuchów zostają pobrane i wyliczana jest całkowita długość. W obszarze
roboczym udostępniane jest wystarczające miejsce do pomieszczenia obu
łańcuchów, gdzie zostają one przekopiowane. Stąd wynikiem tej procedury jest
utworzenie tymczasowej zmiennej A$+B$, która znajduje się w obszarze
roboczym.
359C strs-add CALL 2BF1,STK-FETCH Parametry drugiego łańcucha zostają
PUSH DE pobrane i zapamiętane.
PUSH BC
CALL 2BF1,STK-FETCH Pobrane zostają parametry pierwszego łańcucha.
POP HL
PUSH HL Teraz długości są w HL i BC.
PUSH DE Parametry pierwszego łańcucha są zapamiętywane.
PUSH BC
ADD HL,BC Całkowita długość obu łańcuchów jest obliczana
LD B,H i przekazywana do BC.
LD C,L
RST 0030,BC-SPACES Tworzone jest wystarczające miejsce w pamięci.
CALL 2AB2,STK-STORE Parametry nowego łańcucha są przekazywane
na stos kalkulatora.
POP BC Parametry pierwszego łańcucha zostają odtworzone
POP HL ze stosu i łańcuch jest kopiowany
do obszaru roboczego
LD A,B
OR C tak długo jak nie jest pustym łańcuchem.
JR Z,35B7,OTHER-STR
LDIR
35B7 OTHER-STR POP BC Dokładnie taka sama procedura jest wykonywana
POP HL dla drugiego łańcucha, co daje w wyniku 'A$+B$'.
LD A,B
OR C
JR Z,35BF,STK-PNTRS
LDIR
Ta procedura resetuje parę rejestrów HL, tak aby wskazywała na pierwszy
bajt 'ostatniej wartości', tj. na STKEND-5, a parę rejestrów DE ustawia na
adres o jeden większy za 'ostatnią wartością', czyli STKEND.
35BF STK-PNTRS LD HL,(STKEND) Pobierz bieżącą wartość STKEND.
LD DE,+FFFB Wpisz do DE -5 jako liczbę U2.
PUSH HL Zapisz na stosie wartość STKEND.
ADD HL,DE Oblicz STKEND-5.
POP DE DE teraz zawiera STKEND and HL STKEND-5.
RET
(Indeks 2F: 'chrs')
Ta procedura obsługuje funkcję CHR$ X i tworzy jednoznakowy łańcuch w
obszarze roboczym.
35C9 chrs CALL 2DD5,FP-TO-A 'Ostatnia wartość' jest kompresowana
w rejestrze A.
JR C,35DC,REPORT-B Zgłoś błąd, jeśli X było większe
od 255 dziesiętnie
JR NZ,35DC,REPORT-B lub X było liczbą ujemną.
PUSH AF Zapamiętaj skompresowaną wartość X.
LD BC,+0001 Utwórz jedno wolne miejsce
w obszarze roboczym.
RST 0030,BC-SPACES
POP AF Pobierz wartość.
LD (DE),A Umieść ją w obszarze roboczym.
CALL 2AB2,STK-STORE Przekaż parametry nowego łańcucha
na stos kalkulatora.
EX DE,HL Resetuj wskaźniki.
RET Skończone.
RAPORT-B - Liczba całkowita poza zakresem
35DC REPORT-B RST 0008,ERROR-1 Wywołaj procedurę obsługi błędów.
DEFB +0A
(Indeksy 1D: 'val' i 18: 'val$')
Ta procedura obsługuje funkcje VAL X$ i VAL$ X$. Przy obsłudze
VAL X$,
zwraca 'ostatnią wartość' będącą wynikiem obliczenia wyrażenia numerycznego
zawartego w łańcuchu (bez obejmujących go cudzysłowów).
Przy obsłudze VAL$ X$, wyrażenie w X$ (bez ograniczających
cudzysłowów) jest traktowane jako wyrażenie łańcuchowe, które zostaje
obliczone, a jako 'ostatnia wartość' na stosie kalkulatora zostają zwrócone
parametry do łańcucha wynikowego.
35DE val LD HL,(CH-ADD) Bieżąca wartość CH-ADD zostaje
(również val$) PUSH HL przechowana na stosie maszynowym.
LD A,B 'Indeks' dla 'val' lub 'val$' musi być
w rejestrze B;
teraz zostaje skopiowany do A.
ADD A,+E3 Dla 'val' będzie +00 z ustawionym przeniesieniem;
dla 'val$' będzie +FB z wyzerowanym przeniesieniem.
SBC A,A Utwórz +FF (bit 6 ustawiony) dla 'val',
lecz +00 (bit 6 wyzerowany) dla 'val$'.
PUSH AF Zapamiętaj ten znacznik na stosie maszynowym.
CALL 2BF1,STK-FETCH Zostają pobrane parametry łańcucha;
PUSH DE adres startowy jest zapamiętywany;
INC BC długość jest zwiększana o 1 bajt
RST 0030,BC-SPACES i w przestrzeni roboczej zostaje utworzone
miejsce na łańcuch.
POP HL Adres startowy łańcucha idzie do HL
jako adres źródłowy.
LD (CH-ADD),DE Wskaźnik pierwszego nowego bajtu idzie do CH-ADD
PUSH DE oraz na stos maszynowy.
LDIR Łańcuch jest kopiowany do obszaru roboczego wraz
z dodatkowym bajtem.
EX DE,HL Wymień ze sobą wskaźniki.
DEC HL Dodatkowy bajt zostaje zastąpiony
LD (HL),+0D znakiem 'końca wiersza' (CR – powrót karetki).
RES 7,(FLAGS) Zerowany jest znacznik składni,
CALL 24FB,SCANNING a łańcuch zostaje sprawdzony pod
względem poprawności.
RST 0018,GET-CHAR Zostaje pobrany znak za łańcuchem.
CP +0D Sprawdza się, czy osiągnięto koniec wyrażenia.
JR NZ,360C,V-RPORT-C Jeśli nie, zgłaszany jest błąd.
POP HL Zostaje pobrany adres początku łańcucha.
POP AF Pobierany jest znacznik dla 'val/val$'
XOR (FLAGS) i bit 6 zostaje porównany z bitem 6 wyniku
skanowania składniowego.
AND +40
360C V-RPORT-C JP NZ,1C8A,REPORT-C Jeśli są niezgodne, zgłoś błąd.
LD (CH-ADD),HL Adres startu ponownie do CH-ADD.
SET 7,(FLAGS) Zostaje ustawiony znacznik wykonania wiersza.
CALL 24FB,SCANNING Łańcuch jest traktowany jako
'następne wyrażenie' i utworzona zostaje
'ostatnia wartość' na stosie kalkulatora.
POP HL Odtworzona zostaje oryginalna wartość CH-ADD.
LD (CH-ADD),HL
JR 35BF,STK-PNTRS Procedura wraca poprzez STK-PNTRS, gdzie
przywracane są wskaźniki.
(Indeks 2E: 'str$')
Ta procedura obsługuje funkcję STR$ X i zwraca 'ostatnią wartość' jako
zbiór parametrów definiujących łańcuch, który pojawiłby się na ekranie,
gdyby X było wyświetlone rozkazem PRINT.
361F str$ LD BC,+0001 Tworzone jest jedno miejsce w obszarze roboczym
RST 0030,BC-SPACES i jego adres jest kopiowany
LD (K-CUR),HL do K-CUR, adres kursora.
PUSH HL Ten adres jest również zapamiętywany na stosie.
LD HL,(CURCHL) Adres bieżącego kanału jest
PUSH HL zapamiętywany na stosie maszynowym.
LD A,+FF Zostaje otwarty kanał 'R', który pozwala wydrukować
CALL 1601,CHAN-OPEN łańcuch w przestrzeni roboczej.
CALL 2DE3,PRINT-FP 'Ostatnia wartość', X, zostaje teraz wydrukowana
w przestrzeni roboczej, która jest zwiększana
przy każdym znaku.
POP HL Odtwórz CURCHL w HL
CALL 1615,CHAN-FLAG i odtwórz odpowiednie znaczniki kanału.
POP DE Odtwórz adres początku łańcucha.
LD HL,(K-CUR) Teraz adres kursora wskazuje bajt tuż
za końcem łańcucha
AND A i stąd różnica jest długością.
SBC HL,DE
LD B,H Przenieś długość do BC.
LD C,L
CALL 2AB2,STK-STO-$ Przekaż parametry nowego łańcucha
na stos kalkulatora.
EX DE,HL Odtwórz wskaźniki.
RET Skończone.
Uwaga: Zobacz na PRINT-FP w celu wyjaśnienia
błędu 'PRINT "A"+STR$ 0.1'.
PROCEDURA 'ODCZYTU DANYCH'
(Indeks 1A: 'read-in')
Ta procedura jest wywoływana przez indeks kalkulatorowy w pierwszym
wierszu procedury S-INKEY$ w
SCANNING. Wydaja się, że ma ona dokonywać
odczytu danych przez różne strumienie dostępne na standardowym
Spectrum.
Podobnie jak INKEY$ procedura zwraca łańcuch znaków.
3645 read-in CALL 1E94,FIND-INT1 Parametr liczbowy jest kompresowany
w rejestrze A.
CP +10 Czy jest mniejszy od 16?
JP NC,1E9F,REPORT-B Jeśli nie, zgłoś błąd.
LD HL,(CURCHL) Adres bieżącego kanału jest zapamiętywany
PUSH HL na stosie maszynowym.
CALL 1601,CHAN-OPEN Zostaje otwarty kanał określony parametrem.
CALL 15E6,INPUT-AD Sygnał wejściowy jest przyjmowany,
jak 'kod klawisza'.
LD BC,+0000 Standardowa długość łańcucha wynikowego
wynosi zero.
JR NC,365F,R-I-STORE Skocz, jeśli nie było sygnału.
INC C Ustaw teraz długość na 2.
RST 0030,BC-SPACES Zrób miejsce w obszarze roboczym.
LD (DE),A Wstaw do niego łańcuch.
365F R-I-STORE CALL 2AB2,STK-STO-$ Przekaż parametry łańcucha
na stos kalkulatora.
POP HL Odtwórz CURCHL oraz
CALL 1615,CHAN-FLAG odpowiednie znaczniki.
JP 35BF,STK-PNTRS wyjdź, ustawiając wskaźniki.
(Indeks 1C: 'code')
Ta procedura obsługuje funkcję CODE A$ i zwraca kod Spectrum pierwszego
znaku w A$ lub zero, jeśli A$ jest pustym łańcuchem.
3669 code CALL 2BF1,STK-FETCH Pobrane zostają parametry łańcucha.
LD A,B Sprawdzana jest długość
OR C i przy zerowej rejestr A jest
JR Z,3671,STK-CODE przekazywany jako wynik zero.
LD A,(DE) Inaczej kod pierwszego znaku trafia do A.
3671 STK-CODE JP 2D28,STACK-A Procedura wychodzi poprzez STACK-A,
gdzie jest ustawiany wynik.
(Indeks 1E: 'len')
Ta procedura obsługuje funkcję LEN A$ i zwraca 'ostatnią wartość' równą
długości łańcucha.
3674 len CALL 2BF1,STK-FETCH Pobrane zostają parametry łańcucha.
JP 2D2B,STACK-BC Procedura wychodzi poprzez procedurę STACK-BC,
która ustawia wynik.
PROCEDURA 'ZMNIEJSZENIA O 1 LICZNIKA'
(Indeks 35: 'dec-jr-nz')
Tę procedurę wywołuje jedynie GENERATOR
SZEREGÓW i w rezultacie jest to operacja 'DJNZ', lecz licznikiem jest
zmienna systemowa BREG, a nie rejestr B.
367A dec-jr-nz EXX Przejdź na zapasowy zestaw rejestrów
i zapamiętaj na stosie maszynowym
PUSH HL wskaźnik do następnego literału.
LD HL,+5C67 Ustaw HL na wskazywanie BREG.
DEC (HL) Zmniejsz BREG.
POP HL Odtwórz wskaźnik następnego literału.
JR NZ,3687,JUMP-2 Przy nie-zerze wykonywany jest skok naprzód.
INC HL Wskazany zostaje następny literał.
EXX Wróć do głównego zestawu rejestrów.
RET Skończone.
(Indeks 33: 'jump')
Ta procedura wykonuje bezwarunkowy skok, jeśli zostanie wywołana przez
literał '33'. Jest również używana przez poprzednią procedurę ZMNIEJSZENIA
LICZNIKA O 1 i SKOKU PRZY NIE-ZERZE.
3686 JUMP EXX Przejdź na zapasowy zestaw rejestrów.
3687 JUMP-2 LD E,(HL) Długość skoku do następnego literału
jest wstawiana do rejestru E.
LD A,E Liczba 00 lub FF szesnastkowo
RLA jest tworzona w A w zależności od tego,
SBC A,A czy E jest dodatnie, czy ujemne,
LD D,A a następnie zostaje skopiowana do D.
ADD HL,DE Rejestry H' i L' teraz przechowują wskaźnik
następnego literału.
EXX Przywróć główny zestaw rejestrów
RET Skończone.
PROCEDURA 'SKOKU PRZY PRAWDZIE'
(Indeks 00: 'jump-true')
Ta procedura wykonuje skok warunkowy, jeśli 'ostatnia wartość' na stosie
kalkulatora, lub bardziej precyzyjnie liczba adresowana bieżąco przez parę
rejestrów DE, ma wartość logiczną true.
368F jump-true INC DE Wskaż na trzeci bajt, który jest równy zero lub 1.
INC DE
LD A,(DE) Pobierz go do rejestru A.
DEC DE Wskaż ponownie na pierwszy bajt.
DEC DE
AND A Sprawdź, czy trzeci bajt jest zerem.
JR NZ,3686,JUMP Jeśli nie, skocz.
EXX Przejdź na zapasowy zestaw rejestrów.
INC HL Przeskocz bajt długości skoku.
EXX Wróć do głównego zestawu rejestrów.
RET Skończone.
PROCEDURA 'ZAKOŃCZENIA OBLICZEŃ'
(Indeks 38: 'end-calc')
Ta procedura kończy operację RST 0028.
369B end-calc POP AF Adres powrotny do kalkulatora jest usuwany.
EXX Zamiast niego na stosie maszynowym
zostaje umieszczony adres
EX (SP),HL przechowywany w H'L' i jest wykonywany
skok pośredni
EXX pod ten adres. H'L' będzie teraz zawierało
poprzedni adres w kalkulatorowym łańcuchu adresów.
RET Skończone.
(Indeks 32: 'n-mod-m')
Procedura ta oblicza M mod N, gdzie M jest dodatnią liczbą całkowitą
przechowywaną na szczycie stosu kalkulatora jako 'ostatnia wartość', a N
jest liczbą całkowitą przechowywaną na tym stosie pod M.
Procedura zwraca jako 'ostatnią wartość' wynik z dzielenia całkowitego
N/M, a resztę z dzielenia N/M na drugim miejscu na stosie.
Procedura jest wywoływana przy obliczaniu liczby pseudolosowej do
wyznaczania N mod 65537.
36A0 n-mod-m RST 0028,FP-CALC N,M
DEFB +C0,st-mem-0 N,M mem-0 zawiera M
DEFB +02,delete N
DEFB +31,duplicate N, N
DEFB +E0,get-mem-0 N, N, M
DEFB +05,division N, N/M
DEFB +27,int N, INT (N/M)
DEFB +E0,get-mem-0 N, INT (N/M),M
DEFB +01,exchange N, M, INT (N/M)
DEFB +C0,st-mem-0 N, M, INT (N/M) mem-0 zawiera INT (N/M)
DEFB +04,multiply N, M*INT (N/M)
DEFB +03,subtract N-M*INT (N/M)
DEFB +E0,get-mem-0 N-M*INT (N/M), INT (N/M)
DEFB +38,end-calc
RET Skończone.
(Indeks 27: 'int')
Ta procedura zajmuje się funkcją INT X i zwraca 'ostatnią wartość' będącą
częścią całkowitą dostarczonej wartości. I tak INT 2.4 daje 2, lecz ponieważ
procedura zawsze zaokrągla wynik w dół, to INT -2.4 daje -3.
Procedura używa OBCINANIA W KIERUNKU ZERA
spod adresu 3214 do utworzenia I (X) takiego, że I (2.4) daje 2, a
I (-2.4)
daje -2. Stąd INT X jest równe I (X) dla wartości nieujemnych X, a
I (X)-1
dla wartości ujemnych parametru X, który sam nie jest liczbą całkowitą,
gdzie wynikiem jest wtedy oczywiście I (X).
36AF int RST 0028,FP-CALC X
DEFB +31,duplicate X, X
DEFB +36,less-0 X, (1/0)
DEFB +00,jump-true X
DEFB +04, to 36B7,X-NEG X
Dla wartości X nieujemnych nie jest wykonywany żaden skok i zostaje
znalezione I (X).
DEFB +3A,truncate I (X)
DEFB +38,end-calc
RET Skończone.
gdy X jest ujemną liczbą całkowitą, zwracane zostaje I (X), inaczej
zwracane jest I (X)-1.
36B7 X-NEG DEFB +31,duplicate X, X
DEFB +3A,truncate X, I (X)
DEFB +C0,st-mem-0 X, I (X) mem-0 przechowuje I (X)
DEFB +03,subtract X-I (X)
DEFB +E0,get-mem-0 X-I (X), I (X)
DEFB +01,exchange I (X), X-I (X)
DEFB +30,not I (X), (1/0)
DEFB +00,jump-true I (X)
DEFB +03,do 36C2,EXIT I (X)
Skok jest wykonywany dla wartości będących ujemnymi liczbami całkowitymi,
inaczej skoku nie ma i zostaje wyliczone I (X)-1.
DEFB +A1,stk-one I (X), 1
DEFB +03,subtract I (X)-1
W obu przypadkach procedura kończy się wynikiem:;
36C2 EXIT DEFB +38,end-calc I (X) lub I (X)-1
RET
(Indeks 26: 'exp')
Ta procedura obsługuje funkcję EXP X i jest pierwszą z czterech procedur
korzystających z GENERATORA SZEREGÓW w
celu otrzymania wielomianów Czebyszewa.
Przybliżenie EXP X jest znajdowane następująco:
i. X jest dzielone przez LN 2 w celu otrzymania Y, aby 2 do
potęgi Y dawało pożądany wynik.
ii. Znajdowana jest wartość N taka, że N=INT Y.
iii. Znajdowana jest wartość W taka, że W=Y-N, gdzie 0 <=W <=1, co jest
wymagane do zbieżności szeregów.
iv. Tworzony jest argument Z taki, że Z=2*W-1.
v. Użyty zostaje GENERATOR
SZEREGÓW do zwrócenia 2**W.
vi. Na koniec do wykładnika zostaje dodane N, dając 2**(N+W), co
jest równe 2**Y, a stąd jest pożądanym wynikiem dla
EXP X.
Metoda ta jest zilustrowana przy pomocy języka BASIC w
dodatku.
36C4 EXP RST 0028,FP-CALC X
Wykonaj krok i.
DEFB +3D,re-stack X
(w pełnej postaci zmiennoprzecinkowej)
DEFB +34,stk-data X, 1/LN 2
DEFB +F1,exponent+81
DEFB +38,+AA,+3B,+29
DEFB +04,multiply X/LN 2 = Y
Wykonaj krok ii.
DEFB +31,duplicate Y, Y
DEFB +27,int,1C46 Y, INT Y = N
DEFB +C3,st-mem-3 Y, N mem-3 zawiera N
Wykonaj krok iii.
DEFB +03,subtract Y-N = W
Wykonaj krok iv.
DEFB +31,duplicate W, W
DEFB +0F,addition 2*W
DEFB +A1,stk-one 2*W, 1
DEFB +03,subtract 2*W-1 = Z
Wykonaj krok v, przekazując do GENERATORA
SZEREGÓW parametr 8 i osiem wymaganych stałych.
DEFB +88,series-08 Z
1. DEFB +13,wykładnik+63
DEFB +36,(+00,+00,+00)
2. DEFB +58,wykładnik+68
DEFB +65,+66,(+00,+00)
3. DEFB +9D,wykładnik+6D
DEFB +78,+65,+40,(+00)
4. DEFB +A2,wykładnik+72
DEFB +60,+32,+C9,(+00)
5. DEFB +E7,wykładnik+77
DEFB +21,+F7,+AF,+24
6. DEFB +EB,wykładnik+7B
DEFB +2F,+B0,+B0,+14
7. DEFB +EE,wykładnik+7E
DEFB +7E,+BB,+94,+58
8. DEFB +F1,wykładnik+81
DEFB +3A,+7E,+F8,+CF
Na końcu ostatniej pętli 'ostatnia wartość' wynosi 2**W.
Wykonaj krok vi.
DEFB +E3,get-mem-3 2**W, N
DEFB +38,end-calc
CALL 2DD5,FP-TO-A Wartość bezwzględna N modulo 256
jest umieszczana w A.
JR NZ,3705,N-NEGTV Skocz naprzód, jeśli N jest ujemne.
JR C,3703,REPORT-6 Błąd, jeśli ABS N jest większe od 255.
ADD A,(HL) Teraz dodaj ABS N do wykładnika.
JR NC,370C,RESULT-OK Skocz, o ile e nie jest większe od 255.
Raport 6 - Liczba za duża
3703 REPORT-6 RST 0008,ERROR-1 Wywołaj procedurę obsługi błędów.
3705 N-NEGTV JR C,370E,RSLT-ZERO Jeśli N jest mniejsze od -255,
wynik ma być zerem.
SUB (HL) Odejmij ABS N od wykładnika,
ponieważ N było ujemne.
JR NC,370E,RSLT-ZERO Wynik zero, jeśli e mniejsze od zera.
NEG -e jest zamieniane w e.
370C RESULT-OK LD (HL),A Wykładnik e trafia do liczby.
RET Skończone: 'ostatnia wartość' to EXP X.
370E RSLT-ZERO RST 0028,FP-CALC Użyj kalkulatora, aby wprowadzić zero.
DEFB +02,delete
DEFB +A0,stk-zero
DEFB +38,end-calc
RET Skończone z EXP X = 0.
FUNKCJA 'LOGARYTM NATURALNY'
(Indeks 25: 'ln')
Ta procedura obsługuje funkcję LN X i jest drugą z czterech procedur,
które używają GENERATORA SZEREGÓW do
tworzenia wielomianów Czebyszewa.
Przybliżenie LN X jest znajdowane następująco:
i. X jest sprawdzane i zgłasza się raport błędów, jeśli X jest ujemne.
ii. X jest następnie dzielone na rzeczywisty wykładnik , e' i mantysę
X' = X/(2**e'), gdzie X' jest większe lub równe 0,5, lecz wciąż mniejsze od
1.
iii. Tworzona jest pożądana wartość Y1 lub Y2. Jeśli X' jest większe od 0,8,
to Y1=e'*LN 2, a w przypadku przeciwnym Y2 = (e'-1)*LN 2.
iv. Jeśli X' jest większe od 0,8, to zostaje zapamiętane na stosie
X'-1, inaczej 2*X'-1.
v. Teraz tworzony jest argument Z: jeśli X' jest większe od 0,8,
to Z = 2.5*X'-3; inaczej Z = 5*X'-3. W każdym przypadku zachodzi:
-1 <=Z
<=1, co jest wymagane do zbieżności szeregów.
vi. GENERATOR SZEREGÓW zostaje
użyty do utworzenia pożądanej funkcji.
vii. Na koniec proste mnożenie i dodawanie prowadzi do LN X zwracanej jako
'ostatnia wartość'.
3713 ln RST 0028,FP-CALC X
Wykonaj krok i.
DEFB +3D,re-stack X (w pełnej postaci zmiennoprzecinkowej)
DEFB +31,duplicate X, X
DEFB +37,greater-0 X, (1/0)
DEFB +00,jump-true X
DEFB +04,do 371C, VALID X
DEFB +38,end-calc X
Raport A - Zły argument
371A REPORT-A RST 0008,ERROR-1 Wywołaj procedurę obsługi błędów.
DEFB +09
Wykonaj krok ii.
371C VALID DEFB +A0,stk-zero X,0 usunięte 1 zostaje nadpisane zerem
DEFB +02,delete X
DEFB +38,end-calc X
LD A,(HL) Wykładnik, e, idzie do A.
LD (HL),+80 X jest redukowane do X'.
CALL 2D28,STACK-A Stos zawiera: X', e.
RST 0028,FP-CALC X', e
DEFB +34,stk-data X', e, 128 (dziesiętnie)
DEFB +38,wykładnik+88
DEFB +00,(+00,+00,+00)
DEFB +03,subtract X', e'
Wykonaj krok iii.
DEFB +01,exchange e', X'
DEFB +31,duplicate e', X', X'
DEFB +34,stk-data e', X', X',0.8 (dziesiętnie)
DEFB +F0,wykładnik+80
DEFB +4C,+CC,+CC,+CD
DEFB +03,subtract e', X', X'-0.8
DEFB +37,greater-0 e', X', (1/0)
DEFB +00,jump-true e', X'
DEFB +08,do 373D, GRE.8 e', X'
DEFB +01,exchange X', e'
DEFB +A1,stk-one X', e', 1
DEFB +03,subtract X', e'-1
DEFB +01,exchange e'-1, X'
DEFB +38,end-calc e'-1, X'
INC (HL) Podwój X', aby dostać 2*X'.
RST 0028,FP-CALC e'-1,2*X'
373D GRE.8 DEFB +01,exchange X',e' - X' duże.
2*X',e'-1 - X' małe.
DEFB +34,stk-data X',e',LN 2
DEFB +F0,wykładnik+80 2*X',e'-1, LN 2
DEFB +31,+72,+17,+F8
DEFB +04,multiply X',e'*LN 2 = Y1
2*X', (e'-1)*LN 2 = Y2
Wykonaj krok iv.
DEFB +01,exchange Y1, X' - X' duże.
Y2, 2*X' - X' małe.
DEFB +A2,stk-half Y1, X', .5 (dziesiętnie)
Y2, 2*X', .5
DEFB +03,subtract Y1, X'-.5
Y2, 2*X'-.5
DEFB +A2,stk-half Y1, X'-.5, .5
Y2, 2*X'-.5, .5
DEFB +03,subtract Y1, X'-1
Y2, 2*X'-1
Wykonaj krok v.
DEFB +31,duplicate Y, X'-1, X'-1
Y2, 2*X'-1, 2*X'-1
DEFB +34,stk-data Y1, X'-1, X'-1, 2.5 (dziesiętnie)
Y2, 2*X'-1, 2*X'-1, 2.5
DEFB +32,exponent+82
DEFB +20,(+00,+00,+00)
DEFB +04,multiply Y1, X'-1,2.5*X'-2.5
Y2, 2*X'-1, 5*X'-2.5
DEFB +A2,stk-half Y1, X'-1,2.5*X'-2.5, .5
Y2, 2*X'-1, 5*X'-2.5, .5
DEFB +04,subtract Y1, X'-1,2.5*X'-3 = Z
Y2, 2*X'-1, 5*X'-3 = Z
Wykonaj krok vi, przekazując do GENERATORA SZEREGÓW parametr 12 i
dwanaście wymaganych stałych.
DEFB +8C,series-0C Y1, X'-1, Z lub Y2, 2*X'-1, Z
1. DEFB +11,wykładnik+61
DEFB +AC,(+00,+00,+00)
2. DEFB +14,wykładnik+64
DEFB +09,(+00,+00,+00)
3. DEFB +56,wykładnik+66
DEFB +DA,+A5,(+00,+00)
4. DEFB +59,wykładnik+69
DEFB +30,+C5,(+00,+00)
5. DEFB +5C,wykładnik+6C
DEFB +90,+AA,(+00,+00)
6. DEFB +9E,wykładnik+6E
DEFB +70,+6F,+61,(+00)
7. DEFB +A1,wykładnik+71
DEFB +CB,+DA,+96,(+00)
8. DEFB +A4,wykładnik+74
DEFB +31,+9F,+B4,(+00)
9. DEFB +E7,wykładnik+77
DEFB +A0,+FE,+5C,+FC
10. DEFB +EA,wykładnik+7A
DEFB +1B,+43,+CA,+36
11. DEFB +ED,wykładnik+7D
DEFB +A7,+9C,+7E,+5E
12. DEFB +F0,wykładnik+80
DEFB +6E,+23,+80,+93
Przy końcu ostatniej pętli 'ostatnia wartość' wynosi:
albo LN X'/(X'-1) dla większych wartości X',
albo LN (2*X')/(2*X'-1) dla wartości mniejszych.
Wykonaj krok vii.
DEFB +04,multiply Y1=LN (2**e'), LN X'
Y2=LN (2**(e'-1)), LN (2*X')
DEFB +0F,addition LN (2**e')*X') = LN X
LN (2**(e'-1)*2*X') = LN X
DEFB +38,end-calc LN X
RET Skończone: 'ostatnia wartość' równa LN X.
PROCEDURA 'REDUKCJI ARGUMENTU'
(Indeks 39: 'get-argt')
Ta procedura przekształca argument X funkcji SIN X lub COS X w wartość V.
Procedura najpierw znajduje wartość Y taką, że:
Y = X/(2*PI) - INT (X/2*PI) + 0.5), gdzie Y jest większe lub równe -0,5,
lecz mniejsze niż +0,5.
Procedura wraca z wynikiem:
przypadek i: V = 4*Y, jeśli -1 <= 4*Y <= 1.
przypadek ii: V = 2-4*Y, jeśli 1 < 4*Y < 2.
przypadek iii: V = -4*Y-2, jeśli -2 <= 4*Y < -1.
W każdym przypadku: -1 <= V <= 1 i SIN (PI*V/2) =
SIN X
3783 get-argt RST 0028,FP-CALC X
DEFB +3D,re-stack X (w pełnej postaci zmiennoprzecinkowej)
DEFB +34,stk-data X, 1/(2*PI)
DEFB +EE,wykładnik+7E
DEFB +22,+F9,+83,+6E
DEFB +04,multiply X/(2*PI)
DEFB +31,duplicate X/(2*PI), X/(2*PI)
DEFB +A2,stk-half X/(2*PI), X/(2*PI), 0.5
DEFB +0F,addition X/(2*PI), X/(2*PI)+0.5
DEFB +27,int,1C46 X/(2*PI), INT (X/(2*PI)+0.5)
DEFB +03,subtract,174C X/(2*PI)-INT (X/(2*PI)+0.5)=Y
Uwaga: dodając 0,5 i biorąc część całkowitą, dostajemy zaokrąglenie
wyniku do najbliższej liczby całkowitej.
DEFB +31,duplicate Y, Y
DEFB +0F,addition 2*Y
DEFB +31,duplicate 2*Y, 2*Y
DEFB +0F,addition 4*Y
DEFB +31,duplicate 4*Y, 4*Y
DEFB +2A,abs 4*Y, ABS (4*Y)
DEFB +A1,stk-one 4*Y, ABS (4*Y), 1
DEFB +03,subtract 4*Y, ABS (4*Y)-1 = Z
DEFB +31,duplicate 4*Y, Z, Z
DEFB +37,greater-0 4*Y, Z, (1/0)
DEFB +C0,st-mem-0 Mem-0 przechowuje wynik testu.
DEFB +00,jump-true 4*Y, Z
DEFB +04, do 37A1,ZPLUS 4*Y, Z
DEFB +02,delete 4*Y
DEFB +38,end-calc 4*Y = V - przypadek i.
RET Skończone.
Jeśli został wykonany skok, kontynuujemy.
37A1 ZPLUS DEFB +A1,stk-one 4*Y, Z, 1
DEFB +03,subtract 4*Y, Z-1
DEFB +01,exchange Z-1,4*Y
DEFB +36,less-0 Z-1,(1/0)
DEFB +00,jump-true Z-1
DEFB +02,do 37A8,YNEG Z-1
DEFB +1B,negate 1-Z
37A8 YNEG DEFB +38,end-calc 1-Z = V - przypadek ii.
Z-1 = V - przypadek iii.
RET Skończone.
(Indeks 20: 'cos')
Ta procedura obsługuje funkcję COS X i zwraca 'ostatnią wartość' równą
przybliżeniu COS X.
Procedura korzysta z wyrażenia:
COS X = SIN (PI*W/2), gdzie -1 <= W <=1.
Przy wyprowadzaniu W dla X procedura wykorzystuje wynik otrzymany w
poprzedniej procedurze i przechowany w tym celu w mem-0. Wykonuje wtedy skok
do procedury SINE, wchodząc do niej pod adresem C-ENT, aby utworzyć jako
'ostatnią wartość' COS X.
37AA cos RST 0028,FP-CALC. X
DEFB +39,get-argt V
DEFB +2A,abs ABS V
DEFB +A1,stk-one ABS V, 1
DEFB +03,subtract ABS V-1
DEFB +E0,get-mem-0 ABS V-1, (1/0)
DEFB +00,jump-true ABS V-1
DEFB +06, do 37B7,C-ENT ABS V-1 = W
Jeśli skok nie został wykonany, to kontynuujemy.
DEFB +1B,negate 1-ABS V
DEFB +33,jump 1-ABS V
DEFB +03, do 37B7,C-ENT 1-ABS V = W
(Indeks 1F: 'sin')
Ta procedura obsługuje funkcję SIN X i jest trzecią z czterech procedur
wykorzystujących GENERATOR SZEREGÓW do
tworzenia wielomianów Czebyszewa.
Przybliżenie SIN X jest znajdowane następująco:
i. Argument X zostaje zredukowany i w tym przypadku W = V bezpośrednio.
Zwróć uwagę, że -1 <= W <= 1, co jest wymagane do zbieżności szeregu.
ii. Utworzony zostaje argument Z taki, że Z=2*W*W-1.
iii. GENERATOR SZEREGÓW jest wykorzystywany do zwrócenia (SIN (PI*W/2))/W
iv. Na koniec proste mnożenie daje SIN X.
37B5 sin RST 0028 FP-CALC X
Wykonaj krok i.
Wykonaj krok ii. Procedura od tego punktu jest wspólna dla funkcji SINUS
i COSINUS.
37B7 C-ENT DEFB +31,duplicate W, W
DEFB +31,duplicate W, W, W
DEFB +04,multiply W, W*W
DEFB +31,duplicate W, W*W, W*W
DEFB +0F,addition W, 2*W*W
DEFB +A1,stk-one W, 2*W*W, 1
DEFB +03,subtract W, 2*W*W-1 = Z
Wykonaj krok iii, przekazując do GENERATORA SZEREGÓW parametr 6 oraz
sześć potrzebnych stałych.
DEFB +86,series-06 W, Z
1. DEFB +14,wykładnik+64
DEFB +E6,(+00,+00,+00)
2. DEFB +5C,wykładnik+6C
DEFB +1F,+0B,(+00,+00)
3. DEFB +A3,wykładnik+73
DEFB +8F,+38,+EE,(+00)
4. DEFB +E9,wykładnik+79
DEFB +15,+63,+BB,+23
5. DEFB +EE,wykładnik+7E
DEFB +92,+0D,+CD,+ED
6. DEFB +F1,wykładnik+81
DEFB +23,+5D,+1B,+EA
Przy końcu ostatniej pętli 'ostatnia wartość' jest równa (SIN
(PI*W/2))/W.
Wykonaj krok v.
DEFB +04,multiply SIN (PI*W/2) = SIN X (lub = COS X)
DEFB +38,end-calc
RET Skończone: 'ostatnia wartość' = SIN X.
lub ('ostatnia wartość' = COS X)
(Indeks 21: 'tan')
Ta procedura obsługuje funkcję TAN X. Zwraca ona po prostu
SIN X/COS X z
nadmiarem arytmetycznym, jeśli COS X = 0.
37DA tan RST 0028,FP-CALC X
DEFB +31,duplicate X, X
DEFB +1F,sin X, SIN X
DEFB +01,exchange SIN X, X
DEFB +20,cos SIN X,COS X
DEFB +05,division SIN X/COS X = TAN X
Zgłoś błąd w razie potrzeby.
DEFB +38,end-calc TAN X
RET Skończone: 'ostatnia wartość' = TAN X.
(Indeks 24: 'atn')
Ta procedura obsługuje funkcję ATN X i jest ostatnią z czterech procedur
używających GENERATORA SZEREGÓW do
otrzymywania wielomianów Czebyszewa. Zwraca liczbę rzeczywistą z zakresu
pomiędzy -PI/2 a PI/2 równą wartości w radianach kata, którego tangensem
jest X.
Przybliżenie ATN X jest znajdowane następująco:
i. Wartości W i Y są znajdowane dla trzech przypadków X takich, że:
przypadek i: jeśli -1 < X < 1, to W = 0 i Y = X.
przypadek ii: jeśli -1 <= X, to W = PI/2 i
Y = -1/X.
przypadek iii: jeśli X < =- 1, to W = -PI/2 i
Y = -1/X.
W każdym przypadku jest -1 <= Y <=1, co jest wymagane do zbieżności
szeregów.
ii. Zostaje utworzony argument Z taki, że:
przypadek i: jeśli -1 < X < 1, to Z = 2*Y*Y-1 = 2*X*X-1.
przypadek ii: jeśli 1 < X, to Z = 2*Y*Y-1
= 2/(X*X)-1.
przypadek iii: jeśli X < =-1, to Z = 2*Y*Y-1
= 2/(X*X)-1.
iii. Wykorzystany zostaje GENERATOR
SZEREGÓW do wyliczenia wartości pożądanej funkcji.
iv. Na koniec proste mnożenie i dodawanie dają ATN X.
Wykonaj krok i.
37E2 atn CALL 3297,RE-STACK Użyj pełnej postaci zmiennoprzecinkowej
wartości X.
LD A,(HL) Pobierz wykładnik X.
CP +81
JR C,37F8,SMALL Skocz naprzód dla przypadku i:Y = X.
RST 0028,FP-CALC X
DEFB +A1,stk-one X, 1
DEFB +1B,negate X,-1
DEFB +01,exchange -1, X
DEFB +05,division -1/X
DEFB +31,duplicate -1/X, -1/X
DEFB +36,less-0 -1/X, (1/0)
DEFB +A3,stk-pi/2 -1/X, (1/0), PI/2
DEFB +01,exchange -1/X, PI/2, (1/0)
DEFB +00,jump-true -1/X, PI/2
DEFB +06, do 37FA,CASES Skocz naprzód dla przypadku ii:
Y = -1/X W = PI/2
DEFB +1B,negate -1/X, -PI/2
DEFB +33,jump -1/X, -PI/2
DEFB +03,to 37FA,CASES Skocz naprzód dla przypadku iii:
Y = -1/X W = -PI/2
37F8 SMALL RST 0028,FP-CALC Y
DEFB +A0,stk-zero Y, 0
Kontynuuj dla przypadku i: W = 0
Wykonaj krok ii.
37FA CASES DEFB +01,exchange W, Y
DEFB +31,duplicate W, Y, Y
DEFB +31,duplicate W, Y, Y, Y
DEFB +04,multiply W, Y, Y*Y
DEFB +31,duplicate W, Y, Y*Y, Y*Y
DEFB +0F,addition W, Y, 2*Y*Y
DEFB +A1,stk-one W, Y, 2*Y*Y, 1
DEFB +03,subtract W, Y, 2*Y*Y-1 = Z
Wykonaj krok iii, przekazując do GENERATORA SZEREGÓW parametr '12' oraz
dwanaście wymaganych stałych.
DEFB +8C,series-0C W, Y, Z
1. DEFB +10,wykładnik+60
DEFB +B2,(+00,+00,+00)
2. DEFB +13,wykładnik+63
DEFB +0E,(+00,+00,+00)
3. DEFB +55,wykładnik+65
DEFB +E4,+8D,(+00,+00)
4. DEFB +58,wykładnik+68
DEFB +39,+BC,(+00,+00)
5. DEFB +5B,wykładnik+6B
DEFB +98,+FD,(+00,+00)
6. DEFB +9E,wykładnik+6E
DEFB +00,+36,+75,(+00)
7. DEFB +A0,wykładnik+70
DEFB +DB,+E8,+B4,(+00)
8. DEFB +63,wykładnik+73
DEFB +42,+C4,(+00,+00)
9. DEFB +E6,wykładnik+76
DEFB +B5,+09,+36,+BE
10. DEFB +E9,wykładnik+79
DEFB +36,+73,+1B,+5D
11. DEFB +EC,wykładnik+7C
DEFB +D8,+DE,+63,+BE
12. DEFB +F0,wykładnik+80
DEFB +61,+A1,+B3,+0C
Na końcu otrzymujemy jako 'ostatnią wartość':
ATN X/X - przypadek i.
ATN (-1/X)/(-1/X) - przypadek ii.
ATN (-1/X)/(-1/X) - przypadek iii.
Wykonaj krok iv.
DEFB +04,multiply W, ATN X - przypadek i.
W, ATN (-1/X) - przypadek ii.
W, ATN (-1/X) - przypadek iii.
DEFB +0F,addition ATN X - teraz wszystkie przypadki.
DEFB +38,end-calc
RET Skończone: 'ostatnia wartość' = ATN X.
(Indeks 22: 'asn')
Ta procedura obsługuje funkcję ASN X i zwraca liczbę rzeczywistą w
przedziale od -PI/2 do PI/2 włącznie, która jest równa wartości kata w
radianach, dla którego sinus wynosi X. Stąd jeśli Y = ASN X,
to X = SIN Y.
Funkcja wykorzystuje równoważność trygonometryczną:
TAN (Y/2) = SIN Y/1(1+COS Y)
do otrzymania TAN (Y/2), a stąd (korzystając z
ATN)
Y/2 i ostatecznie Y.
3833 asn RST 0028,FP-CALC X
DEFB +31,duplicate X, X
DEFB +31,duplicate X, X, X
DEFB +04,multiply X, X*X
DEFB +A1,stk-one X, X*X, 1
DEFB +03,subtract X, X*X-1
DEFB +1B,negate X,1-X*X
DEFB +28,sqr X,SQR (1-X*X)
DEFB +A1,stk-one X,SQR (1-X*X), 1
DEFB +0F,addition X, 1+SQR (1-X*X)
DEFB +05,division X/(1+SQR (1-X*X)) = TAN(Y/2)
DEFB +24,atn Y/2
DEFB +31,duplicate Y/2, Y/2
DEFB +0F,addition Y = ASN X
DEFB +38,end-calc
RET Skończone: 'ostatnia wartość' = ASN X.
(Indeks 23: 'acs')
Ta procedura obsługuje funkcję ACS X i zwraca liczbę rzeczywistą od zera
do PI włącznie, która jest równa wartości kąta w radianach, dla którego
kosinus wynosi X.
Wykorzystywana jest tu relacja:
ACS X = PI/2 - ASN X
3843 acs RST 0028,FP-CALC X
DEFB +22,asn ASN X
DEFB +A3,stk-pi/2 ASN X,PI/2
DEFN +03,subtract ASN X-PI/2
DEFB +1B,negate PI/2-ASN X = ACS X
DEFB +38,end-calc
RET Skończone: 'ostatnia wartość' = ACS X.
PROCEDURA 'PIERWIASTEK KWADRATOWY'
(Indeks 28: 'sqr')
Ta procedura obsługuje funkcję SQR X i zwraca dodatni pierwiastek
kwadratowy liczby rzeczywistej X, jeśli ta jest dodatnia, a zero, jeśli
X =
0. Ujemna wartość X powoduje zgłoszenie błędu A - nieprawidłowy argument
(poprzez In w procedurze POTĘGOWANIE).
Procedura traktuje operację pierwiastka kwadratowego jako X**.5 i dlatego
umieszcza na stosie wartość 0,5, po czym przechodzi bezpośrednio do
procedury POTĘGOWANIE.
384A sqr RST 0028,FP-CALC X
DEFB +31,duplicate X,X
DEFB +30,not X,(1/0)
DEFB +00,jump-true X
DEFB +1E,do 386C,LAST X
Skok zostaje wykonany, jeśli X = 0, inaczej procedura wykonuje się dalej
z:
DEFB +A2,stk-half X,.5
DEFB +38,end-calc
A następnie znajdowany jest wynik X**.5.
(Indeks 06: 'to-power')
Procedura wykonuje dwuargumentową operację podnoszenia pierwszej liczby X
do potęgi określonej drugą liczbą Y.
Procedura traktuje wynik X**Y jako równoważność EXP (Y*LN X). Zwraca tę
wartość o ile X nie jest równe zero, w którym to przypadku zwraca 1, jeśli Y
jest również zerem (0**0=1), zwraca zero, jeśli Y
jest dodatnie lub zgłasza nadmiar arytmetyczny, jeśli Y jest ujemne.
3851 to-power RST 0028,FP-CALC X,Y
DEFB +01,exchange Y,X
DEFB +31,duplicate Y,X,X
DEFB +30,not Y,X,(1/0)
DEFB +00,jump-true Y,X
DEFB +07,do 385D,XIS0 Y,X
Skok jest wykonywany, jeśli X = 0, inaczej tworzone jest
EXP (Y*LN X).
Dając raport błędu A, jeśli X jest ujemne.
DEFB +04,multiply Y*LN X
DEFB +38,end-calc
JP 36C4,EXP Wyjdź poprzez EXP,
aby utworzyć EXP(Y*LN X).
Wartość X wynosi zero, zatem należy rozważyć trzy możliwe przypadki z tym
związane.
385D XIS0 DEFB +02,delete Y
DEFB +31,duplicate Y,Y
DEFB +30,not Y,(1/0)
DEFB +00,jump-true Y
DEFB +09,to 386A,ONE Y
Skok jest wykonywany, jeśli X = 0 i Y = 0, inaczej procedura kontynuuje
się.
DEFB +A0,stk-zero Y,0
DEFB +01,exchange 0,Y
DEFB +37,greater-0 0,(1/0)
DEFB +00,jump-true 0
DEFB +06,to 386C,LAST 0
Skok jest wykonywany, jeśli X = 0, a Y jest dodatnie, inaczej procedura
kontynuuje się.
DEFB +A1,stk-one 0,1
DEFB +01,exchange 1,0
DEFB +05,division Wyjdź poprzez 'division',
ponieważ dzielenie przez
zero daje 'nadmiar arytmetyczny'.
Wynik operacji ma być równy 1.
386A ONE DEFB +02,delete -
DEFB +A1,stk-one 1
Teraz wróć z 'ostatnią wartością' na stosie kalkulatora będącą wynikiem
0**Y.
386C LAST DEFB +38,end-calc (1/0)
RET Skończone: 'ostatnia wartość'
równa 0 lub 1.
386E - 3CFF Ten obszar jest zapasowy, przechowuje
bajty +FF.
3D00 - 3FFF Tutaj znajdują się matryce znaków. Każdy
znak posiada matrycę z 8 bajtów o kodach 00...FF. Na przykład litera 'A' posiada
matrycę o wartościach 00 3C 42 42 7E 42 42 00, co w systemie dwójkowym
wygląda następująco:
00000000
00111100
01000010
01000010
01111110
01000010
01000010
00000000