ROM 2 je prvo komercijalno raspoloživo proširenje "galaksije" koje je, ljubaznošću Zavoda za učila i nastavna sredstva, na raspolaganju i svima onima koji su svoj računar sami sastavili. Ovaj ROM je delo Voje Antonića, konstruktora "galaksije", i predstavlja logičnu nadgradnju osnovnog operativnog sistema. Ovaj ROM će "naučiti" vaš računar većini standardnih matematičkih funkcija, proširiti njegov bejzik, podržati rad sa portom za ekspanziju i štampačem koji je eventualno priključen i omogućiti "galaksiji" da, uz proširenje memorije i hardverske dodatke (emulator i EPROM programator), postane moćan sistem za razvoj softvera za druge mikroprocesorske sklopove koji koriste Z80. Za to je, jasno, posebno značajan kompletan asembler (program za rad sa mašinskim jezikom) koji je ugrađen u ROM 2. One koji planiraju da koriste asembler za razvoj mašinskih programa koji će se izvršavati na samoj "galaksiji" će posebno obradovati činjenica da je omogućeno postavljanje tačaka prekida programa ('break points') i par drugih monitorskih naredbi.
Važno je pomenuti da "galaksija" opremljena ROM-om 2 ostaje potpuno kompatibilna sa neproširenim modelima. Iako ROM 2, po inicijalizaciji, deluje na neke sistemske promenljive (posebno linkove), sve do sada objavljene informacije o dodavanju naredbi i sličnim "specijalnim efektima" ostaju u važnosti.
Kao što je ROM 2 logičan nastavak ROM-a 1, ovaj tekst je nastavak 'Uputstva za upotrebu računara "galaksija"'. On će vam omogućiti da lako koristite mogućnosti dodatka koji ste upravo kupili i, uz školu mašinca koju objavljujemo, pomoći da sastavite interesantne programe.
Suvišno je reći da je pre početka rada sa ROM-om 2 neophodno montirati čip u "galaksiju". Otvorite računar i umetnite EPROM na predviđeno mesto, pored mikroprocesora i ROM-a 1. Važno je da obratite pažnju na činjenicu da se pri programiranju na EPROM stavlja nalepnica sa nekim napisom koji, greškom, može da bude okrenut naopako. Čip treba postaviti tako da zasek na njemu bude okrenut prema zadnjoj strani "galaksije" (dalje od tastature).
Iako o inicijalizaciji ROM-a 2 još nismo govorili, jasno je da će ona biti neophodna posle svakog uključivanja računara. Posle izvesnog vremena ova inicijalizacija će vam postati toliko prirodna da je nećete ni primećivati. Ukoliko, međutim, baš ne možete da se naviknete na nju, postoji rešenje koje možete da primenite uz malo truda i hardvera: mala izmena ROM-a 1 koja će automatski inicijalizovati ROM 2 posle svakog uključenja "galaksije". Od opreme vam je potreban programator EPROM-a i uređaj za njihovo brisanje. Ukoliko vaša "galaksija" kontroliše EPROM programator, moraćete da pronađete prijatelja koji poseduje "galaksiju" ili da kupite ili pozajmite jedan prazan EPROM 2732.
Najpre otkucajte SAVE 0,&FFF i snimite na kasetu čitav sadržaj ROM-a 1. Zatim sa OLD 12288 relocirano upišite ovaj sadržaj u RAM tako da počinje od &3000 (ili od neke druge adrese na kojoj softver vašeg EPROM programatora pretpostavlja da je smešten bafer koji treba prepisati u EPROM). Slede izmene: BYTE &33F9,&C4:WORD &33FA,&1000:BYTE &37,29 (time ste, zapravo, smestili CALL &1000 na adrese &3F9-&3FB i promenili bajt &37 u koji je upisana verzija ROM-a 1. Do sada je verzija bila 28 a sada je 29.
Posle ovih izmena isprogramirajte prazan EPROM, zamenite njime ROM 1 i isprobajte računar. Ako je sve u redu, možete da izbrišete vaš bivši ROM 1, isprogramirate u njega sadržaj koji imate na traci i vratite ga u računar vašeg prijatelja. Uključite vaš računar i, dok ste u društvu, prionite na čitanje ostatka ovog uputstva.
Posle svakog uključenja računara odnosno njegove namerne (PRINT USR(0)) ili slučajne (posle neke vaše grube greške, najčešće pri radu sa asemblerom) reinicijalizacije, otkucajte A=USR(&1000) i pritisnite ENTER. Time je "galaksiji" stavljeno do znanja da je priključen ROM 2 i izvršene neophodne promene područja sistemskih promenljivih. Ukoliko zaboravite ovu inicijalizaciju neće se dogoditi ništa strašno - normalno ćete raditi sa ROM-om 1 i računar će prijaviti grešku WHAT? kada prvi put pokušate da koristite neku specifičnost ROM-a 2. U tom trenutku možete da otkucate A=USR (&1000) i "galaksija" će raditi sa drugim ROM-om kao da je on aktiviran u samom početku. Neće doći do gubitka vašeg programa ili podataka osim promenljive A. Ukoliko želite da sačuvate i nju, upotrebite A=A+0*USR(&1000).
ROM 2 ćete, dakle, inicijalizovati samo kada vam je potreban; ukoliko želite da igrate "Jumping Jack-a" nema nikakve potrebe da se zamarate iako, jasno, inicijalizacija neće imati nikakvih loših posledica.
Zagriženije "hakere" će interesovati tačan opis onoga što se dešava u toku inicijalizacije ROM-a 2. "Galaksija", pre svega, briše ekran što je neophodno za slučaj da je inicijalizacija automatska (u tom slučaju je LD A,&C RST &20 zamenjeno sa CALL &1000). Zatim se ispravlja bag koji se ispoljava kada je priključeno memorijsko proširenje od 48 Kb; nema, dakle, više potrebe da kucate WORD &2A6A,&FF00 kada god uključite računar. Posle ovoga u sistemsku promenljivu 'horizontalna pozicija slike' (&2BA8) biva upisan broj 12; pokazalo se, naime, da je na većini televizora ova promena neophodna dok broj 11 odgovara jedino profesionalnim monitorima.
Posle ovoga ispravljanja bagova, menjaju se sadržaji linkova za naredbe (JP &100F) i za video (JP &106F). Ova promena ne bi trebala da utiče na kompatibilnost propisno napisanog softvera; u najgorem slučaju neki program će isključiti ROM 2 utičući na linkove.
Na kraju inicijalizacije ROM-a 2 biva izvršeno RET i kontrola se vraća osnovnom operativnom sistemu.
Posle inicijalizacije možete da koristite sve potencijale ROM-a 2 baš kao da je on deo "galaksijinog" operativnog sistema. Naredbe se pišu i skraćuju na uobičajeni način. Možete, na primer, da otkucate DUMP &1000,10 i na ekranu će se pojaviti prvih 10*8=80 bajtova ROM-a 2. Umesto DUMP možete slobodno da otkucate DU. &1000,10 uz iste efekte.
Obzirom da "galaksija" opremljena ROM-om 2 ima više naredbi od slova abecede, nije više moguće skratiti svaku od njih na jedno slovo i tačku. Da ste, u gornjem slučaju, otkucali D. &1000,10, "galaksija" bi izvršila DOT 4096,10 sa neželjenim efektima. Pri prepoznavanju naredbi, dakle, prioritet ima tablica u ROM-u 1, sledi tablica u RAM-u (ako ste je sastavili) i, na kraju, naredbe ROM-a 2. Kompletan spisak naredbi sa primerima i neophodnim skraćenicama je dat na kraju ovoga teksta.
Da bi se olakšala upotreba češće korišćenih funkcija, neki specijalni znaci su dobili posebne uloge. Ukoliko, na primer, poželite da zabavite prste i otkucate /.,MNBV a zatim pritisnete ENTER, "galaksija" neće prijaviti WHAT? Pogodite zašto! Čestitaćemo vam ako uspete u tome ali mislimo da nećete - odgovor je na sledećih nekoliko stranica.
ROM 2 se isključuje, svako će reći, tako što se odstrani iz računara! Ovakvo isključivanje ne bismo, naravno, mogli da vam savetujemo (ukoliko je ROM 1 promenjen tako da inicijalizuje ROM 2 ovo rešenje je čak i nemoguće) pa predlažemo drugo, čisto programsko: otkucajte BYTE &2BA9,&C9:BYTE &2BAC,&C9 i pritisnite ENTER. Time je ROM 2 skoro sasvim isključen. Odakle ovo "skoro"? Ukoliko se u vašem programu nalazi naredba tipa A=USR(&1000), računar u kome se fizički ne nalazi ROM 2 će kraširati dok kompjuter sa ROM-om 2 neće pretrpeti nikakve posledice. Potpunije isključenje nije moguće.
Računar "galaksija" u osnovnoj verziji ima dobru aritmetiku pokretnog zareza koja je potpuno prilagođena njegovim karakteristikama - šest tačnih cifara je sasvim dovoljno za računar te klase. "Galaksiji", međutim, potpuno nedostaju bilo kakve matematičke funkcije što za mnoge primene, pogotovu kada se radi o srednjošolskom obrazovanju, predstavlja vrlo ozbiljan hendikep. Ovaj problem se delimično rešava dodavanjem bejzik potprograma ali je pravo rešenje tek mašinski rešen set rutina za izračunavanje matematičkih funkcija koji je uklopljen u standardni bejzik. ROM 2 nudi baš to.
Matematičke funkcije se, naravno, uvek nalaze sa desne strane znaka jednakosti ili iza PRINT naredbe. Iza svake od njih sledi argument koji može da bude konstanta ili brojni izraz; u oba slučaja argument mora da se nalazi u zagradi. Pokušajte, na primer, da otkucate PRINT SQR(4) i pritisnete ENTER. Dobićete 1.99998 - dobrodošli u svet primenjene numeričke analize!
Pre nego što bacite "galaksiju" u koš i vratite se "digitronu" koga ste davno sahranili na policu pružite nam još jednu šansu i pročitajte sledeći pasus.
Trigonometrijske, korene, logaritamske i druge funkcije nikako ne mogu da se izraze kao konačan niz sabiranja, oduzimanja, množenja i deljenja; matematičari su se vekovima mučili da ih izračunaju na ovakav način sve dok nije dokazano da je ovako nešto nemoguće. Danas koristimo kompjutere koji vrše približno izračunavanje vrednosti ovih funkcija preko beskonačnih redova. Ne biste, sigurno, poželeli da vaša "galaksija" beskonačno dugo radi da bi sabrala beskonačan red, zar ne? "Galaksija" se zato zaustavlja po sabiranju određenog broja članova reda u trenutku kada je tačnost 'zadovoljavajuća'.
Jedini je problem u tumačenju reči 'zadovoljavajući'. Isprobavajući algoritme matematičkih funkcija morali smo da pravimo kompromise između utrošenog memorijskog prostora, brzine rada i tačnosti. Smatrali smo da je "galaksiji" dovoljno 5 do 6 tačnih cifara; za većinu inžinjerskih primena dosta bi bile i dve. Problem, međutim, može da nastupi kada poželimo da dobijemo koren koji bi trebao da bude ceo - i osnovci znaju da je SQR(4) = 2 a ne 1.99998. Nema problema - upotrebićemo PRINT INT( SQR(4)+0.5). Ukoliko želimo da zaokružimo rezultat na dve decimale, koristićemo:
PRINT INT((SQR(4)*100+0.5)/100)
Upoznali smo, dakle, funkciju SQR (kvadratni koren) i njena ograničenja. Da nismo malo požurili? Ako ne želimo da već sutra zaboravimo koje funkcije naš računar ima, moraćemo da ih obradimo sistematično i to po grupama.
Svako zna kako se definiše stepenovanje kada je eksponent ceo broj: 25 je isto što i 2*2*2*2*2 = 32. Znamo li šta da radimo kada je eksponent ceo negativan broj? Ništa lakše; 2-3 je isto što i 1/(2*2*2)=1/8 = 0.125. Za neke racionalne brojeve problemi su i dalje rešivi: 20.5 je isto što i SQR(2) (kvadratni koren). Šta je, međutim, 2PI ili, još gore, PIPI?
Matematički posmatrano, ab je definisano za sve realne brojeve a i b pri čemu a mora da bude veće od nule ili eventualno jednako nuli (tada b mora biti različito od nule). To znači da PIPI može da se izračuna. Ovo računanje se najčešće obavlja primenom logaritama. O logaritmima ćemo reći par reči nešto docnije; dovoljno je da znate da vaša "galaksija" sasvim lepo ume da računa ab korišćenjem funkcije POW. POW ima dva argumenta koji se nalaze u zagradi i odvojeni su zarezom. Argumenti su, jasno, a i b pa ćete 23 izračunati tako što ćete otkucati PRINT POW(2,3) i dobiti 8 ili, da ne budemo prestrogi, bar nešto slično tome.
Posle određenog razmišljanja zaključićete da a ne mora uvek da bude negativno da bi ab bilo definisano. Jasno je, na primer, da je (-2)3 = (-2)*(-2)*(-2) = -8. "Galaksija", međutim, računa funkciju POW korišćenjem logaritama pa će PRINT POW(-2,3) rezultirati greškom. Da ostvarite celobrojno stepenovanje koje radi u svim mogućim slučajevima moraćete, dakle, da koristite običnu FOR-NEXT petlju za koju ROM 2 nije ni potreban.
Dok nekom prijatelju sa ponosom pokazujete vaš ROM 2 koji je "galaksiju" naučio matematici možete da se nađete u velikoj nevolji kada čujete pitanje "a kako se računa kubni koren iz 8?". Ne brinite, "galaksija" ume i to uz malo programerske veštine. Treba da se prisetimo prvog paragrafa ovog poglavlja u kome smo rekli da je SQR(4) isto što i 40.5 = 41/2. Slično tome je i kubni koren iz 8 jednak 81/3 a sedmi koren iz 1200: 12001/7. Znajući da argumenti u POW mogu da budu i izrazi lako ćemo napisati program poput sledećega:
5 ! RAČUNANJE N-TOG KORENA 10 PRINT "KOJI BROJ TREBA DA KORENUJEM";:INPUT A 20 PRINT "KOJI KOREN TREBA DA IZVADIM";:INPUT B 30 PRINT POW(A,1/B)
Program poput ovoga možemo da koristimo da nađemo kvadratni koren. Zašto je, onda, potrošen prostor u ROM-u za funkciju SQR? Kvadratni koren je u upotrebi mnogo češće od bilo kog drugog pa ga većina kompjutera odvojeno realizuje. Osim toga, odaćemo vam i jednu malu tajnu: "galaksija" računa SQR(X) kao POW(X,0.5)!
"Galaksija" poseduje i funkciju EXP koja je, za korisnika koji tek ulazi u svet matematike, specijalni slučaj stepenovanja. EXP(X) je, naime, isto što i eX pri čemu je e matematička konstanta barem jednako važna koliko i PI. Broj e, poput broja PI, ne može da se izrazi kao konačan decimalni broj niti kao razlomak; kažemo da se radi o 'transcedentnoj' konstanti. Prvih nekoliko cifara broja e su 2.718281828 (može li ovo nekako da se zapamti? Možda i može: u broju e se dva puta ponavlja 1828 što je godina Tolstojevog rođenja. Ako znate kada je Tolstoj rođen, znate i broj e. Ako, kao većina "hakera", znate broj e možda zaradite neki poen na času književnosti). EXP(X) je, dakle, isto što i 2.71828X.
SQR smo nekako objasnili ali kome je potrebna funkcija EXP kada već postoji POW? Odgovor će vas možda začuditi: EXP je potreban "galaksiji"; bez ove funkcije se, jednostavno, ne može realizovati POW. ex je funkcija koja se lako razvija u red i tako izračunava dok ćemo, za nekoliko trenutaka, videti da se POW(a,b) izračunava kao EXP(b*LN(a)). U međuvremenu vam ostaje da otkucate PRINT EXP(1) i tako saznate sa kolikom tačnoću vaš računar "pamti" konstantu e.
Čitaoci ovih redova, baš kao i njihov autor, verovatno pripadaju generaciji koja ne zna šta su to logaritamske tablice i koja koristi kalkulator umesto šibera. Upitajte, međutim, bilo koga ko je ranije studirao neku od tehničkih ili prirodnih nauka pa ćete saznati da su logaritamske tablice neka vrsta Biblije svakog inženjera. Pa dobro, šta su to logaritmi?
Uopšte govoreći, logaritam je funkcija koja ima dva argumenta a i b i koja se piše u obliku logb a. Obzirom da naša štamparija ponekad pravi probleme sa indeksima, unekoliko ćemo promeniti ovu konvenciju i pomenuti logaritam pisati kao log (b) a. Ovde je sa a označen broj čiji se logaritam traži a sa b takozvana "baza logaritma". Kažemo da je log (b) a = c ako je bc=a. Logaritmovanje je, dakle, operacija inverzna stepenovanju baš kao što je deljenje inverzno množenju.
Sve će postati mnogo jasnije kada pogledamo jedan primer. Već smo videli da je 23=8 što znači da je log (2) 8=3. Funkcija log može da nam posluži da nađemo eksponent (ovde 3) ako nam je data osnova (2) i rezultat (8). To samo po sebi i nije mnogo korisno ali treba upoznati još neke fascinantne osobine ove funkcije. Jeste li, na primer, znali da je log (a*b)=log a+log b? Da bismo, dakle, pomnožili dva broja treba da nađemo logaritam svakoga od njih, saberemo te vrednosti i, kako bi se to nekada reklo, "antilogaritmujemo rezultat". Znajući da se logaritmi i "antilogaritmi" lako pronalaze u tablicama i da je lakše sabirati nego množiti, vidimo da logaritmi mogu nečemu i da posluže.
Još bolju primenu su logaritmi nalazili kod stepenovanja. Treba, naime, znati da je log(ab)=b*log a pa ćemo biti u stanju da zamenimo stepenovanje realnih brojeva (čak i PIPI) množenjem koje, ako želimo da idemo do kraja, možemo zameniti sabiranjem i još jednim logaritmovanjem.
Pažljiv čitalac će primetiti da smo u zadnja dva pasusa izneverili konvenciju koju smo uveli samo trenutak ranije: umesto log (b) a pisali smo log a. Šta to može da znači i koliko, najzad, argumenata ima funkcija logaritam?
Oblik koji smo najpre napisali je strogo posmatrajući pravilniji: logaritam ima dva argumenta od kojih je jedan baza logaritma. Pokazalo se, međutim, da se u praksi koriste logaritmi sa bazama 10 (LOG ili dekadni logaritam) i e (LN ili prirodni logaritam). Računar "galaksija" poseduje samo LN kao češće korišćen logaritam.
Šta da radite ako vam nekada zatreba dekadni logaritam ili logaritam za neku drugu bazu? Nema većih problema ako zapamtite formulu log (B) A = LN(A)/LN(B) ili otkucate program poput sledećeg:
10 P."KOJI SE BROJ LOGARITMUJE"; 20 INPUT A 30 P."KOJA JE BAZA"; 40 INPUT B 50 C=LN(A)/LN(B) 60 PRINT "LOG (";B;")";A;"=";C
Ostalo je da kažemo još par reči o "antilogaritmovanju" i da izložimo jedno ograničenje matematičke prirode. EXP je funkcija inverzna LN pa bi PRINT EXP(LN(X)), za bilo koje X, trebalo da da isto to X u granicama računske greške. Ovo 'svako X' ne treba shvatiti baš bukvalno: argument funkcije LN mora da bude broj veći od nule što je posledica definicije logaritma.
Trigonometrija... Zastrašujuće zvuči a bilo bi lako preskočiti ovo poglavlje i preći na mnogo lepši naslov 'proširenja bejzika'. Ipak, obećavamo da poglavlje neće biti teško za čitanje i da ne zahteva neko posebno predznanje. Ako izdržite do kraja bićete u stanju da, na primer, sastavite program koji na ekranu crta vaš bioritam!
Trigonometrija je prilično stara geometrijska disciplina koja se bavi rešavanjem trouglova. Pod rešavanjem trouglova podrazumevamo računanje svih stranica i uglova jednog trougla kada su neki njegovi elementi poznati. Da bi trougao bio potpuno određen treba poznavati tri njegova elementa. To ne mogu da budu tri ugla (jer je, znajući da je zbir uglova u trouglu 180 stepeni, treći ugao određen čim su poznata dva) niti dve stranice i ugao naspram manje od njih (jer tada mogu da se konstruišu dva trougla koji zadovoljavaju uslove); bilo koja druga kombinacija je dobra. Pokušajte, na primer, da izračunate uglove trougla čije su stranice 10, 20 i 25 cm. Ne ide, zar ne? Videćete da se problem rešava sasvim jednostavno uz elementarno poznavanje trigonometrije.
Pokušaćemo najpre da "rešimo" pravougli trougao sa prve slike. Jedan od uglova pravouglog trougla je poznat (90 stepeni) pa ga određuju dva elementa. Ukoliko znate dve stranice, lako ćete da odredite treću znajući Pitagorinu teoremu koja, "hakerski" iskazana, glasi c=SQR(a*a+b*b). No, kako da odredite uglove trougla? Ili, kako da odredite dve stranice ako je poznata treća i jedan od uglova?
Potrebne su vam forumule:
sin A=a/c
cos A=b/c
tg A=a/b
Ovde je sa A označen ugao između stranica b i c; slovo 'alfa' bi možda bolje poslužilo ali je ovako lakše jer vaša "galaksija", kao i većina računara, nema grčka slova. Bilo kako bilo, sinus ugla je količnik dužina naspramne katete i hipotenuze, kosinus je količnik dužina nalegle katete i hipotenuze a tangens količnik dužina naspramne i nalegle katete. Setimo se malopređašnjeg problema. Neka je ugao A 20 stepeni a stranica b 10 cm. Tada je c=b/cos A i a=b*tg A. Bilo koji džepni kalkulator sa funkcijama će nam reći da je, iz ovih formula, c= 10.6418 cm i a= 3.6397 cm.
Pre nego što napišemo program koji će rešiti problem, treba da upoznamo novu jedinicu za izražavanje uglova - radijan. Izražavanje uglova u radijanima ima mnoge prednosti u odnosu na izražavanje u stepenima kada se radi o numeričkoj analizi i, posebno, rešavanju transcedentnih jednačina. Za početnika je jednostavnije da uglove izražava u stepenima jer je na njih navikao. "Galaksija" omogućava obe jedinice: ukoliko je ugao izražen u radijanima, njegov sinus ćemo računati sa X=SIN(A). Ukoliko je A u stepenima, koristićemo X=SIND(A) (D dolazi od reči degree, stepen). Na raspolaganju su nam i funkcije COS, COSD, TG i TGD. Ukoliko nam nekada zatreba da izvršimo konverziju manualno, 180 stepeni je isto što i PI radijana. "Galaksija" može da nam pomogne pri ovoj konverziji - ROM 2 dodaje pseudo promenljivu PI koja ima vrednost ove poznate konstante. Prvih desetak decimala broja PI je 3.141592654 a vi otkucajte PRINT PI da vidite kako ga "galaksija" pamti.
Sledeći program ilustruje neke osnovne trigonometrijske relacije na "galaksiji":
10 PRINT "UNESI KATETU B";:INPUT B 20 PRINT "UNESI UGAO A";:INPUT A 30 C=B/COSD(A) 40 PRINT "HIPOTENUZA JE";C 50 Z=B*TGD(A) 60 PRINT "KATETA A JE";Z 70 Y=90-A 80 PRINT "UGAO B JE";Y
Znanje koje smo stekli nam i dalje ne omogućava da rešimo svaki pravougli trougao. Ponekad ćemo, naime, iz formula koje imamo izračunati sin, cos ili tg nekog ugla i poželeti da odredimo sam taj ugao. Za to nam služe inverzne trigonometrijske funkcije arcsin, arccos i arctg (čita se 'arkus sinus', 'arkus kosinus' odnosno 'arkus tangens'). PRINT TG(ARCTG(X)), u granicama računske greške, daje X za bilo koju vrednost promenljive X.
Poput većine računara, "galaksija" od inverznih trigonometrijskih funkcija ima jedino arkus tangens. Razlog leži u tome što je jednostavno naći arkus sinus i arkus kosinus nekog ugla ako znamo njegov arkus tangens. Važi, naime:
arcsin x = arctg (x/sqr(1-x*x))
arccos x = arctg (sqr(1-x*x)/x)
Ostavljamo vam da napišete program koji bi ovo potvrdio; za kontrolu će vam poslužiti neki kalkulator ili urođeni osećaj za proporcije u trouglu.
Dva upozorenja vezana za inverzne trigonometrijske funkcije: ARCTG vraća ugao u radijanima. Ako želite rezultat u stepenima, iskoristite PRINT ARCTG(X)*180/PI. Obzirom na opšte poznatu činjenicu da je bilo koja kateta u trouglu kraća od hipotenuze, sinus i kosinus ugla su uvek manji od jedan (za tangens ovo ograničenje ne važi). Ako pokušate da simulirate arcsin x gde je x veće od 1, dobićete poruku o grešci jer će računar pokušati da nađe koren negativnog broja (1-x*x je manje od nule ako je x veće od jedan).
Došli smo, najzad, i do rešavanja bilo kog trougla. Za to nam služe sinusna (a/SIN(A) = b/SIN(B) = c/SIN(C)) i kosinusna (a*a = b*b + c*c - 2*b*c*COS (A)) teorema. Iako su relacije jednostavne, predložili bismo vam da zavirite u neki udžbenik srednjoškolske geometrije pre nego što ih primenite; ne možete, na primer, da očekujete da nađete uglove trougla čije su stranice 10, 20 i 100 cm jer takav trougao, jednostavno, ne može da postoji! Postoje mnoga ograničenja poput ovoga; ukoliko ih ne poznajete vaša "galaksija" će stalno ispisivati WHAT? i HOW? iako je program ispravan.
Uspeli smo da grupišemo matematičke funkcije u nekoliko poglavlja ali je najjednostavnija od njih ostala sasvim usamljena. ABS (X) daje, naime, apsolutnu vrednost ili modul argumenta. PRINT ABS(10.25) i PRINT ABS(-10.25) daju isti rezultat: 10.25. Dalji komentar teško da je potreban.
Bejzik interpretator koji je ugrađen u ROM 1 je pisan sa težnjom da zauzme što manje memorijskog prostora. Zbog toga su korisnici "galaksije" lišeni određenog broja standardnih naredbi i funkcija. Uložen je, međutim, maksimalan trud da se ostave one naredbe koje će omogućiti veštom programeru da sintetizuje sve bez čega je ostavljen. Dodatkom ROM-a 2 situacija se unekoliko popravlja ali su i njegova 4 kilobajta bila jedva dovoljna za asembler i brojne matematičke funkcije. Ponovo smo bili u situaciji da biramo bejzik dodatke koji će biti od najveće moguće pomoći ali pre svega onima koji žele da pišu mašinske programe.
Mašinski programi se, u odnosu na odgovarajuće bejzik rutine, sastoje od velikog broja kratkih naredbi. Obzirom da, kao što ćemo videti, svaka programska linija sme da sadrži samo jednu asemblersku instrukciju, očekujemo programe sa mnogo linija. Ukoliko poželite da obrišete veći segment ovakvog programa, naći ćete se u velikoj nevolji. Lepo je što znate da brojite od 1000 do 10000 u intervalima po 10 ali nije lepo da to znanje potvrđujete previše često! Nikakva programerska "caka", pa čak ni normalna upotreba naredbi BYTE i WORD ne može da obriše veliki segment linija. To je dovoljan razlog da u ROM-u 2 podržimo naredbu DEL (DELETE = obriši).
DEL ima dva argumenta koji se razdvajaju zarezima. DEL 1000,10000 će, na primer, obrisati sve linije između 1000 i 10000 uključujući i ove dve. Napominjemo da je DEL destruktivna funkcija - ne postoji apsolutno nikakav način da povratite linije obrisane pomoću nje. Pre nego što pritisnete ENTER treba, dakle, da dobro proverite granice i uverite se da u okviru neke od njih ne postoji višak ili manjak cifre (100 umesto 1000 će vas "zaviti u crno"!). Da bi se bar unekoliko umanjio rizik koji nosi ova naredba, "galaksija" strogo proverava njenu sintaksu: ukoliko ma koja od dve linije pomenute u DEL ne postoji biva prijavljeno HOW? bez ikakvih loših posledica po program u memoriji.
Isključivo programiranju u asembleru je namenjena naredba REN (RENUMBER = prenumeriši). U asemblerskim programima se, naime, koriste samo labele pa linijski brojevi nisu mnogo bitni. Ovi brojevi, međutim, ponekad mogu da budu i velika smetnja: pišući mašinski program često ćemo poželeti da umetnemo pedeset instrukcija između dvadesete i dvadeset pete linije!
REN 100 će nam pomoći u takvim situacijama: ova naredba vrši prenumeraciju celog programa tako da linijski brojevi budu 100, 200, 300 ... Umesto REN 100 možemo da koristimo REN 10 (linije će biti 10, 20, 30...), REN 50 (50, 100, 150...), REN 72 ili nešto slično.
Neobično je važno da razumete da REN ne sme da se koristi za prenumeraciju bejzik programa. Za ove programe su linijski brojevi veoma bitni: ukoliko je postojala naredba GOTO 125 a linija 125 posle prenumeracije dobije obeležje 500, GOTO 125 će dovesti do greške HOW? ili do potpuno pogrešnog izvršavanja programa. REN će, dakle, pretvoriti bejzik program koji dobro radi u program koji ne radi osim ako se odlučite da ručno promenite sve GOTO i CALL i neke TAKE naredbe i tako ih uskladite sa novim brojevima. Obzirom da "galaksija" nema naredbu AUTO koja bi olakšala kucanje programa sa "okruglim" linijskim brojevima, ne čini nam se da je trud utrošen na prenumeraciju dužeg programa (čak i kada on treba da bude objavljen u nekom časopisu) uopšte isplativ!
Potrudili smo se da vas na najbolji mogući način zaštitimo od slučajnog kucanja naredbe REN. Pre svega, "galaksija" interpretira R. kao RUN a RE. kao RETURN. Čak i ako otkucate REN, računar će prijaviti grešku ukoliko ne sledi propisan broj (normalno bi bilo da se, ako broj nije naveden, podrazumeva 10). Kada, međutim, otkucate REN n i pritisnete ENTER, povratka na staro nema - najbolje je, zato, da program prethodno snimite na kasetu.
Treba pomenuti još jednu "sitnicu": linijski brojevi naredbi mogu da budu najviše 32767; ukoliko upotrebite REN ne uvažavajući ovo ograničenje (REN 250 kod programa koji ima nekih 140 linija) dobićete program na čijem su kraju linije sa negativnim brojevima! U ovakvom slučaju možete da spasete program: jednostavno ponovo otkucajte naredbu REN sa nekim manjim brojem iza nje.
Čini nam se da većina vlasnika "galaksije", kada se upozna sa njenim bejzikom, koristi uputstvo za upotrebu jedino za konsultovanje tabela. Jedna od tih tabela je data na strani 18: "ASCII karakteri". Znamo da je neprijatno stalno listati knjižicu pa smo odlučili da u ROM-u 2 utrošimo nekoliko bajtova i uvedemo "konvenciju o navodnicima".
Navodnici se u bejziku koriste kao terminatori alfanumerika. Nema, zato, smisla napisati A=10+"X" jer broj i string ne smeju da se sabiraju. Ukoliko, međutim, otkucate ovakvu naredbu kada je u vašoj "galaksiji" ROM 2, neće se pojaviti nikakvo WHAT?; računar će prikazati uobičajeno READY. Kolika je vrednost promenljive A? Otkucaćemo PRINT A i dobiti 98. Stvari počinju da bivaju jasnije: ASCII kod slova X je 88 a "galaksija" mu je dodala 10.
Kada se god izračunava neki aritmetički izraz možete, umesto broja ili funkcije, iskoristiti navodnike između kojih se nalazi neki string. Funkcija će vratiti ASCII kod prvog znaka u tom stringu. Umesto da, na primer, kucate CP 88 u nekom mašinskom programu ćete napisati CP "X". Na taj ćete najpre sebi olakšati posao a zatim omogućiti nekom drugom da razume čemu ta naredba služi: vi, zapravo, ne poredite akumulator sa 88 već sa ASCII kodom slova X; zašto da to i ne naglasite?
Sličnom logikom možete da se vodite i pri pisanju bejzik programa: BYTE &29FF,"A" će ispisati na samom kraju ekrana slovo A ne izazivajući pomeranje slike (ovo iz programa ne može da se postigne ni na koji drugi način).
Problem može da nastupi ako želite jednostavno da znate ASCII kod nekog znaka. Ne smete da otkucate PRINT "X" jer ćete na ekranu dobiti obično slovo X. Jedno od rešenja je da otkucate A="X":PRINT A ali postoje i dva duhovitija:
Otkucajte PRINT 0+"X" i pritisnite ENTER. "Galaksija" će, analizirajući uneti izraz, najpre detektovati nulu kao brojni podatak. Odatle će izvesti zaključak da se ne očekuje alfanumerik i pozvati sistemski potprogram za izračunavanje vrednosti izraza. Ovaj potprogram će, jasno, znati da je 0+"X" isto što i 0+88 i prikazati na ekranu ASCII kod slova X.
Drugi način je još lakši - otkucaćemo PRINT %"X" i dobiti &0058. ASCII kod slova X je, dakle, &58 što je, kada se prevede, isto što i 88 dekadno. Dobra ili loša (zavisi kako posmatrate stvar) strana ovoga metoda je, dakle, što ASCII kod biva izražen heksadekadno. Potrebno je, ipak, da malo bolje objasnimo znak % koji smo upravo upotrebili; i on je jedna od novina koje donosi ROM 2.
PRINT &3F će, kao što znamo, dati prevod heksadekadnog broja 3F u dekadni zapis. Kada je god u nekom izrazu moguće napisati dekadni broj, možete da napišete & i neku heksadekadnu konstantu (svako pravilo ima po neki izuzetak pa tako i ovo: heksadekadna konstanta ne sme da se navodi iza NEW i OLD). Obrnuta konverzija, međutim, nije moguća na standardnoj "galaksiji". Kada radite sa mašinskim jezikom često ćete poželeti da je izvršite jer većina tabela operiše sa heksadekadnim brojevima. Zato je znak za procenat (%) rezervisan za prevođenje dekadnih brojeva u heksadekadne. Jasno je da ovaj znak može da ima smisla jedino kod PRINT naredbe.
PRINT %izraz će, dakle, izračunati <
Sa korisničke tačke gledišta "galaksija" ne operiše sa celim brojevima: sve promenljive čuvaju brojeve u takozvanom pokretnom zarezu. Za interne potrebe "galaksija", međutim, koristi cele brojeve prikazane binarno u potpunom komplementu (ukoliko vam reči "potpuni komplement" i "pokretni zarez" ništa ne znače, zanemarite ostatak ovoga pasusa). Brojevi manji od &8000 su pozitivni (bit 7 više signifikantnog bajta resetovan) a konstante veće od &8000 su negativne. Zato će PRINT MEM, ukoliko imate memorijsko proširenje od 48 Kb, dati utisak ne samo da nemate memorije već i da je nekome dugujete! Ovaj problem rešavate tako što uz ROM 2 kucate PRINT %MEM i interpretirate dobijenu heksadekadnu vrednost kao broj slobodnih bajtova ili, ako ne želite da imate posla sa heksadekadnim brojevima, PRINT MEM+65536 (odakle li je došao broj 65536? To je 2^16 ili 64 Kb). Na sličan način možete da koristite i PRINT %WORD(&xxxx) i tako izbegnete mnoge neprijatne situacije.
Često je potrebno prikazati sadržaj niza sukcesivnih memorijskih ćelija. To može da se učini uz pomoć FOR-NEXT petlje ali je takvo rešenje "sirotinjsko": sporo je i zahteva mnogo kucanja. Zato je u ROM-u 2 našla mesto naredba DUMP koja ima dva argumenta odvojena zarezom.
DUMP x,n prikazuje sadržaje memorijskih ćelija počevši od one čija je adresa x. Prikazuje se sadržaj osam ćelija u svakom redu pri čemu se na početku svakog reda nalazi adresa njegove prve ćelije. Biće prikazano n redova (n može da bude najviše 255) tj. dampovano 8*n bajtova počevši od onoga čija je adresa x. Sve konstante se prikazuju heksadekadno dok x i n mogu da budu dekadni ili (ako nekom od njih prethodi &) heksadekadni brojevi pa čak i izrazi.
Otkucajte, na primer, DUMP &1000,200 i na ekranu će biti prikazano prvih 1600 bajta ROM-a 2. Cifara će, naravno, biti previše da biste ih pratili (sa razumevanjem tih cifara ćete još malo pričekati - treba da naučite mašinski jezik) pa ćete morati da pritisnete DEL (privremeni prekid prikazivanja) ili BRK (trajni prekid i poruka READY).
Dampovanje memorije se najčešće koristi za traženje nekog dela mašinskog programa. Traženje neke naredbe u bejzik programu je daleko lakše ako pročitate sledeće poglavlje.
"Galaksija" čuva bejzik programe u memoriji na jednostavan i prirodan način - bajt po bajt. Zato nije bilo ni malo teško realizovati funkcija koja će vam pomagati pri traženju nekog teksta u bejzik programu. Ovakva funkcija je postaje apsolutna nužnost kada se pređe na asembler sa mnoštvom labela.
Želeli smo da se nova funkcija što lakše koristi pa smo za nju morali da iskoristimo neki ne-šiftovani specijalni znak. Jedini slobodan je kosa crta (/). Otkucajte, dakle, /PRINT i "galaksija" će izlistati sve programske linije u kojima se nalazi reč PRINT (ne i one u kojima je P., PR. ili nešto slično); ako ih ima previše možete da koristite DEL da usporite prikazivanje.
Pomoću / možete da tražite bilo koju programsku naredbu, ime promenljive, konstantu, komentar ili, jednostavno, bilo koji deo bejzik programa. Nije moguće tražiti jedino broj programske linije ali takvo traženje i nema smisla: ako znate broj neke linije možete da iskoristite LIST da je vidite.
ROM 2 je, rekosmo, softversko proširenje "galaksije" što znači da je bilo hardverskih i da će ih biti još više. Takva proširenja se priključuju na port za ekspanziju koji je smešten sa zadnje strane vašeg računara. Da bi takva proširenja bila na najbolji mogući način kontrolisana, ROM 2 je opremljen naredbama INP i OUT. Obzirom da smatramo da je štampač najpotrebnija periferijska jedinica koja pretvara kompjuter u nešto korisno, podržali smo rad sa njim u ROM-u. Ukoliko u ovom trenutku nemate nikakav uređaj koji biste priključili na vašu "galaksiju", ne smatrajte da je prostor u ROM-u 2 koji opisujemo bačen - vaš računar je donedavno imao i jedno prazno podnožje pa ste ga popunili ovim ROM-om; na sasvim sličan način ćete uskoro "popuniti" i port!
Mikroprocesor Z80A može da opšti sa periferijskim uređajima na dva načina: preko memorijske i input/output (ulazno/izlazne) mape. Opštenje preko memorijske mape se zasniva na tome da memorijska lokacija &FFFF, na primer, deluje na neki priključeni relej. Tada će BYTE &FFFF,1 uključiti a BYTE &FFFF,0 isključiti uređaj koji je kontrolisan relejom.
Kontrola uređaja uz pomoć memorijske mape nije uvek sjajno rešenje: šta ako imamo pun adresni prostor popunjen ROM-om i RAM-om? Zato su konstruktori mikroprocesora predvideli još jednu, I/O mapu, koja ima 256 ćelija koje nazivamo portovima. Neki periferijski uređaj može, na primer, da bude konstruisan tako da ga upis broja &FF u port nula uključuje a broja &00 u isti port isključuje. Komunikacija može da bude i dvosmerna: priključeni uređaj može da saopštava neke informacije koje će kompjuter "čitati" iz nekog drugog (ili tog istog) porta. EPROM programator, na primer, može da prima od računara sadržaj koji treba programirati ili da izveštava kompjuter o njegovom sadržaju.
Ni jednom od I/O portova ne možete da priđete naredbom BYTE ili WORD. Da biste iz bejzika pročitali sadržaj nekog porta koristićete funkciju INP a da biste upisali nešto u port - naredbu OUT.
Funkcija INP ima jedan argument koji se obavezno nalazi u zagradi - broj porta koji je između 0 i 255. PRINT INP(10) će, na primer, prikazati sadržaj desetog porta.
Naredba OUT ima dva argumenta odvojena zarezom. Prvi od njih predstavlja broj porta (0-255) a drugi sadržaj koji treba upisati u port (obzirom da svaki port predstavlja jednu memorijsku ćeliju, i ovaj sadržaj mora da bude između 0 i 255 odnosno, što je isto, 0 i &FF). OUT 100,&F0 upisuje konstantu &F0 u port čiji je broj 100. Umesto ovoga oblika mogli smo da koristimo i OUT &64,&F0 ili OUT 100,240.
Vredi napomenuti da je port broj 255 namenjen radu sa štampačem i da treba izbegavati njegove druge primene. Kada je bit 7 ulaza sa porta &FF resetovan štampač je spreman za prijem sledećeg znaka a ako je setovan, "galaksija" treba da sačeka.
Bilo koji standardni matrični štampač može da se poveže sa računarom "galaksija" preko Centronix interfejsa koji se dokupljuje ili gradi kao posebna opcija. Od tog trenutka možemo da štampamo programe, rezultate njihovog izvršavanja, segmente memorije i asemblirane rutine. Sve ovo nam omogućavaju naredbe LPRINT, LLIST i LDUMP koje dodaje ROM 2.
LPRINT je, u suštini, isto što i PRINT s tim što se sadržaj liste prikazuje na štampaču umesto na ekranu. Iza ove naredbe sledi lista koja liči na onu iza "običnog" PRINT-a osim u jednoj sitnici: iza LPRINT sme da se nalazi samo jedan element. To može da bude promenljiva, izraz, alfanumerik ili CHR$ ali nije dozvoljeno navoditi nekoliko podataka koji bi bili razdvojeni zarezom ili tačkom i zarezom. Nije, takođe, dozvoljeno korišćenje naredbe LPRINT AT. Ukoliko vam je ona neophodna, ispišite niz blankova ispred teksta koji treba štampati.
Većina štampača prihvata različite kontrolne kodove koji određuju neke njihove funkcije: tip slova, broj redova na strani, širina papira... Ovi kodovi se nalaze u uputstvu za korišćenje vašeg štampača i "galaksija" će biti srećna da ih pošalje preko LPRINT CHR$(x);. Treba obratiti pažnju na manji bag "galaksijinog" operativnog sistema koji onemogućava da se pošalje CHR$(0). Ovo je bag uobičajen za Microsoftov bejzik pa svi štampači dozvoljavaju korišćenje nekog drugog koda umesto nule sa istim efektom.
Da bi se na štampač preneo sadržaj ekrana na kome je nešto crtano primenom naredbe DOT, potrebno je posedovati printer opremljen takozvanom "blok grafikom". Kod ovakvog printera kodovi 128-192 daju blokove koji odgovaraju organizaciji "galaksijine" video memorije. Preciznija obaveštenja o ovoj organizaciji su već objavljena i biće ponovljena u okviru uputstva za upotrebu oficijelnog štampača.
Naredba LLIST omogućava prenošenje čitavog programa ili jednog njegovog dela na papir. Upotreba je jednostavna: otkucajte LLIST i pritisnite ENTER. Listanje će trajati sve dok je ENTER pritisnut; njegovo otpuštanje izaziva privremeni a pritisak na BRK trajan prekid rada štampača. Iza LLIST može da sledi broj naredbe od koje listanje treba da počne.
Naredba LDUMP je potpuno identična već opisanoj DUMP s tim što se sadržaj šalje na printer i na ekran. LDUMP 0,512 će, na primer, ispisati heksadekadni sadržaj ROM-a 1.
U podršku štampača spada, strogo gledajući, i jedna od opcija asemblera (OPT 4). Ova mogućnost će biti dokumentovana nešto docnije.
Ukoliko ste dovoljno nestrpljivi da isprobate sve pomenute naredbe bez štampača, "galaksija" će se blokirati ali će je BRK ili RESET vratiti u normalno stanje.
Set karaktera računara "galaksija" je, kao što znamo, dopunjen našim latiničnim slovima. Većina raspoloživih štampača, međutim, ima malo razumevanja za naše probleme ovoga tipa - ASCII kodovi 91-94 koji, u "galaksijinom" setu, odgovaraju našim slovima izazivaju štampanje specijalnih simbola, najčešće strelica. Listing programa koji sadrži naša slova bi, dakle, izgledao u najmanju ruku smešno!
Da bi se izbegao ovaj problem, "galaksija" umesto slova Č i Ć štampa C, umesto Ž štampa Z dok S zamenjuje Š. Ova konvencija može da bude neprijatna ukoliko nabavite štampač sa našim setom karaktera ili promenite EPROM sa štampačevim generatorom karaktera tako da vam odgovara. Ukoliko želite da isključite pomenutu pogodnost, otkucajte BYTE &2AAB,1 a ukoliko želite da je ponovo uključite - BYTE &2AAB,0.
U ROM 2 je ugrađen originalni asembler napisan uz poštovanje Zilog-ovih konvencija i određenim promenama uslovljenim specifičnostima "galaksijinog" operativnog sistema. On omogućava komforno pisanje i ispravljanje mašinskih programa uz podršku nekih "specijalnih efekata" kao što je postavljanje prekidnih tačaka u programima.
"Galaksijin" asembler je pripreman tako da se mašinski programi pišu kao deo bejzika. Time je, najpre, ušteđen prostor jer nije bilo neophodno sastavljati novi editor a zatim olakšano pisanje bejzik programa sa mašinskim potprogramima što će verovatno najviše interesovati početnike. Da bi se prevazišlo ograničenje nastalo zbog toga što, u ovakvoj implementaciji, nije moguće pisati program koji će se smeštati u svaki segment memorije (npr. programa koji će se upisivati od linka za video), omogućeno je relocirano asembliranje dopunjeno programom za relocirano snimanje koji smo dali u "Računarima 2".
Mašinske programe pišete, dakle, poput bejzik programa: svaka linija počinje brojem, sledi (neobavezna) labela iza koje mora da se nađe bar jedan blanko simbol. Zatim pišemo standardnu mnemoničku skraćenicu instrukcije a iza nje, ukoliko je potrebno, adresni deo. Adresni deo je od instrukcije odvojen bar jednim blanko simbolom. Iza instrukcije sledi (neobavezni) komentar koji počinje uzvičnikom. Dozvoljeno je postojanje linija u kojima se nalazi samo labela ili samo komentar ali ne i smeštanje većeg broja instrukcija u jednu liniju.
Evo nekoliko primera korektno napisanih linija:
100 SCF 100 LD A,(HL) 100 ! POČETAK PROGRAMA 100 CIKLUS PUSH BC 100 PROVERA 100 ! PROVERA 100 PROVERA CP "A" ! DA LI JE A?
A zatim i nekoliko nepravilnih linija:
SCF nedostaje broj 100 LDA,&10 nema blanka između LD i A 100 PRVA PROMENA blanko u labeli ili komentar bez ! 100 SCF:ADC (HL) dve instrukcije u liniji 100 EX BC,DE nepostojeća instrukcija 100 1CIKLUS ime labele ne sme da počinje cifrom
Asemblerski programi se, kako rekosmo, uklapaju u bejzik. Da bi rekli računaru kada započinje mašinski potprogram tj. kada treba da aktivira ROM 2 iskoristićemo programsku liniju na čijem se početku nalazi znak < (manje). U tu liniju nećemo više ništa upisivati tako da će u docnijem listingu biti lako uočiti mašinski potprogram. Od momenta kada smo "otvorili asembler" više ne radimo na bejziku - naredbe PRINT, STOP, IF i slične će izazvati grešku ili biti interpretirane kao labele. Na raspolaganju su nam jedino komande koje će biti opisane u daljem tekstu.
Prva naredba mašinskog segmenta treba da bude ORG (origin, početak). Iza ove naredbe stavljamo adresu (dekadnu ili, ako joj prethodi &, heksadekadnu) na koju treba da bude smešten mašinski program. ORG &3000 će, na primer, smeštati mašinski program tako da počinje od &3000 pa ćemo docnije moći da ga pozovemo sa A=USR(&3000). Treba, međutim, da pazimo gde smeštamo mašinski program!
Smeštanje na adrese 0-&1FFF (prostor koji zauzimaju ROM 1 i ROM 2) ne može da donese nikakve probleme ali ni koristi: "galaksija" pokušava da upiše nešto u ROM i u tome, na svu sreću, ne uspeva. Smeštanje programa u prostor latcha i tastature je korisno jedino ako želimo da vidimo naš računar u haosu. Područje video memorije i sistemskih promenljivih je dostupno ali opasno: video memorija se stalno menja ako zahtevamo listing programa, područje numeričkih varijabli i bafer za tastaturu su dostupni bez opasnosti dok je ostatak manje više zabranjen. Programi se obično upisuju od &2C3A ali ne treba zaboraviti da u tom slučaju bejzik treba da bude pomeren sa NEW 100, NEW 1000 ili nečim sličnim; u protivnom će rastući mašinski program "pojesti" svoj izvor sa nepredvidljivim ali uvek vrlo neprijatnim rezultatima.
Smeštanje mašinskog programa na sam kraj memorije je sasvim moguće ali uz razumevanje jednog ograničenja. "Galaksiji" je potreban prostor za smeštanje imena labela i njihovih adrese. Za ovo se koristi prostor ispod RAMTOP-a. Ukoliko ovde smeštate mašinac nastaće totalna konfuzija. Osim toga, asembliranje će svakako uništiti određen broj elemenata alfanumeričke matrice X$(I) i/ili elemenata numeričkog niza A(I).
Problem se rešava na jedan od dva načina. Pre asembliranja možete da promenite RAMTOP (sistemska promenljiva na adresi &2A6A) i tako zaštitite važne podatke ili zonu na kraju memorije u koju će mašinac biti smešten.
Drugo rešenje je relocirano upisivanje programa u memoriju. Program se asemblira tako da mu je oridžin, na primer, &3FA0 a upisuje &500 bajtova niže. Po završetku asembliranja ovaj program premeštate na pravo mesto primenom FOR-NEXT petlje ili snimate na kasetu a zatim relocirano upisujete sa OLD 1280. Pri ovakvoj egzibiciji neophodno je dobro paziti na to da ORG treba pokazuje adresu na kojoj će se program izvršavati (u našem slučaju &3FA0) dok će se relociranje postići primenom komande OPT.
Kao i ORG, OPT je opisna komanda koja ne rezultira smeštanjem nekog bajta u memoriju; ona jedino govori računaru koju od opcija asembliranja da izabere.
OPT ima dva argumenta razdvojena zarezom: OPT n,r. Prvi argument je obavezan a drugi neobavezan: moguće je, dakle, upotrebiti OPT n. Suprotno uobičajenom redu stvari, objasnićemo najpre drugi argument jer je neposredno povezan sa sadržajem prethodnog poglavlja.
Slovo r simbolizuje broj bajtova za koji treba relocirati mašinski program pri upisu u memoriju. Sekvencu:
10 < 20 ORG &2C3A 30 OPT 3,&1000 40 ! OSTATAK PROGRAMA 100 >
koristimo da asembliramo program koji će pri izvršavanju biti smešten od &2C3A ali će u toku asemblilaranja biti upisivan od &3C3A (&2C3A+&1000). Argument r može da bude i negativan (npr. OPT 3,-&100 bi upisivalo program 256 bajta pre ORG-a) uz uvažavanje "galaksijine" predstave brojeva. U granicama o kojima ćemo govoriti u sledećem poglavlju r može da bude i izraz.
Argument n je ceo broj između 0 i 7. Odredićete ga konsultujući sledeću tabelu:
n Funkcija
1 Asemblerski listing se prikazuje na ekranu 2 Rezultujući mašinski program se upisuje u memoriju 4 Asemblerski listing se ispisuje na štampaču
Ukoliko nam je, na primer, potrebno da se kod ne upisuje u memoriju i da se listing ne prikazuje na ekranu (prvo isprobavanje programa da bi se jednostavno ispravile sintaksne greške) upotrebićete OPT 0. Ukoliko vam je potrebno da se kod upiše u memoriju uz izdavanje listinga na ekranu (ovu opciju koristite u toku razvoja i testiranja programa), upotrebićete OPT 3 (3=1+2). Ukoliko ste finalizovali neki program vratićete se na OPT 2 kako korisnik ne bi bez potrebe gledao listing koji će ga možda zbunjivati. Za vašu upotrebu ćete, uz OPT 5, ispisati program na ekranu i štampaču.
Ukoliko ne navedete OPT, podrazumevaće se OPT 1. To znači da će program biti asembliran i njegov listing prikazan na ekranu zajedno sa porukama o greškama ali rezultujući kod neće biti upisan u memoriju da ne bi, usled neke greške korisnika, uništio njegov izvorni program. Za stvarnu upotrebu asemblera morate, dakle, da navedete OPT 2 ili OPT 3.
Kako se listing prikazuje? Sa leve strane ekrana vidite adresu instrukcije posmatrano apsolutno (eventualno relociranje se ovde ne prikazuje) u memoriji. Sledi nekoliko bajtova koji predstavljaju kodiranu instrukciju (već smo rekli da neke instrukcije zauzimaju jedan a neke, zajedno sa adresnim delom, čak četiri bajta). Iza toga sledi mnemonik instrukcije i eventualni komentar koji je mogao da pređe i u sledeći red. Labele su posebno istaknute tako što je ostatak mnemonika uvučen za dva mesta.
"Galaksija" će, prirodno, prijaviti greške u slučajevima kada neka vaša akcija nije bila propisna. WHAT? je standardna poruka koja će se pojaviti kada upotrebite nepostojeću instrukciju, HOW? će nastupiti ako, na primer, upotrebite JR tako da pokazuje na instrukciju koja je izvan domena relativnog skoka a SORRY ako se tabela vrednosti labela "sudari" sa bejzik programom. U svakom slučaju biva prikazana linija u kojoj je nastupila greška sa upitnikom na njenom početku. Iskoristite standardnu "galaksijinu" naredbu EDIT ili prekucajte pogrešnu liniju a zatim ponovo startujte program.
"Galaksijine" labele su reči proizvoljne dužine (sva slova su značajna tj. labela RACUN se razlikuje od labele RACUNAJ) koje počinju slovom a dalje se sastoje od slova i brojeva. Svakoj od njih se dodeljuje ceo broj uz poštovanje "galaksijinih" internih konvencija o kojima smo već dosta govorili. Rezervisane reči asemblera ne smeju da se koriste kao imena labela (ako iskoristite labelu HALT računar neće moći da je razlikuje od odgovarajuće mašinske instrukcije) ali o tome ne treba mnogo da brinete: upotrebite labelu koja vam je potrebna a računar će prijaviti grešku ako mu njeno ime ne odgovara. Primenom / ćete lako locirati sve greške i promeniti nazive.
Vrednost može da se dodeli labeli samo jednom u toku asembliranja i to isključivo na jedan od dva načina: pomoću EQU ili prostim navođenjem na početku neke linije.
Koristeći EQU dodeljujemo labeli vrednost neke konstante ili izraza. Opšti oblik je:
<labela> EQU <izraz >
na primer
START EQU &2C3A
Navodeći labelu na početku neke linije dodeljujemo joj vrednst koju će registar PC imati u trenutku kada naiđe na to mesto pri docnijem izvršavanju tog programa. U programu:
10 < 20 ORG &3000 30 OPT 3 40 SCF 50 ULAZ LD A,&10 60 ! OSTATAK PROGRAMA
labela ULAZ dobija vrednost &3001 (lokacija &3000 je popunjena kodom instrukcije SCF). Labele koje su dobile vrednost na ovaj način se najčešće koriste kod CALL i JUMP naredbi.
Asembler je opremljen potprogramima za obavljanje računskih operacija koje su potrebne pri radu sa mašinskim jezikom. Sva aritmetika je po prirodi celobrojna i nije povezana sa aritmetikom koju koristi bejzik; bejzik promenljive nisu raspoložive u asembleru kao što labele nisu raspoložive u bejziku.
Izračunavanje izraza se vrši sa leva u desno pri čemu zagrade nisu dozvoljene. U izrazu mogu ravnopravno da se koriste celobrojne konstante i imena labela. Na raspolaganju su sledeće operacije:
+ celobrojno sabiranje - celobrojno oduzimanje # logičko "i" (AND) <n šiftovanje nalevo za n mesta >n šiftovanje nadesno za n mesta
Sabiranje i oduzimanje ne zaslužuju poseban komentar. Minus može da se koristi i kao unarni operator promene znaka mada je jasno da se umesto -2 uvek može iskoristiti &FFFE. Logičko množenje (AND) se obavlja bit po bit. Da bismo upoznali njegovo dejstvo proučićemo primer:
KRAJ EQU &2C3A#&1FA0
Prikažimo najpre brojeve &2C3A i &1FA0 binarno. Dobijamo:
&2C3A = 0010 1100 0011 1010 &1FA0 = 0001 1111 1010 0000 ----------------------------- KRAJ = 0000 1100 0010 0000 =& 0 C 2 0
Labela KRAJ je, dakle, dobila vrednost &0C20. Moramo, međutim, da kažemo da se logičko množenje retko koristi za ovako "opšte" operacije - njegova glavna primena je pri takozvanom "maskiranju".
Ponekad će nam, naime, biti potrebno da izdvojimo nekoliko bitova neke vrednosti a da ostale zanemarimo. Pretpostavimo, na primer, da želimo da labela STRANA dobije vrednost adrese početka strane na kojoj se nalazi labela RADNI (svaka strana memorije ima 256 bajtova). Ukoliko, na primer, RADNI ima vrednost &2DAD, STRANA treba da dobije vrednost &2D00. Potrebno nam je, dakle, da izdvojimo osam signifikantnijih bitova labele RADNI. Za to će nam poslužiti:
STRANA EQU RADNI#&FF00
&FF00 će (napišite brojeve binarno i to proverite) zakloniti niži bajt labele RADNI (bilo koji broj logički množen sa nulom daje opet nulu) dok će &FF ostaviti viši bajt nepromenjenim.
Šiftovanje ćemo takođe upoznati na primeru:
STRANA1 EQU RADNI>8
Neka RADNI ima vrednost &2DAD kao u prethodnom primeru. Prikazan binarno ovaj broj glasi:
&2DAD = 0010 1101 1010 1101
Šiftovanjem na desno za osam bita dobijamo:
0000 0000 0010 1101 = &002D.
Kada bismo ovaj broj šiftovali levo za osam bita dobili bismo &2D00 što znači da promenljivoj STRANA vrednost možemo da dodelimo i sa:
STRANA EQU RADNI>8<8.
U izrazima može da se pojavi i znak za dolar ($) koji ima sasvim specijalnu funkciju - njime je definisana pseudo promenljiva koja ima vrednost koju će imati PC kada program, u toku izvršavanja, dođe na to mesto. Naredba LD A,($+5) će dovesti u akumulator sadržaj pet bajta udaljene memorijske lokacije. $, dakle, donekle odgovara naredbi PTR bez adresnog dela u bejziku.
Već smo rekli da se u okviru asemblerskog programa ne sme nalaziti PRINT, IF ili neka druga bejzik konstrukcija. Asembler, međutim, omogućava umetanje nekih naredbi koje Z80 ne bi razumeo. Dve takve smo već upoznali: ORG i OPT. Preostale tri su BYTE, WORD i TEXT (sličnost sa bejzikom je namerna).
Ponekad nam je potrebno da u nekom segmentu mašinskog programa umetnemo neki bajt ili par bajtova koji neće predstavljati kodove neke instrukcije. Potrebno nam je, na primer, da definišemo internu promenljivu SPACE koju ćemo koristiti za privremeno smeštanje sadržaja nekog šesnaestobitnog registra. Na kraju mašinskog programa ćemo, posle poslednjeg RET-a, dodati:
1570 SPACE WORD &2C3A
Time smo definsali dva bajta kojima možemo da se obraćamo sa LD HL,(SPACE), LD (SPACE),DE ili nekom sličnom naredbom. Početna vrednost promenljive SPACE je &2C3A ali treba obratiti pažnju da će ona ovu vrednost imati samo pri prvom startovanju programa; za docnija startovanja ćemo sami morati da je postavimo.
BYTE, WORD i TEXT se, dakle, koriste za definisanja bajta, reči ili niza bajtova u toku asembliranja. Sledeći jednostavan program će vam pomoći da shvatite upotrebu ovih naredbi.
10 < 20 ORG &3000 30 OPT 3 40 DFILE EQU &2800 50 LD A,&C 60 RST &20 ! SISTEMSKI POZIV ZA BRISANJE EKRANA 70 LD HL,PORUKA 80 LD DE,DFILE+231 :! KAO PRINT AT 231 90 LD BC,KRAJ-PORUKA 100 LDIR 110 RET ! POVRATAK U BEJZIK 120 PORUKA BYTE """ 130 TEXT "GALAKSIJA" 140 BYTE """ 150 TEXT " 8 K ROM" 160 KRAJ 170 > 180 A=USR(&3000)
Otkucajte i izvršite program pa će se na sredini ekrana pojaviti tekst "GALAKSIJA" 8 K ROM. Primetite da je pojava navodnika u poruci omogućena dvema naredbama BYTE u kojima je korišćena konvencija o navodnicima i to na pomalo čudan ali za računar sasvim prihvatljiv način.
Iza poslednje asemblerske naredbe, kao što smo videli u prethodnom primeru, mogu da slede definicije i početne vrednosti nekih promenljivih, poruke i tabele. Iza poslednje od njih treba dodati programsku liniju u kojoj se nalazi jedino znak > (veće). Znacima < i > je, dakle, uokviren mašinski deo programa. Kada "galaksija" naiđe na >, kontrola se vraća bejzik interpretatoru dok se oridžin i vrednosti svih labela trajno "zaboravljaju" (ove vrednosti se, istina, i ne brišu tako da bi vešt programer mogao da iskoristi neku od njih).
Iza kraja asemblera može, kao u prethodnom primeru, da se nađe poziv upravo asembliranog programa. Umesto toga, početnici će verovatno radije započinjati osnovni bejzik program koji će docnije i po potrebi pozivati asemblirane potprograme. Kada završite razvoj čitavog programa sačuvajte izvorni oblik a zatim, pomoću DEL, obrišite čitav asemblerski deo. Mašinske potprograme pripremite tako da se nalaze ispred bejzika a zatim snimite samo ono što je neophodno za izvršavanje programa. Ne samo da će na taj način i oni koji nemaju ROM 2 moći da koriste vaš program već će on zauzimati manje memorije pa će se brže učitavati sa kasete.
U toku razvoja mašinski potprogram neće, jasno, proraditi "iz prve". Moraćete, dakle, da radite na njegovim ispravkama i modifikacijama. U takvim slučajevima biće vam neophodno da "zavirite" u sadržaj registara i flegova u nekoj fazi izvršavanja programa. Za to vam služi naredba REG.
Postavite REG u neki mašinski program i izvršite ga. Kada mikroprocesor naiđe na REG prikazaće izveštaj koji se sastoji od sledećih elemenata:
AF BC DE HL IX SP AF' BC' DE' HL' IY (SP)
Vidimo, dakle, sadržaje osnovnih i alternativnih registara, oba indeks registra, vrednost stek pointera i poslednji broj koji je stavljen na stek. Računar čeka da pritisnemo bilo koji taster (osim BRK, DEL i LIST) da bi nastavio izvršavanje našeg mašinskog programa.
Iza REG možemo da napišemo dva argumenta razdvojena zarezom. U tom slučaju ćemo dobiti i damp segmenta memorije koji nas interesuje. Brojevi iza REG predstavljaju početnu adresu bloka i broj redova koje treba prikazati - baš kao kod naredbi DUMP i LDUMP.
NAREDBE I FUNKCIJE ROM-a 2
Naredba Skraćenica Primer
" A="Z" % PRINT %(&2C3A+517) / /LABELA < početak mašinskog programa > kraj mašinskog programa ABS PRINT SQR(ABS(A)) PRINT ABS(100) ARCTG AR. PRINT ARCTG(PI/4) COS A=COS(PI/3) PRINT COSD(30) DEL DEL 100,200 DUMP DU. DUMP &1000,212 EXP PRINT EXP(1) INP X=INP(10) LDUMP LD. LDUMP 0,10 LLIST LL. LLIST LLIST 1000 LN PRINT 20*LN(2.367) LPRINT LP. LPRINT "GALAKSIJA" OUT OUT 10,&FF PI PRINT PI POW PRINT POW (8,1/3) REN REN 100 SIN PRINT SIN(2*PI/3) PRINT SIND(60) SQR PRINT SQR(2) TG A=TG(PI/2) PRINT TGD(45)
Sistemske adrese ROM-a 2
Ovaj dodatak nije namenjen početnicima; u njemu, uz minimum teksta i podrazumevajući značajno predznanje, navodimo informacije koje će vam pomoći da u potpunosti iskoristite vaš ROM 2.
U sledećoj tabeli je data mapa sistemskih promenljivih "galaksijinog" operativnog sistema, bejzik interpretatora i ROM-a 2. Tabela je u mnogome slična onoj koja je objavljena na strani 26. Uputstva za upotrebu vašeg računara. Pažljiviji čitalac će, međutim, primetiti da su ispravljene dve nebitne greške i dodate nove sistemske promenljive koje koristi ROM 2. Prostor "ispod" bejzika je, dakle, sada potpuno popunjen!
Adresa | Bajta | Inicijalno | Sadržaj |
2800 | 512 | 20 | Video memorija |
2A00 | 104 | 00 | Numeričke varijable A-Z |
2A68 | 2 | 2800 | Pozicija kurzora u memoriji |
2A6A | 2 | 3800 | Kraj memorije |
2A6C | 2 | 00 | Broj HOME zaštićenih bajta video memorije |
2A6E | 2 | 00 | Izlazni kriterijum za FOR-NEXT |
2A70 | 16 | 00 | X$ |
2A80 | 16 | 00 | Y$ |
2A91 | 2 | 00 | Stek za tekuću petlju |
2A93 | 2 | 00 | Pozicija tekuće linije (za vreme FOR-NEXT) |
2A95 | 2 | 00 | Basic pointer (za vreme CALL i FOR-NEXT) |
2A97 | 2 | 00 | Lokacija od koje treba DUMP-ovati |
2A99 | 2 | 00 | 16*ARR$+16 |
2A9B | 2 | 00 | Adresa NEXT varijable |
2A9D | 2 | 2C3C | TAKE pointer |
2A9F | 2 | 00 | Pozicija tekuće linije |
2AA1 | 2 | 00 | Registar za aktivni FOR-NEXT |
2AA3 | 2 | 00 | Privremeni SP, tokom CALL-a |
2AA5 | 2 | 00 | Diferencijator za tastaturu |
2AA7 | 3 | 00 | Seed za RND |
2AAA | 1 | 00 | Koji prolaz kroz asembler (1 ili 2) |
2AAC | 1 | 00 | ČĆŠŽ postaju CCSZ kod štampe za bit7=0 |
2AAC | 124 | 00 | Aritmetički akumulatori (IX) |
2BA8 | 1 | 0C | Horizontalna pozicija teksta |
2BA9 | 3 | C9 | Link za naredbe |
2BAC | 3 | C9 | Link za video |
2BAF | 1 | 00 | Ako je bit 7=1, sat radi |
2BB0 | 1 | 00 | Brojač za pomeranje slike |
2BB1 | 1 | 00 | Flag za pomeranje slike |
2BB2 | 1 | 00 | Koliko redova treba DUMP-ovati |
2BB3 | 1 | 00 | OPT pri asembliranju |
2BB4 | 1 | 00 | Registar za REPT |
2BB5 | 1 | 00 | Flag za štampač |
2BB6 | 125 | 00 | Bafer |
2C36 | 2 | 2C3A | Pointer početka basic-a |
2C38 | 2 | 2C3A | Pointer kraja basic-a |
2C3A | ?? | 00 | Program |
U trenutku kada asembler završi posao, sve labele bivaju zaboravljene. Ponekad, međutim, može da bude korisno da bejzik program odredi gde se nalazi neki mašinski potprogram označen labelom.
Asembler upisuje labele počevši od kraja memorije. Najpre je upisano ime prve labele kao niz ASCII karaktera od kojih je poslednjem setovan sedmi bit. Iza (tačnije ispred jer se sve upisuje od viših adresa prema početku memorije) imena slede dva bajta koja predstavljaju broj dodeljen labeli. Iza toga, bez ikakvog posebnog terminatora, sledi sledeća labela, zatim sledeća... Kraj tabele označen je nula-bajtom.
U sledećoj tabeli su date ulazne adrese važnih potprograma operativnog sistema i ROM-a 2. Razlike u odnosu na tabelu objavljenu u "Računarima u vašoj kući broj 2" se svode na dodavanje ulaznih adresa matematičkih funkcija. Kod svih trigonometrijskih funkcija i kod POW po pozivu potprograma čija je ulazna adresa data DE treba da pokazuje ASCII string u memoriji koji predstavlja argument u zagradi. Za ostale funkcije argument treba da se nađe na aritmetičkom steku.
Opis | CALL & |
Izraz adresiran sa DE - HL | 008 |
Izraz u zagradi adresiran sa DE - HL | A6A |
HL na aritmetički stek | ABC |
Četiri bajta adresirana sa HL na aritmetički stek | A45 |
Izraz adresiran sa DE na aritmetički stek | AB2 |
Broj sa aritmetičkog steka u HL | A6D |
Broj sa aritmetičkog steka u četiri bajta adresirana sa HL | 73B |
Stanje aritmetičkog steka | 8F6 |
Element izraza adresiran sa DE - HL | 18D7 |
Izraz u zagradi adresiran sa DE - (IX) | 781 |
Ceo izraz u HL | 1866 |
Poređenje elemenata sa aritmetičkog steka (Z,C) | B10 |
RND na aritmetički stek | C8F |
Ako je (DE) zarez, kao RST &8 inače prijavljuje WHAT? | 5 |
Preskoči blankove | 104 |
Lociraj varijablu čije ime pokazuje DE. PTR u HL, uz C i Z | 125 |
KEY(0) | CF5 |
Karakter A na ekran | 20 |
HL na ekran kao ASCII niz | 8FB |
Alfanumerik adresiran sa DE na ekran | 937 |
Obrada sledeće naredbe | 30 |
Slobodna memorija ARR$-RAMTOP u HL | 183 |
Pokaži sadržaj svih registara na ekranu | 1978 |
DUMP od HL za A redova | 19DE |
Link za naredbe | 100F |
Link za video | 106F |
+ | B32 |
- | B1E |
* | AE6 |
/ | AF7 |
ABS | 1BFC |
SQR | 1D09 |
POW | 1CDA |
EXP | 1D1B |
LN | 1B6B |
SIN | 1C30 |
COS | 1C24 |
TAN | 1C04 |
ARCTG | 1D81 |