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 |
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). |
(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. |
(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ę. |
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 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. |
(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. |
(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 |
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. |
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. |
(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. |
(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. |
(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. |
(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'. |
(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 |
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óć. |
(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. |
(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ż uzywana 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. |
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. |
(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. |
(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. |
(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'.
(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. |
(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. |
(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. |
(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. |
(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. |
(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.
DEFB +39,get-argt W |
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. |
(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).
DEFB +25,ln 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. 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 |
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.