Računari 2

Galaksija bez tajni *

Uputstvo za upotrebu računara "galaksija" koje smo objavili kao podlistak specijalnog izdanja "Računari u vašoj kući" bilo je namenjeno prevashodno početnicima. Osim njih, "galaksiju" su napravili i mnogi koji su "prevazišli bejzik" i poželeli da pišu i mašinske programe. Njima, osim korisne mape sistemskih promenljlvih, uputstvo nije pružalo ništa, nismo mogli da damo čak ni adrese korisnih rutina u ROM-u jednostavno zašto što one nisu bile fiksirane kada je uputstvo pisano. Za njih smo ovoga puta pripremili obilje programskih finesa za napredno programiranje računara "galaksija".

Dejan Ristanović

Čim je razvoj ROM-a završen, ponudili smo svima zainteresovanima njegov disasemblirani listing (GALA005052 u "Katalogu programa"). On je praktično trenutno postao bestseler, ali smo ipak bili svesni da svi oni koji su ga naručili neće moći da izvuku mnogo koristi od njega. Da biste razumeli operativni sistem i bejzik interpretator jednog računara (čak i ako, kao u našem slučaju, taj program ima samo 4 Kb), morate da poznajete mašinski jezik izuzetno dobro i uložite mnogo rada, strpljenja i, što je najvažnije, dosta vremena. Zato smo odlučili da vam u "Računarima 2" omogućimo da pođete prečicom: izdvojili smo sistemske adrese koje su nam se činile najkorisnijim, obradili kompletnu aritmetiku pokretnog zareza, proučili za vas korišćenje linkova za naredbe, video i (do sada nedokumentovanog) linka u interaptu i sve to sumirali u sledećih nekoliko strana. Obzirom da je sada pisanje mašinskih programa za "galaksiju" postalo moguće na jedan od tri načina (o njima nešto docnije), nadamo se da će podaci koje dajemo biti iskorišćeni na najbolji mogući način: za pisanje sistemskih i uslužnih programa i, naravno, efektnih igara.

PTR

Dvadeset šesto poglavlje Uputstva za upotrebu računara "galaksija" bilo je posvećeno naredbi PTR. Ona, da podsetimo, daje memorijsku adresu neke numeričke ili alfanumeričke promenljive (PRINT PTR X$, na primer, daje rezultat 10864, što je isto što i &2A70 prema mapi sistemskih promenljivih). No naredba PTR može da se koristi i bez adresnog dela, npr. A=PTR ili PRINT PTR (poslednja modifikacija "galaksijinog" ROM-a pred njegovo "zaključivanje" 3. januara 84.) U tom slučaju, naredba PTR daje memorijsku adresu na kojoj je sama smeštena. Šta će nam to? Ako se u memoriji nalazi iole duži bejzik program, nije ni malo jednostavno pronaći neko određeno slovo u njemu da bisno ga, pomoću BYTE. promenili. Ako pre toga slova stavimo jednostavno PRINT PTR i izvršimo program, direktno ćemo dobiti traženu poziciju (ne treba zaboraviti da će se ta adresa smanjiti za 9 bajtova ako izbrišemo naredbu PRINT PTR koja, računajući i blanko simbol, ima isto toliko slova).

Navedimo jedan primer upotrebe naredbe PTR. Dok lista program, računar "galaksija" ne očekuje da naiđe na linijski broj 0. Ukoliko ipak naiđe na njega, računar smatra da je listanje završeno i vraća se u komandni mod prikazavši READY. Kako da kreiramo linijski broj 0? Ako želimo da prva naredba programa ima taj broj, ništa lakše: otkucaćemo WORD WORD(&2C36), 0, pa će "galaksija" listati samo prvu liniju programa u kojoj može da piše ime njegovog autora ili, možda, A = USR(&2C3A) što bi stvorilo utisak da je program pisan na mašinskom jeziku, No. šta ako želimo da se listanje programa prekine posle neke druge linije? U prethodnu liniju ćemo. na samom njenom kraju, dodati naredbu PRINT PTR, a zatim je i izvršiti. Dobićemo adresu prvog bajta iza slova R (od PTR). To je bajt &D koji označava kraj programske linije. Iza njega, kao što ćemo videti, stoji linijski broj sledeće naredbe koji možemo da promenimo u 0 primenom naredbe WORD. Ne treba da zaboravimo da obrišemo PRINT PTR naredbu koja je obavila svoju funkciju. Ukoliko bismo ovu naredbu obrisali pre nego što promenimo linijski broj sledeće, morali bismo ponovo da preračunavamo adrese jer se sadržaj memorije pomerio.

Naredbu PTR ćete mnogo više koristiti (opisani metod je prilično "opasan" jer "galaksijin" sistem traženja linijskih brojeva kod GOTO i CALL naredbi očekuje da ovi brojevi rastu) za pisanje programa koji menjaju samog sebe. Jedan od takvih je i "Telefonski imenik", ilustracija Interfejsa 1, koji je objavljen u martovskoj "Galaksiji". Ako se odlučite na sličnu "avanturu", vodite računa da adresa početka i kraja bejzik programa mora stalno da bude smeštena u sistemske promenljive &2C36 i &2C38. Odstupanje od ovoga može da ima neprijatne posledice po GOTO naredbe i, posebno, ispravke pojedinih linija.

TAKE

Devetnaesto poglavlje Uputstva govori o naredbi TAKE koja je mnogim vlasnicima drugih računara poznata pod imenom READ. Radi uštede prostora u ROM-u, u bejziku uobičajena naredba RESTORE je zastupljena samo kao poseban slučaj TAKE. Ovoj mogućnosti smo do sada posvetili samo jedan pasus, propuštajući da spomenemo jedan interesantan trik koji je zamišljen još kada je TAKE koncipirana. Ako se iza TAKE nalazi neki broj n (npr. TAKE A,B,100,C), "galaksija" će potražiti liniju sa tim brojem i postaviti pointer naredbe TAKE na njen početak. Ukoliko se u toj naredbi nalazi # (DATA) LISTA, sledeće TAKE će uzeti podatak iz nje. Ukoliko se u naredbi uopšte ne nalazi lista, računar će potražiti sledeću naredbu, zatim sledeću...

Ovakva struktura naredbe TAKE je prilično fleksibilna i omogućava uštedu RAM-a: sve se dešava u istoj listi. Na prvi pogled, međutim, koncepcija ima veliku manu: simulacija naredbe RESTORE N, gde je N promenljiva a ne konstanta, nije moguća! Zaista, ako otkucamo TAKE A, računar neće potražiti listu u liniji čiji je broj smešten u A, već će promenljivoj A dodeliti vrednost iz prve sledeće liste. Šta da se radi? Mogli bismo, naravno, da smestimo N u sistemsku promenljivu čija je adresa &2A9D. ali je takvo rešenje "hleb sa sedam kora": u ovu sistemsku promenljivu se ne smešta broj linije već adresa njenog početka posmatrano apsolutno u memoriji. Ovu adresu možemo da odredimo pomoću PTR, ali moramo da je menjamo svaki put kada pravimo ispravke u programu, što nije baš mnogo prijatno. Zato je bolje primeniti ovaj trik: kada "galaksija" razmatra naredbu TAKE, bejzik interpretator koristi potprogram koji određuje da li je sledeći element numerik. Ako jeste, biva pozvan potprogram koji izračunava vrednost izraza (ako je taj izraz običan broj, vrednost koja se vraća iz potprograma je sam taj broj, naravno) a zatim se on preračunava u vrednost koju treba smestiti u sistemsku promenljivu. A šta ako umesto TAKE A napišemo TAKE 0+A? Nula plus A je, kao što znamo iz osnovne škole, isto što i A, ali za "galaksiju" to ne važi u svakoj konstelaciji događaja. Pri analizi naredbe računar nailazi na broj nula koji prepoznaje kao numerik, podrazumevajući da se radi o simularnoj naredbi RESTORE. Potprogram koji izračunava vrednost izraza, međutim, nije tako lako prevariti i on će svakako razumett da je 0+A isto što i A. pa ćemo dobiti naredbu RESTORE A!

KEY

Odmah iza naredbe TAKE govorili smo o naredbi KEY uz odgovarajuću tabelu u kojoj su se nalazila dva provokativna prazna mesta pa su se mnogi verovatno zapitali šta znači KEY(49) i KEY(51). Pripremajući tabelu, imali smo puno razloga da izostavimo pomenuta dva koda jer u bejziku mogu samo da izazovu zabunu, ali ćemo sada govoriti o njima pošto mogu da budu od velikog značaja pri pisanju mašinskih programa.

KEY(49) testira taster BRK, a KEY(51) taster DEL. BRK nema mnogo smisla testirati jer pritisak na njega prekida izvršavanje programa (otkucajte 10 PRINT KEY (49): GOTO 10 i startujte program pokušavajući da pritisnete BRK samo na kratko, toliko kratko da ga KEY registruje, ali da se program ne prekine. Nije lako ali je moguće!

Testiranje DEL je još beznadežniji slučaj: pritisak na njega prekida izvršavanje programa i taj prekid traje sve dok korisnik ne otpusti DEL. U mašinskom programu, međutim, svakom od ovih tastera možete da dodelite proizvoljnu funkciju ukoliko ne koristite potprogram za testiranje tastature iz ROM-a. U mašinskim programima, štaviše, mogu da se testiraju i pritisci na SHIFT BRK (npr. u "Zamku" i Jumping Jack-u, programima koji su emitovani preko "Ventilatora", ova kombinacija se koristi za prekidanje igre i novi start) i slične "nemoguće" kombinacije.

Naredba KEY(0) koristi potprograme za rad sa tastaturom iz ROM-a, što znači da se javljaju isti problemi (sasvim očekivani, uzgred rečeno) sa testiranjem BRK i DEL, ali i jedna nova zagonetka: ako slučano pritisnemo STOP/LIST dok se izvršava KEY (0), poćeće listanje programa i, samim tim, prestati njegovo izvršavanje. Dalje ispitivanje bi nas uverilo da sličan artefakt postoji i kod naredbe INPUT. Ništa ozbiljno, ali o tome treba voditi računa u toku pisanja bejzik programa.

INPUT

Kada smo već kod naredbe INPUT. potrebno je da odgovorimo na jedno često postavljano pitanje: ako koristimo naredbu INPUT X$, tekst koji kucamo ne mora da bude pod navodnicima. Kada su. zapravo, navodnici obavezni? Najpre u # listama (što se vidi i iz spiska naredbi sa primerima iz uputstva za upotrebu), a zatim i u naredbama za dodeljivanje koje bi mogle da izazovu zabunu. Možemo, dakle, da napišemo X$=GALAKSIJA, ali ako u X$ želimo da smestimo slova Y i $, moraćemo da iskoristimo X$ = "Y$" jer X$ = Y$ ima drugi smisao! Kod "numeričkog INPUT-a" imamo puno pravo da otkucamo neki aritmetički izraz umesto obične konstante; "galaksija" će ga izračunati i dodeliti promenljivoj koja je navedena u INPUT-u. U tekstu koji kucamo mogu da se koriste i promenljive i funkcije, ali tako da sintaksa bude ispravna; u protivnom, "galaksija" će ispisati WHAT? ili HOW? (zavisno od prirode greške) i prestati sa radom. U toku INPUT-a, dakle, biva izvršena i naredba VAL.

VAL

Naredba VAL je neobično moćna i treba je koristiti kad god je to moguće. Potreban nam je, na primer, program koji pretvara heksadekadne brojeve u dekadne. Možemo, naravno, da izdvajamo slovo po slovo iz promenljive X$, pretvaramo ga u broj i primenjujemo uobičajeni algoritam množenja sa 16, ali postoji i daleko jednostavniji način: otkucaćemo:

10 INPUT X$
20 Y$ = "&" + X$
30 PRINT VAL(PTR Y$)

i... to je sve. Ako u odgovoru na INPUT otkucamo 2A0, promenljiva Y$ će dobiti vrednost &2A0 a na ekranu će biti štampan broj 522, prevod 2A0 u dekadni sistem. Ako pišete program koji će vam omogućiti da unosite mašinski program dat kao "hex-dump" u memoriju. program poput ovog će vam uštedeti čitavu trećinu kucanja podataka!

Postoji još mnogo načina da lukavo iskoristite potprograme operativnog sistema bez potrebe da se pozabavite mašinskim jezikom. Za pripremanje pomenutih heks-dampova koji bi bili pogodni za listanje i objavljivanje u "Galaksiji", bilo je neophodno da sastavimo program koji će dati mašinski program pretvarati u naredbe. Za to je bilo potrebno pretvarati numerike dobijene pomoću BYTE u ASCII vrednosti i od njih kreirati # liste (program koji samoga sebe menja). Za ostvarivanje toga poslužili smo se malim trikom: obrišemo ekran sa HOME, štampamo vrednost koju treba pretvoriti u ASCII karaktere a zatim iz same video memorije (od &2801, pošto se na &2800 nalazi znak koji je za vrednosti koje su nam potrebne (do 255) uvek blanko jer su brojevi pozitivni) čitamo jednu po jednu cifru običnim BYTE!

Korišćenje rutina operativnog sistema, naravno, nosi sa sobom i određene opasnosti da će nas računar "pogrešno shvatiti". Svi oni koji su napisali više mašinskih programa počeli su da "misle heksadekadno", tj. da koriste heksadekadni sistem za predstavljanje svih programerskih problema. Za njih će, dakle, biti sasvim prirodno da umesto NEW 1024 otkucaju NEW &400 rezervišući kilobajt za mašinski i program koji će biti smešten neposredno ispred bejzika. Računar "galaksija" ih, na žalost, neće razumeti! Iza NEW i OLD se, naime, mora nalaziti numerik, a ne izraz. NEW &400 će biti shvaćeno kao obično NEW i računar, da stvar bude gora, neće to prijaviti ni na kakav način. Docnije može da dođe do mešanja bejzika i mašinskog programa sa katastrofalnim posledicama po oba. Ako. dakle, koristimo neku opciju koja nije do-kumentovana. moraćemo najpre da proverimo njeno dejstvo.

Minsko polje

Skijaše-početnike uče da se zaustave pre nego što nauče da krenu niz padinu, pa ćemo i mi. pre nego što počnemo ,da govorimo o mašinskim programima, izložiti koje memorijske zone i sistemske registre treba po svaku cenu čuvati ili, bar. vratiti u prvobitno stanje.

Postoje dve vrste mašinskih programa: jedni se koriste iz bejzika kao potprogrami. što znači da. posle njihovog izvršavanja, "galaksija" treba da se vrati u bejzik. Da bi se takva kooperacija ostvarila, potrebno je, očigledno, dobro čuvati sve ono što je interpretatorov radni prostor. Postoje, sa druge strane, i mašinski programi sasvim nezavisni od bejzika i ROM-a koji, na primer, predstavljaju interpretatore drugih programskih jezika ili (mnogo verovatnije) kompletne igre. Reklo bi se da ovi programi ne moraju ništa da čuvaju i da mogu proizvoljno da se prostiru u memoriju. No, odmah ćemo videti da nije baš tako.

Treba, pre svega, da razumemo da računar ne izvršava naš program sve vreme. Svake pedesetinke sekunde procesor prekida rad na našem programu i pomaže video-stepenu da generiše sliku na ekranu monitora. Ovu rečenicu pišemo već po ko zna koji put ali za to imamo mnogo razloga: iz ličnog iskustva nam je poznato da je vrlo teško naći grešku koja je nastala kao posledica interapta koji programer često potpuno zaboravlja jer se dešava van njegovog uticaja. Da bi računar korektno izvršio interapt, nužno je da ni po koju cenu ne menjamo sadržaj procesorškog IY registra; Ukoliko to učinimo (pa makar se restauirali samo nekoliko naredbi docnije), rizikujemo da računar posle interapta počne da izvršava program na nekom drugom mestu u RAM-u pa ćemo, pogotovu ako je prostor sistemskih promenljivih poremećen, izazvati siguran krah praćen reinicijalizacijom računara i gubitkom programa.

Ma koliko se trudili da naš program bude nezavistan od bejzika, za njegovo testiranje će biti korisno da se ipak oslonimo na njega. Nema toga ko će napisati sistemski program tako da proradi "iz prve". Ukoliko se program razvija na "galaksiji", posle svake probe ćemo izgubiti program ukoliko ne obezbedirno mogućnost da bejzik interpretator preuzme kontrolu. Čak i ako program razvijemo na nekom drugom računaru, poželećemo da koristimo potprograme iz ROM-a koji zahtevaju određene predostrožnosti.

Stek mora da vam bude "najveća svetinja". Ukotiko vaš program ima, u nekoj grani, više naredbi PUSH nego naredbi POP, povratak u bejzik će biti nemoguć, jer RET nalazi adresu za povratak na vrha steka. Isto tako, ako se stek stalno puni, računar će se garantovano "ugušiti" posle izvesnog vremena. Simptomi ove greške su programi koji jedno vreme ispravno rade. a onda nastupa "krah" praćen brisanjem čitave memorije.

Dakle, svaka operacija sa stekom, a naročito direktna izmena registra SP. treba da bude plod pažljivog planiranja (ovim, naravno, nikako ne želimo da kažemo da ne treba koristiti stek - bez njega se ne pišu ni najkraći, programi) koje će imati za cilj da sve bude vraćeno u prvobitno stanje. Vodite računa o tome da poziv potprograma iz koga se ne vraćamo dodaje dva broja na stek. Kao i svako pravilo, i ovo ima izuzetaka: ako se ne vraćate u bejzik pomoću RTN već pomoću JP &66, ne morate previše da brinete o steku: posle ovog skoka "galaksija" ispisuje READY i reinicijafiztije registar SP (u programerskom žargonu ova adresa se zove "farma", pa bi zagrrženiji hakeri prethodnu rečenicu izgovorili kao "ne brini o steku ako računar posle ide na farmu".

Osim steka adresiranog registrom SP, "galaksija" ima još jedan stek adresiran registrom IX - aritmetički stek čiju ćemo strukturu izložiti kada budemo govorili o aritmetici u pokretnom zarezu. Ovaj stek. ukratko, sadrži argumente aritmetičkih operacija i ne treba ga previste remetiti. Ponekad će nam, naravno, zatrebati registar IX (pošto IY i tako ne smemo da koristimo) pa ćemo ga najpre sačuvati (sa PUSH IX), onda koristiti i najzad vratiti u početno stanje (POP IX).

Sistemske promenljive

Što se područja sistemskih promenljivih tiče, ne treba menjati poziciju kurzora u memoriji tako da se on nade van područja A2800-&2A00, poziciju kraja memorije (osim ako ugrađujemo proširenje memorije), bejzik pointer, poziciju tekuće linije, linkove za naredbe i video (osim na sasvim specijalan način, o kome ćemo govoriti nešto docnije) i pointere početka i kraja bejzika. Promena drugih sistemskih promenljivih ne može da ima katastrofalne posledice. ali može da izazove male neprijatnosti (ako, na primer. promenite sadržaj sistemske promenljive &2BA8, slika će se pomeriti što ćete lako ispraviti).

Ne bismo želei i da pomislite da je najbolje ne dirati sistemske promenljive: pisanje mašinskih programa, pogotovu ako se radi o rutinama sistemske prirode, ne može ni da se zamisli bez intervencija u ovom bloku memorije. Hoćemo samo da vas upozorimo da svaka promena neke od sistemskih promenljivih mora da bude rezultat ražu-mevanja njene funkcije i situacija kada se ta funkcija ostvaruje.

Pažljiv pogled na tabelu sistemskih promenljivih otkriva da u njemu ima neiskorišćenog prostora - bajtovi &2A97, &2A98, &2AAA i &2A90 nisu korišćeni. pa bi mogli lepo da se iskoriste za smeštaj nekih podataka koji su našem programu potrebni. Da li je pametno koristiti ih? Nismo sigurni u to - računar "galaksija" će biti i dalje proširivan, pa je sasvim moguće da će neka od varijanti ROM-a II iskoristiti prazan sistemski prostor. U tom slučaju moraćete da prerađujete vaše programe kako bi ostali kompatibilni i sa proširenjima računara. Teško da će vaš program biti baš toliko dugačak da mu zafale tačno četiri bajta, pa vam savetujemo da prostor za podatke potražite na nekom drugom mestu. A jedno od takvih mesta je već poznato - bafer koji se prostire od &2BB6 do &2036. Ovih 126 bajtova su prostor koji se u toku izvršavanja programa svakako ne koristi, pa može zgodno da posluži kao zona u koju bi se privremeno smeštali podaci. Zašto kažemo privremeno? Ukoliko se izvršavanje programa prekine, svakako će biti potrebno da korisnik otkuca nešto da bi program nastavio da radi. To nešto biva smešteno u bafer, čime jedan deo njegovog sadržaja nepovratno strada. Treba, takode. biti vrlo oprezan sa upotrebom bafera ako se koristi naredba INPUT za primanje podataka.

Mašinske programe i podatke koji su za njih potrebni možete slobodno da smeštate i na kraj RAM-a. ali je korisno pre toga promeniti sadržaj sistemske promenljive &2A6A. Područje iznad RAMTOP-a je bezbedno i na njega ne utiču ni naredbe za editovanje programa ni operacije sa numeričkim i alfanumeričkim nizom. Potrebno je, ipak, da obratimo pažnju na probleme koji mogu da nastupe ako jednoga dana proširimo memoriju "galaksije" ili ako program damo nekom prijatelju koji je to već učinio.

Nove naredbe

ROM računara "galaksija" je koncipiran tako da omogućava relativno jednostavno dodavanje novih naredbi i funkcija. Da bismo dodali novu naredbu ili funkciju nije neophodno da razumemo čitavu strukturu bejzik interpretatora (dovoljan je "recept" koji ćemo. korak po korak, dati u okviru ovoga poglavlja), ali nije loše da uočimo nekoliko osnovnih stvari.

Pri analizi bejzik programa računar "galaksija" u registru DE čuva adresu bajta koji se trenutno obraduje. Kada pišemo običan mašinski potprogram koji se poziva sa USR. registar DE će biti automatski, sačuvan na steku. Ako želimo da dodamo novu naredbu, potrebno je da se uklopimo u sam interpretator, tj. da po svaku cenu čuvamo sadržaj DE registra. Ukoliko naša naredba ima i neki adresni deo, potprogram koji je podržava mora da primi i taj deo, vodeći računa da registar DE. po povratku u bejzik. "pokazuje" na prvi neobrađen bajt iza.

Kao i DE, registar IX permanentno pokazuje stanje aritmetičkih akumulatora i treba ga, ukoliko nije vršeno računanje koje vraća rezultat bejziku, ostaviti nepromenjen. Naš program mora da se pobrine i za sve moguće sintaksne greške. Ako pogledate listing ROM-a. videćete da je dosta prostora posvećeno proveri sintakse i rutinama za tretiranje grešaka. Tako mora da bude. Ukoliko interpretatori (a dodajući naredbe i vi pišete taj interpretator) ne reaguje na grešku, može lako da se desi da računar krahira i da se program izgubi. Kada god u vašoj naredbi sintaksa koju je korisnik otkucao nije ispravna, treba da predvidite naredbu JP &78F (poruka WHAT?) ako je sintaksa ispravna ali argumenti ne odgovaraju naredbu JP &65A (poruka HOW?), a ukoliko je memorija premala za ono što je korisnik želeo da uradi JP &153 (SORRY). Pri tome ne morate mnogo da razmišljate o steku (SP će biti reinicijalizovan pre nego što "galaksija" napiše READY), ali morate da obratite pažnju na registar DE i sistemsku promenIjivu &2A9F. Ukoliko se u &2A9F (i &2AA0, naravno) nalazi nula, računar će jednostavno izdati poruku WHAT?, HOW? ili SORRY. Ukoliko je u &2A9F nešto drugo, računar smatra da mora da prikaže i liniju u kojoj se nalazi greška. Trebalo bi da DE pokazuje na prvi bajt koji nije bio razumljiv kako bi na tom mestu bio štampan upitnik. Ukoliko DE pokazuje neki bajt ove naredbe, sve će biti u redu i upitnik štampan na pravom mestu. Ukoliko DE ne pokazuje ispravno, biće štampana linija označena promenljivom &2A9F sa upitnikom na kraju. To se, na primer, dešava ako TAKE listi ne odgovaraju podaci u # listama.

Već smo u prethodnom pasusu videli koliko za nas mogu da učine potprogrami koji već postoje u ROM-u. Moramo da naučimo da se njima služimo što više, jer će nam tako nove naredbe biti mnogo kraće, pisaćemo ih nauporedivo lakše i brže i jednostavnije ćemo ispravljati greške koje smo napravili. Čitanje "recepta" koji sledi će vas. nadamo se, konačno uveriti u korist od sistemskih potprograma.

Link za naredbe zauzima tri bajta čije su adrese &2BA9, &2BAA i &2BAB. U prvoj od ovih memorijskih ćelija se normalno nalazi C9, što je kod mašinske naredbe RET dok druge dve nisu važne. Ukoliko želimo da dodajemo nove naredbe, treba da promenimo bajt čija je adresa &2BA9 u C3 (kod naredbe JP), a u sledeća dva da smestimo adresu na kojoj se nalazi naš program koji prepoznaje nove naredbe. Ukoliko taj program počinje od &3000. upotrebićemo naredbe:

LD A,&C3
LD (&2BA9), A
LD HL,&3000
LD (&2BAA), HL

Program koji počinje od &3000 treba najpre da prepozna da li je vreme da se naiđe na naredbu ili na funkciju. U čemu je razlika? Jednostavno rečeno funkcije se razlikuju od naredbi po tome što se nalaze desno od znaka jednakosti. Tako je, na primer, PRINT naredba a INT funkcija. Postoje neke reći koje mogu da budu i naredbe i funkcije (BYTE, WORD, DOT), ali to ne treba da vas zbuni: pogled na listing ROM-a će vas uveriti da je svaka od ovih reci u memoriji smeštena po dva puta i da se potpuno različito tretira u zavisnosti od toga da li se trenutno traži naredba ili funkcija. Mi ćemo, najpre. pokušati da uvedemo jednu naredbu.

Tabela naredbi

Kada očekuje da prepozna naredbu. "galaksija" će na link doći pomoću naredbe CALL i to sa adrese &75B. Obzirom na to. na vrhu steka će se u tom slučaju nalaziti bajtovi &07 i &5B. Pošto nam je i tako potrebno da sačuvamo HL registar, prva naredba našeg programa će biti EX (SP), HL čime smo u HL registar dovfeli adresu sa koje je dodeno na link. Sada treba da proverimo da li se u HL registru nalazi broj &75B. To ćemo uraditi tako što ćemo najpre sačuvati registar DE (PUSH DE), zatim u njega uneti ovu konstantu (LD DE, &75B) a onda izvršiti RST &10. Time je pozvan sistemski potprogram koji uporedu-je ragistre HL i DE upotrebom svega jednog bajta. Po povratku sa ovoga potprograma Z i C flagovi su setovani u zavisnosti od rezultata poredenja. Ukoliko je Z flag resetovan, registri HL i DE nisu bili jednaki, pa treba vratiti kontrolu bejzik interpretatoru. To radimo tako što restauiramo DE i HL i izvršimo jednostavno RET.

Ukoliko je Z setovan. treba da pokušamo da prepoznamo naredbu. Najpre ćemo, za svaki slučaj, vratiti DE u normalno stanje (POP DE), a zatim ćemo u HL smestiti adresu tablice umanjenu za jedan i preći na sistemski program čija je ulazna adresa &39A:

LD HL, TABLICA-1
JP &39A

Potrebno je još da formiramo tablicu koja se sastoji od naziva bejzik naredbi koje dodajemo, pri čemu se iza svake od njih nalazi ulazna adresa mašinskog programa koji je ostvaruje. Tekst se, jednostavno, smešta u memoriju slovo po slova, ali je ulazna adresa priličan problem. Ona se odnosi na neki program koji se nalazi bilo gde u prvih 16 Kb memorije, pa su za njeno smeštanje potrebna dva bajta. Prvi od njih daje značajniji bajt adrese (veoma je važno da uočite da ovo odstupa od standardne Zilogove mnemonike kod koje najpre dolazi manje značajan bajt adresa), pri čemu mu je najznačajniji bit setovan. Ovo setovanje bita je neophodno da bi računar razlikovao kraj imena od početka ulazne adrese.

Posle drugog, manje značajnog bajta adrese, sledi ime sledeće naredbe koju dodajemo, zatim sledeće i tako dalje. Posle poslednje naredbe stavljamo još jednu ulaznu adresu kojoj ne prethodi ni jedna reć. Ta adresa pokazuje bilo koji bajt prvih 16 KB memorije na kome se nalazi naredba JP &75B. Potrebno je, dakle, da računar nekako prepozna kraj tabele kako bi znao da nema više novih naredbi.

Naredbu koju dodajemo treba da započnemo jednim POP AF koje će resiti problem steka koji je poremećen CALL-om na link koji nije završen sa RET. Ovaj POP treba da zaboravimo čim smo ga stavili u program: ne treba ga kompenzovati nikakvim daljim PUSH, niti smo njim u AF registre doveli neke podatke od značaja. Slede instrukcije koje izvršavaju naredbu i njen završetak sa RST &30. Posle ovoga bejzik interpretator će pokušati da prepozna sledeću naredbu koja je adresirana DE registrom.

Koje korisne sistemske programe još možemo da upotrebimo? Potrebno je, pre svega, da prenesemo neke argumente nove naredbe. Ukoliko je naredbi potrebno samo jedan argument koji sledi iza nje u zagradi i po prirodi predstavlja ceo broj, stvar je vrlo jednostavna: u okviru tabele ćemo setovati bit 6 prvog bajta ulazne adrese (sada znamo zašto se sve mora nalaziti u prvih 16 Kb - najstarija dva bita ne služe za adresiranje). Izraz u zagradi će biti izračunat, računar će naći ceo deo tog izraza i poslati ga našem programu kao sadržaj registra HL. Registar DE će u tom slučaju pokazivati prvi bajt iza zagrade.

Ukoliko iz nekih razloga ne želimo da setujemo bit 6 u tabeli (to će se, na primer, dogoditi ako realizujemo naredbu koja ima različite moguće tipove adresnog dela), možemo da započnemo naredbu sa CALL &A6A, što ima istu funkciju. Ukoliko se argument ne nalazi u zagradi, iskoristićemo RST &8 koji će izračunati vrednost izraza i njen ceo deo smestiti u HL registar. Posle toga, naravno, može da sledi zarez koji odvaja prvi argument od drugog. Za detektovanje toga služi CALL &5. Ako OE pokazuje zarez, on će biti preskočen i sledeći izraz vraćen kao sadržaj registra HL, a ako ne pokazuje biće prikazano WHAT? prema pravilima koja smo ranije definisali.

Možda ćemo poželeti da jednostavno preskočimo blankove i dođemo do sledeće značajne bejzik konstrukcije. To radimo sa CALL &104. Ova rutina će nam koristiti ako želimo samo da detektujemo ono što se nalazi iza naše naredbe; u protivnom, do sada pomenuti potprogrami obaviće i ovo zaobilaženje blanko simbola.

Pošto dodajemo naredbu, nije nam dovoljno samo da prenesemo argumente - naša nova naredba treba da ima i neko dejstvo. To će retko biti neko jednostavno pomeranje memorije - obično treba kontaktirati sa ekranom ili tastaturom, a i tu mogu mnogo da pomognu sistemski pozivi.

RST &20 štampa na ekranu karakter čiji je kod smešten u registrar A. Pri tome će se, ako je taj bajt &D. preći u novi red. obrisati čitav ekran ako je poslat bajt &C. a obrisati poslednji karakter ako je u A &1D.

Ako se ne zadovoljavamo štampanjem jedne jedine cifre, poželećemo da koristimo CALL &937. Ovaj poziv na ekranu štampa čitav alfanumerik adresiran OE registrom i to sve do koda &D (izdaje se novi red na ekranu) ili do koda &00 koji ne izaziva novi red. Debagovanju programa će pomoći i mogućnost štampanja vrednosti registra HL kao ASCII niza slova - to se postiže sa CALL &8FB.

Očitavanje tastature

Tastaturu možemo da testiramo na više načina. Filozofiji mašinskog jezika najviše odgovara da se poslužimo memorijskim prostorom &2000 - &2037. Svakom bajtu ovoga prostora dodeljen je po jedan taster prema tablici KEY(N). Najmanje signifikantan bit ovoga bajta je setovan ako je taster pritisnut, a resetovan ako nije. Ako, na primer, želimo da detektujemo da li je taster A (kod 1) pritisnut, izvršićemo program:

LD A, (&2000+1) AND 1
JP Z, PRITISNUT

Mnogo je, međutim, komfornije koristiti potprograme za tastaturu. CALL &CF5, na primer. vraća u A registar kod zadnjeg pritisnutog tastera (kao KEY(0)) pri čemu, ukoliko je BRK pritisnut, računar prikazuje READY a ako je pritisnuto DEL privremeno prekida sa radom. Najneprijatnije je to sto STOP/LIST započinje (u takvoj prilici najverovatnije neželjeno) listanje programa. Sistemski potprogram &CF5 podržava, pored ostalog, i naredbu REPT za ponavljanje teksta.

Ukoliko želimo samo da računar prekine sa radom ako je pritisnuto BRK, a malo pričeka ako je DEL u akciji, izvršićemo samo CALL &2FF.

Interakcija bejzika sa mašinskim programima može da se odvija i preko promenljivih A-Z, X$, Y$, A(I) i X$(I). Za to je najbolje upotrebiti CALL &125. što locira varijablu na čije ime pokazuje DE. Po završetku rada u HL registru se nalazi apsolutna pozicija promenljive (poput naredbe PTR u bejziku). Carry flag je setovan ako DE ne pokazuje na nešto što bi moglo da bude promenljiva. Ukoliko je C flag resetovan, Z flag govori o vrsti promenljive: setovan Z označava numeričku, a resetovan - alfamuneričku promenljivu.

Sve što smo govorili o dodavanju naredbi ilustruje i program na slici 1. Unesite ga u računar (pomoću UTM-a) i startujte, pa će set naredbi vašešeg računara biti dopunjen naredbom CLEAR. Ona dodeljuje svim numeričkim promenljivima (A-Z) vrednost nula, što je neobično korisno pri inicijalizaciji programa (kada normalno otkucate RUN, promenljive zadržavaju vrednosti koje su dobile u prethodnim programima ili, ako od uključivanja računara nisu korišćene, sadrže broj 0.5).

Zašto smo se odlučili za naredbu koja ne opšti sa ekranom, ne prima ništa sa tastature niti zahteva neke argumente? Jednostavno smo želeli i da ilustrujemo sam princip dodavanja naredbi dok za prenošenje argumenata ima vremena - njega ćemo ilustrovati u sledećim redovima.

Nove funkcije

Funkcije se. kao što rekosmo, uvek nalaze sa desne strane znaka jednakosti kao deo aritmetičkog izraza. Najveći deo funkcija (ovde nije reč samo o računaru "galaksija") zahteva jedan argument koji se da bi se poštovala logika sintakse bejzika, obavezno stavlja u zagradu (kod nekih novijih kompjutera ovaj argument može ali ne mora da se stavi u zagradu, ali se korišćenjem zagrada eliminiše mogućnost zabune u slučajevima kada je argument čitav izraz). Kada naiđe na funkciju računar najpre određuje vrednost izraza u zagradi, zatim na tu vrednost primenjuje funkciju i dobijenim rezultatom dalje operiše u aritmetičkom izrazu.

Program za dodavanje funkcija je u mnogo čemu sličan programu za dodavanje naredbi, mada postoji i nekoliko razlika. Prva i najvažnija razlika je činjenica da se na ovaj program ne stiže sa lokacije &75B već sa lokacije &777. Na početku programa, dakle, ne treba u DE registar smestiti &75B već &777 pre nego što se izvrši RST &10. Isto tako. na kraju tabele ne treba ići na lokaciju RAM-a na kojoj se nalazi JP &75B. već negde treba formirati JP &777, pa se sa kraja tabele uputiti na to mesto.

Možda je najvažnije da se program koji izvršava funkciju završava sa RET ili JP &ABC. a ne sa RST &30. Kada koristimo RET a kada JP &ABC? Kada je rezultat neki ceo broj koji se nalazi u HL registru, koristićemo JP &ABC da bi taj broj bio smešten na aritmetički stek. Ukoliko smo već računali sa brojevima u pokretnom zarezu tako da se rezultat nalazi na aritmetičkom steku, upotrebićemo obično RET. Kako za sada znamo da radimo samo sa celim brojevima, naše funkcije će se završavati sa JP &ABC.

Program na slici 2 će. nadamo.se. učiniti da vam dodavanje funkcija bude znatno jasnije. Odlučili smo se za naredbu DISPLAY koja ima jedan argument koji daje poziciju na ekranu. Naredba DISPLAY tada vraća ASCII kod karaktera koji se nalazi na toj poziciji. Ovo, jasno, uvek možemo da zamenimo sa BYTE (&2800 + I) ali nam. kao što znamo, nije cilj da po svaku cenu dodajemo korisne naredbe koje bi bile složene. Kada razumete princip, moći ćete da se okušate i na nekoj drugoj funkciji.

Za sada, dakle, znamo da dodajemo samo funkcije čiji su argumenti i rezultati celi brojevi. Ovakve funkcije mogu da budu korisne u igrama i sličnim primenama. ali su matematički nastrojeni čitaoci ovih redova svakako poželeli da svoj računar dopune nekom trigonometrijskom ili eksponencijalnom funkcijom koja im mnogo nedostaje. To nije jednostavno kako se u prvi mah čini, ali verujemo da će ovakve funkcije veoma brzo opravdati trud uložen u razumevanje principa njihovog dodavanja. Taj trud će najvećim delom biti utrošen na razumevanje tzv. obrnute poljske notacije.

Obrnuta poljska notacija

Obrnuta poljska notacija. Lukasijevičeva notacija ili. jednostavno. RPN je sistem računanja koji na prvi pogled izgleda sasvim neprirodno (odatle valjda i ono "obrnuta" u nazivu), ali koji je sa aspekta računara i posebno mašinskih jezika nešto sasvim normalno i,skoro bi se moglo reći, jedino prihvatljivo. Oni koji su posedovali ili poseduju neki Hewlett-Packardov džepni računar (bio on programabilan ili ne) svakako su upoznati sa principima RPN-a pa mogu slobodno da predu na čitanje sledećeg poglavlja. Preostalima savetujemo da posete nekog prijatelja koji ima ovakav računar i u praksi provere koliko će im ovo poglavlje biti jasno. Proba sa džepnim kalkulatorom je daleko manje naporna od pokušaja da se na mašinskom jeziku (pogotovu ako ne posedujemo asembler) nauči RPN.

Za RPN notaciju je stek neobično važan pojam. Stek možete da zamislite kao orma n sa mnogo polica koje se nalaze jedna iznad druge. Na svakoj polici može da se nade samo jedan predmet (u našem slučaju samo jedan broj). Zato kada god želimo da stavimo broj na donju policu broj koji se u njoj nalazio mora da bude prenesen na prethodnu, broj iz prethodne na policu iznad nje i tako dalje. U teoriji bi stek morao da bude beskonačan, što znači da se dodavanjem broja ništa ne gubi iz njega. No računari teško mogu da posluju sa beskonačnom memorijom koja bi morala da bude upotrebljena da se sačuvao beskonačni stek, pa naš orman ima gornju policu. Kada stavimo neki broj na stek, broj iz pretposlednje police će preći u poslednju, dok će broj iz poslednje police biti za sva vremena izgubljen.

Najniže dve police u steku su posebno privilegovane jer se u njih smeštaju argumenti aritmetičkih operacija. Ako, na primer. treba da saberemo brojeve 2 i 3, najpre ćemo na stek staviti broj 2 a zatim i broj 3 (time će broj 2 biti pomaknut u sledeću policu), a zatim pozvati program za sabiranje. Da li će on izračunati zbir i staviti ga na stek? Stvar nije tako jednostavna: po sabiranju nam je potreban zbir. a ne i argumenti koji bi na ovaj način ostali zauvek na steku. Zato će program za sabiranje najpre spustiti stek za jedno mesto (u gornju policu upisati nulu, sadržaj gornje, police preneti na policu ispod nje itd, sve dok sadržaj druge police ne pomeri u prvu a sadržaj prve ne skloni sa steka), sabrati argumente koji su se ranije nalazili na najniže dve police i smestiti zbir na najnižu policu "zaboravljajući" njen prethodni sadržaj. Ako su se. dakle, na steku nalazili brojevi 2, 3, 4 i 7 (tim redom; 2 je na najnižoj polici), posle sabiranja će na steku biti brojevi 5, 4, 7 i 0.

O množenju teško vredi reći išta novo, ali oduzimanje i deljenje zahtevaju nekoliko reći objašnjenja. Kod ove dve operacije, naime, nije svejedno da li će se računati X-Y (X/Y) ili Y-X (Y/X). Zato je u RPN-u uvedena konvencija koja kaže da je broj koji se nalazi na najnižoj polici steka uvek umanjilac (delilac), a da je broj iznad njega uvek umanjenik (deljenik). Ako se, kao u malopredašnjem primeru, na steku nalaze brojevi 2, 3, 4 i 7 posle oduzimanja će on dobiti oblik 1, 4, 7 i 0.

Osim četiri osnovne računske operacije, potrebno nam je i poređenje brojeva. Porede se, naravno, brojevi na najniže dve police steka. ali mogu da postoje dva pristupa ovakvoj operaciji. Po jednoj poredenje brojeva ne remeti stek ni u kom smislu (ovako nešto važi kod Hewlett-Packardovih programabilnih kalkulatora kao što je HP41C), a po drugoj poređeni brojevi nestaju sa steka dok se čitav stek spušta za dva mesta uz popunjavanje poslednje dve police nulama (ovakav pristup je zastupljen na računaru "galaksija").

Broj u kondenzovanom formatu

Do sada smo smatrali da se na svakoj polici steka u jednom trenutku može naći samo jedan broj, što nam je u mnogome olakšalo čitavo rezonovanje. Svaki vlasnik "galaksije", međutim, zna da svaki broj u pokretnom zarezu zauzima četiri bajta. a zabuna će biti kompletna kada kažemo da se svaki broj na steku sastoji od pet bajtova!

Da bismo razumeli čitavu zbrku, moramo da upoznamo organizaciju "galaksijinog" pamćenja brojeva. Svaki broj u pokretnom zarezu zauzima četiri bajta (32 bita) memorije nalazeći se u takozvanom "kondenzovanom formatu". Kondezovani format, međutim, nije pogodan za računanje, jer je eksponent broja pomešan sa njegovom mantisom. Zato je pre svake aritmetičke operacije neophodno broj iz kondenzovanog prevesti u normalizovani format. Takav broj će zauzimati 40 bitova od kojih će osam biti neiskorišteno. Ako po završetku rada treba "zapamtiti" neki normalizovani broj, pretvorićemo ga ponovo u kondezovani format i smestiti u memoriju. Čemu ova komplikacija kada su svi brojevi mogli da se čuvaju u normalizovanom formatu? Jednostavno zbog uštede skučenog memorijskog prostora.

Za programera bi bilo previše komplikovano da stalno misli na to koliko bajtova zauzima koji broj na steku, koliko je ovaj popunjen, šta pokazuje registar IX i slično. Zato su obezbedeni sistemski programi koji omogućavaju da stek zamislimo kao orman sa policama opisan u prethodnom poglavlju. Ukoliko se služite njima, ćiniće vam se da se na svakoj polici nalazi po jedan broj; nećete misliti na to koliko on ima bajtova, u kom je formatu i tome slično. Zato ćemo sledeće redove posvetiti sistemskim potprogramima za operacije sa stekom.

Najčešće će procesorski registar HL pokazivati na neku memorijsku lokaciju počevši od koje je smeštena konstanta koja zauzima četiri bajta. CALL &A45 će ovu konstantu prevesti u normalizovani format i smestiti je na aritmetički stek uz njegovo obavezno pomeranje nagore. Inverznu funkciju (smeštanje broja sa dna steka u četiri bajta memorije na koje pokazuje HL) obavlja CALL &A6D.

Kako se konstante uopšte stavljaju u memoriju? Ako se radi o celobrojnoj konstanti, možemo da je smestimo u HL registar i izvršimo CALL &ABC. Ovaj poziv će sadržaj registra HL pretvoriti u broj u normalizovanom obliku i smestiti ga na aritmetički stek uz uobičajeno pomeranje. Inverznu funkciju (smeštanje celog dela broja sa dna aritmetičkog steka u HL uz spuštanje steka) obavlja CALL &A6O.

Kako, međutim, da smestimo konstantu koja nije cela tako da je docnije prenesemo na stek naredbom CALL &A45? Namerno nismo trošili prostor na objašnjenje smeštanja brojeva u kondenzpvanom formatu (možete li da dedukujete način na koji "galaksija" smešta brojeve?) jer ovo prevođenje može za nas da obavi operativni sistem primenom jednog lepog trika. Potrebno nam je, na primer, da ustanovimo kako se u memoriju smešta broj 1 (on je ceo. ali na sasvim isti način možemo da postupimo i ako nije). Tada ćemo najpre izvršiti A=1, a zatim: FOR I=0 TO 3: PRINT BYTE (PTRA+I): NEXT I. Tako ćemo, bajt po bajt, videti da se broj 1 smešta u memoriju kao (posle prevođenja u uvek pogodnije heksadekadne brojeve): &00, &00, &80 i &00.

Krajnje je vreme da damo i adrese sistemskih rutina koja obavljaju osnovne operacije. CALL &B32 sabira. CALL &B1E oduzima, CALL &AE6 množi, CALL &AF7 deli a CALL &B10 poredi brojeve (rezultat poređenja biva smešten u Z i C flagove na uobičajeni način). Da ne ostanemo dužni onima koji žele da pišu programe za igre, sistemski program koji na stek stavlja slučajni broj između O i 1 može da se pozove sa CALL &C8F. Ukoliko nam je, najzad, potrebno da izračunamo vrednost čitavog izraza i smestimo je na stek, postavićemo DE registar tako da pokazuje na početak izraza i izvršiti CALL &AB2. Ukoliko je taj izraz u zagradi (npr. ako je argument neke funkcije), upotrebićemo CALL &781. Ukoliko, najzad, želimo samo da utičemo na znak broja, setovaćemo ili resetovati bit 7 u ćeliji na koju pokazuje IX-1, u zavisnosti od toga da li je broj negativan ili pozitivan.

Kao ilustraciju svega ovoga i još jedno podsećanje na mogućnosti dodavanja funkcija dajemo program sa slike 3. On dodaje računaru funkciju REC koju prati argument u zagradi. Funkcija izračunava, kao što joj ime i govori, recipročnu vrednost ovog argumenta, što i nije nešto naročito korisno ali zato odlično ilustruje rad sa aritmetičkim stekom. Namerno se nismo poslužili sistemskim programom &ABC koji je mogao da prenese jedinicu iz HL na stek - smeštanje četvorobajtne konstante u memoriju i njeno prenošenje na stek pomoću CALL &A45 je mnogo instruktivnije.

Link za video

Pogled na mapu sistemskih promenljivih pokazuje da "galaksija", osim linka za naredbe, ima i link za video na adresama &2BAC, &2BAD i &2BAE. Pre nego što će na ekranu ispisati bilo koje slovo (podrazumeva se da to slovo treba da bude ispisano sistemskim pozivom RST &20 a ne direktno smešteno na ekran pomoću LD ili BYTE) računar izvršava CALL &2BAC. Ukoliko po pozivu naiđe na RET, računar će se vratiti u ROM i ispisati karakter. Ukoliko, međutim, na ovim adresama nađe neki JP, naš program će preuzeti kontrolu i karakter će biti ispisan tek posle naše obrade, kada računar nađe RET na kraju našeg programa u RAM-u.

Link za video je pre svega obezbeđen da bi uopšte bilo moguće podržati rad sa štampačom. Ukoliko je ovaj priključen, trebalo bi sastaviti program koji, kada je neki flag setovan, prenosi svako slovo koje treba da bude ispisano na ekranu na papir posredstvom porta i štampača koji je sa njim povezan. Videćemo, međutim, da se sa ovim linkom mogu postići i neke druge stvari koje će interesovati i one koji ne poseduju štampač. Poćećemo od najjednostavnije i ne naročito korisne primene koja će nam pomoći da shvatimo drugi primer programa.

Da li vam se nekada učinilo da vaša "galaksija" radi prebrzo? Naravno da nije (to se ne dešava čak ni vlasnicima daleko bržih kompjutera), ali ćemo vam prikazati program koji će usporiti ispisivanje poruka. Ideja je u tome da nije ni malo teško sastaviti bejzik program koji će na ekranu usporeno ispisivati neki tekst da bi se, na primer, realizovala neka EPP poruka. Ipak, retki su računari kod kojih se može intervenisati tako da se uspori ispisivanje poruka bejzik interpretatora. Pokažite program sa slike 4 nekom vlasniku ZX81 ili Spectruma - računara koji ne omogućavaju nikakav izlazak iz ROM-a!

Kako radi ovaj program? Ništa lakše - pre ispisivanja svakog, karaktera "galaksija" izvesno vreme izvršava "mrtvu petlju" koju možete da skraćujete ili produžavate menjanjem broja koji se smešta u HL registar na početku njenog radnog dela. Po završetku "mrtve petlje" jedno RET vraća kontrolu nad računarom bejzik interpretatoru u ROM-u. Primetite da je bilo neophodno sačuvati registar AF.

Program sa slike 5 predstavlja daleko složeniju primenu linka za video i znatno veće posezanje u rad operativnog sistema. Umesto READY, računar će ispisivati GALAKSIJA sve dok je ovaj program u memoriji.

Kako smo to postigli? Pre svakog READY, "galaksija" ispisuje znak koji se sastoji od dva karaktera čiji su kodovi 64 i 39 (označeni u tabeli na strani 18 kao spec). Mašinski program najpre ispituje da li se u registru A nalazi kod 64 koji označava da upravo treba da bude štampana leva polovina znaka. Ukoliko nije stigao kod 64, izvršava se obično RET i dozvoljava ispisivanje karaktera. Ukoliko, međutim, program prepozna karakter čiji je kod 64, biva proglašeno "vanredno stanje": u jednu memorijsku lokaciju se upisuje podatak da sledećih 6 bajtova ne treba štampati a zatim se, na sasvim standardan način, na ekranu ispisuje tekst GALAKSIJA.

Najsloženije je bilo "zabraniti" računaru da štampa karaktere. Da bi ovo bilo moguće, proučili smo rutinu za štampanje karaktera u ROM-u i utvrdili da "galaksija", posle RST &20, poziva dva nivoa potprograma od kojih je drugi link. Zato naša rutina skida sa steka prva četiri bajta koja predstavljaju dve adrese za povratak sa potprograma (trebalo bi da svi znamo da adresa za povratak sa potprograma ima dva bajta, a da isto toliko sa steka "sklanja" jedno POP HL). Računar, dakle, na završetku našeg programa nailazi na RTN, ali sa ono ne vraća na mesto na kome se nalazio CALL koji je pozvao link već u rutinu koja je pozvala RST &20: karakter nije ni štampan, što smo i želeli.

Link za video može da se koristi i za mnogo što-šta drugo (sačekajte samo malo pa ćete naići na program koji se automatski startuje) pa i za jednostavno intervenisanje u video igrama. Ima, na primer, igara kod kojih se igračev "broj života" ispisuje samo na ekranu, pa bi u principu bilo moguće beskonačno produžavati igru zabranjujući brisanje karaktera koji ga predstavljaju. Čini nam se, ipak, da je ovakva primena sličnih linkova daleko zahvalnija kod drugih računara. kod kojih je struktura ekrana komplikovanija (link za video kod Spectru-ma bi mogao divno da se koristi... da postoji). Autori igara za "galaksiju" će svakako smatrati da je lakše prosto "poukovati" nešto u ekran nego koristiti sistemski i program koji to radi.

Link u interaptu

Na početku poglavlja koje je posvećeno računaru "galaksija" rekli smo da nikako ne treba koristiti registar IY jer je on korišćen kao link u interaptu. Pošto smo do sada stekli sva potrebna znanja o pojmu linka. posve tičemo se podrobnije ulozi koja je dodeljena registru IY. Moramo, međutim, da upozorimo da su linkovi koje smo pominjali opasni prema redosledu izlaganja, što znači da je najopasnije baviti se ovim poslednjim: pre startovanja svakog programa treba "sors fajl" (izvorni program) snimiti na kasetu. Kada pogrešno završen interapt "uguši" racunar. RESET najverovatnije neće pomagati - biće potrebno da isključite i ponovo ga uključite.

Pošto je pomogao video stepenu da generiše sliku i povećao brojač sekundi u časovniku (ako je ovaj uključen, naravno), mikroprocesor je pri kraju interapta - treba još samo uzeti sistemske registre sa steka i izvršiti RETI. Pre nego što to uradi, međutim, mikroprocesor nailazi na naredbu JP (IY). U registru IY je u toku inicijalizačije računara smešten broj &00FD, pa mikroprocesor izvršava naredbe koje se tamo nalaze. To su četiri POP naredbe i RETI.

Možemo da promenimo sadržaj registra IY tako da on pokazuje neku lokaciju u RAM-u. Tamo treba da se nalazi program koji će se izvršavati svake pedesetinke sekunde i koji će se završavati sa JP &FD. Pri izradi takvog programa, međutim, treba da budemo neobično pažljivi: on. pre svega, mora da se izvršava vrlo kratko jer svaki mašinski ciklus njegovog izvršavanja skraćuje iskorištenje mikroprocesora za izvršavanje redovnog programa. Osim toga, za vreme interapta ne sme nikako da se desi da mikroprocesor dobije novi interapt, ako ništa drugo zbog toga što bi se stek tako stalno punio. Da bi to bilo sprečeno, na samom početku interapta mikroprocesor automatski izvršava DI. Ukoliko naš program koji se izvršava u interaptu, samostalno ili nehotičnim pozivom neke rutine iz ROM-a, izvrši EI, vrlo je verovatno da će nastupiti veliki problemi. Ako se ovo ne desi, ali se interapt ne omogući u razumnom vremenu, slika se više neće videti i jedini spas će biti isključenje računara.

Osim kratkoće, savetovali bismo vam da u okviru programa koji se izvršava u interaptu ne pozivate potprograme iz ROM-a jer većina njih u nekim slučajevima može da poremeti normalan tok stvari (odlaskom na rutinu za grešku, na primer). Ako. dakle, želite da testirate neke tastere u interaptu, moraćete da testirate ćelije &2000-&2037 a ne da koristite CALL &CF5.

Na slici 6 dajemo primer korišćenja linka u interaptu. Radi se o rutini koja se nekada nalazila u ROM-u, ali je morala da bude žrtvovana zbog nekih resenja rada sa alfanumericima: neprekidnom prikazivanju vremena. Kada otkucamo i izvršimo ovu rutinu, neće se, bat u prvi mah. ništa dogoditi. Da bismo videli i njeno dejstvo. otkucaćemo Y$=12:10.15:10":DOT* (zapazite da su minuti i sekundi odvojeni tačkom, a ne uobičajenim dvema tačkama). Od toga momenta u desnom gornjem uglu ekrana videćemo tekuće vreme. Bez obzira da li listamo program ili brišemo ekran, vrema će biti prikazivano sve dok, na primar, ne otkucamo Y$="12:10:15:10".

Kako je ovaj efekat posignut? Prilično jednostavno: svake pedesetinke sekunde racunar prenosi sadržaj promehljive Y$ na ekran ukoliko su ispunjena dva uslova. Prvi je da se u Y$ uopšte nalazi vreme (treći simbol treba da budu dve tačke), a drugi da je peti simbol stringa Y$ tačka. U ovom programu se javlja i naredba HALT koju obično prenebregavamo u školama programiranja na mašincu, pa smo odlučili da joj ovde posvetimo par reči.

Naredba HALT izaziva prekid rada mikroprocesora, što obično izaziva pomisao da je ona destruktivna. Mikroprocesor, međutim, neće zadugo stajati: čim naiđe prvi interapt, njegova aktivnost će se nastaviti. To znači da se HALT može prevesti kao "sačekaj prvi interapt. izvrši ga, pa nastavi sa radom". Kao takva, HALT je neobično korisna naredba: ukoliko želimo da radimo nešto sa IY registrom ili čak da prenosimo veće blokove ekrana, vrio je korisno upotrebiti naredbu HALT kao neku vrstu sigurnosnog ventila. Ukoliko to ne učinimo, moguće je da program počne da greši s vremena na vreme u naoko besmislenim trenucima, a iskustvo nam govori da se takve greške najteže otkrivaju.

Šta bi se desilo da je, u momentu kada je mikroprocesor naišao na HALT, interapt bio onemogućen (DI)? U tom slučaju bi HALT zaista blokirao računar, ali bi pritisak na RESET povratio sve u normalno stanje bez štete po sadržaj RAM-a. Dolazak na "farmu" bi, ujedno, i omogućio interapt, pa bi se pojavila i slika koje do toga momenta nije bilo.

Obzirom da govorimo o interaptu, neophodno je da sa par reći obradimo NMI, nemaskirani interapt. On nastupa kada korisnik pritisne dirku RESET koja se nalazi sa zadnje strane "galaksije". Nemaskirani interapt se razlikuje od maskiranog po tome što racunar. kada ga dobije, u istom trenutku prestaje sa izvršavanjem naredbe koja je trajala i prelazi na program koji se nalazi u ROM-u počevši od &66. Tamo najpre biva reinicijatizovan stek pointer a zatim ispisano READY. Posle nemaskiranog interapta "galaksija" neće reinicijalizovati sistemske promenljive, linkove i sadržaj IY registra, što za praktičnu posledicu ima činjenicu da računar može ali i ne mora da se vrati u radno stanje - ako je, na primer, interapt pogrešno organizovan, slike neće biti ni posle RESET-a.

Kako se "pakuje" bejzik

Došlo je vreme da se posvetimo periferijskoj jedinici koju svi vlasnici "galaksije" redovno koriste - kasetofonu. Pre nego što objasnimo rad sa njom i navedemo adrese dva sistemska potprograrna koja će nam omogućiti daleko više od naredbi OLD i SAVE, posvetićemo pažnju načinu na koji "galaksija" pakuje bejzik program u svome RAM-u.

Kod "galaksije" nije zastupljeno takozvano tokenizovanje naredbi, što ima dobre i loše strane. Pošto naredba nije pretvorena u poseban kod (kod Spectruma se, na primer, PRINT pretvara u &F5). lako je analizirati progam bajt po bajt, ali se zato njegovo izvršavanje unekoliko usporava. Program je, dakle, u memoriji smešten onakav kakav jeste, slovo po slovo, uz dva izuzetka.

Linijski broj se kodira kao dva bajta i to u obliku koji proizvodi naredba WORD. Ukoliko, na primer, prva naredba bejzik programa glasi 1500 GOTO 1550, PRINT WORD (&2C3A) će dati rezultat 1500. Blanko koji računar prikazuje prilikom listanja programa između linijskog broja i prvog slova naredbe nije upisan u RAM-u (tako se štedi memorija), dok se ostali blankovi u okviru linije kodiraju kao i svaki drugi ASCII karakter.

Posle poslednjeg znaka neke programske linije u memoriji je obavezno smešten bajt &D (13 dekadno) koji predstavlja terminator linije (znak da je ona završena) i pokazuje računaru da su sledeća dva bajta broj sledeće linije. Ukoliko se radi o poslednjoj liniji bejzik programa, iza njenog &D se ne stavlja ništa posebno (kod drugih računara kraj bejzika označavaju jedna do tri nule ili neki drugi specijalni kodovi). Kod "galaksije" bi ovakav terminator bio nepotreban: sistemska promenljiva čija je adresa &2C38 u svakom trenutku pokazuje gde se nalazi prvi slobodan bajt iza bejzik programa. Ukoliko smo, na primer. u memoriju stavili samo bejzik naredbu 10 PRINT A, memorijske ćelije počevši od &2C3A imaju redom sadržaje 0, 10, 80, 82, 73, 78, 84, 32, 65 i 13 a promenljiva &2C38 ima vrednost &2C44.

Dobar primer svega ovoga je program "Telefonski imenik" koji je objavljen u "Galaksiji" broj 143. Ovaj program modifikuje samoga sebe dodajući nove naredbe i kodirajući ih na odgovarajući način. On stalno vodi računa o sistemskoj promenljivoj &2C38 koju povećava posle dodavanje svakog bajta. Pri njegovoj analizi treba jedino imati u vidu da bejzik program ne počinje od &2C3A (tu je smešten mašinski potprogram) već da je sa NEW 60 početak bejzika pomeren za 60 bajtova. Računar to registruje promenom sistemske promenljive &2C36.

Snimanje na kasetu

Dolazimo, najzad, do snimanja programa i podataka na kasetu. Da bi računar mogao korektno da učita program, moraju da mu budu saopštene informacije o njegovoj dužini i (kada nije reč o bejzik programu) adresi od koje ga treba upisivati. Zato se ispred svakog programa nalazi takozvani "heder" (zaglavlje) u okviru koga su upisane ove informacije. Pre hedera na traku biva snimljen takozvani "lider" od 96*8 nula bitova koji nemaju nikakvu posebnu ulogu - oni jednostavno saopštavaju računam da sledi program i omogućavaju da se kasetofoni koji imaju automatsku kontrolu nivoa reprodukcije prilagode specijalnim tonovima. Računar pri ućitavanju ne proverava da li je učitano baš 768 "praznih" bitova pa očitavanje programa ne morate da počnete sa trakom premotanom tačno na mesto na kome se nalazi početak "lidera"; tolerancija, jasno, nije velika.

Posle "lidera" nailazi sinhronizacioni bajt &A5 koji se takode ne unosi u memoriju; on govori računaru da je došao kraj "lidera" i da sledi "heder". Heder ima samo četiri bajta: prva dva označavaju adresu od koje program treba da bude smešten u memoriju, a druga dva adresu prvog bajta koji će biti slobodan posle unošenja programa. Sledi sam program, bajt po bajt. Na kraju snimka nailazi takozvani "čeksum": jedan bajt koji omogućava računaru da sa velikom sigurnošću (ova sigurnost ni kod jednog kompjutera ne može da bude stoprocentna) utvrdi da li je program ispravno upisan u memoriju ili je u toku očitavanja neki bajt ispušten ili deformisan. Šta je, dakle, "čeksum"? U toku upisa programa u memoriju. "galaksija" sabira pročitane bajtove i to po modulu 256 (100+20=120, 120+111=231. 231+30=50=261-256) i tome slično), a čeksum ovaj zbir popunjava do 00 (u gornjem primeru čeksum bi bio 256-5=251).

Ukoliko bi se po učitavanju pokazalo da zbir dopunjen ćeksumom nema vrednost nula, bilo bi sasvim sigurno da je program pogrešno upisan, pa bi računar ispisao WHAT? a zatim i READY. U protivnom, vrlo je verovatno (moguće je, naravno, da je neki bajt povećan za jedan, a neki drugi smanjen za 1, što se u konačnom zbiru ne primećuje) da je program ispravno prepisan u memoriju, pa će "galaksija" ispisati samo READY.

Čak i kada je program pogrešno upisan sa kasete, rečunar "galaksija", zahvaljujući originalnom metodu kodiranja bitova, olakšava njegovo "vraćanje na normalu" uz minimalne intervencije. Na kasetu se upisuju četvrtasti impulsi koji predstavljaju binarne jedinice i nule. Svaki impuls se sastoji od pozitivne i negativne poluperiode od kojih svaka traje po 0.22 ms. Ukoliko se na kasetu upisuje binarna nula sledi pauza duga 2.46 ms a ukoliko se upisuje jedinica - kratka pauza od 1.1 ms. Iza ovakvog "dvostrukog" imulsa koji odgovara jednom bitu slede drugi, treći i ostali bitovi bajta, koji su kodirani na isti način. Po završetku čitavog bajta sledi dodatna pauza od 5.36 ms koja predstavlja značajno osiguranje: ako se desi da računar zbog oštećenja trake ili nekog drugog problema ispusti neki bit, pauza od 5.36 ms će se "podsetiti" da je bajt završen i on će biti spreman da primi sledeći. Tako će biti ispušteno jedno slovo, ali će sva dalja biti ispravna ukoliko nije bilo daljih oštećenja. Računar će po učitavanju ispisati WHAT?, pa će obično RUN verovatno naći sintaksnu grešku koju ćemo lako ispraviti. Postoji verovatnoća (mada vrlo mala) da program posle greške u učitavanju bude sintaksno ispravan, ali da nekorektno radi. U tom je slučaju mnogo lakše pokušati novi upis sa kasete nego tražiti grešku u imenu promenljive ili konstanti.

Da biste sami upisali bajt na traku treba, najpre. da mašinskim programom isključite interapt (DI), a zatim da pozovete sistemski potprogram čija je ulazna adresa &E68. Na traku će biti poslat bajt iz registra A.

Učitavanje bajta sa kasete se postiže na prilično sličan način - CALL &EDD će navesti računar da sačeka sledeći bajt ("galaksija" neće imati ništa protiv ako do nailaska tog bajta protekne daleko više od 5.36 ms) i da ga prenese u registar C.

Program sa slike 7 je jedan od primera rada sa kasetofonom: on omogućava relocirano snimanje programa. Rutina sa slike 7 se smešta na sam kraj memorije kako bi bilo moguće upisivati programe koji se nalaze na njenom početku. Kada izvršite program, vaš računar će posedovati novu naredbu RSAVE koja ima tri argumenta: prva dva odgovaraju argumentima naredbe SAVE koja omogućava snimanje segmenta memorije, a treći daje adresu počevši od koje će se na kasetu upisani program docnije upisivati. Naredba RSAVE &3000, &3500, &500 će snimiti sadržaj memorijskih ćelija &3000-&3500 na traku, ali će se ovaj program ubuduće ućitavati počevši od &3500 (=&3000+&500) kada upotrebimo obično OLD. Program predstavlja dobar uvod za sledeće poglavlje. Želeli smo da navedemo dve primene koje bi trebalo da budu ne samo poučne nego i korisne. Prva od njih će biti automatsko startovanje programa!

Automatsko startovanje programa

Sinclairovi računari omogućavaju da program koji se učitava sa kasete počne da se izvršava bez ikakvih daljih intervencija korisnika. Obrazloženje potreba za ovim automatskim startovanjem je obično tvrdnja da je za početnika teško da pamti naredbu RUN što i nije neki razlog (ako već mora da pamti naredbu LOAD"", RUN valjda ne predstavlja toliki problem). Da su oni koji propovedaju automatsko startovanje iskreni, rekli bi da ono predstavlja dobar način zaštite od neovlašćenog presnima-vanja programa. "Galaksija" nikada nije bila pristalica nekih zaštita programa, najpre zbog želje da naš softver što više kruži među čitaocima. Dakle, razlog zbog koga navodimo informacije vezane za autostart programa nije naša želja da stimulišemo čitaoce da nam šalju zaštićene programe (na kraju poglavlja ćemo reći i kako se ovakve zaštite "probijaju"), već verovanje da je autostart lepa "caka" koja ilustruje mnogo stvari o kojima smo do sada govorili.

Ideja je prilično jednostavna: kada računar "galaksija", primenom naredbe OLD. učita program, on će pokušati da ispiše READY. Ukoliko je u link za video upisan poziv nekog programa, kontrola će biti predata tom programu koji će se, dakle, startovati odmah po učitavanju. Ostalo je još pitanje kako da postignemo da se sadržaj bajtova &2BAC-&2BAE promene u toku učitavanja programa. Samo na jedan način - naš program treba da počne da se ućitava od adrese &2BAC, a njegova ulazna adresa treba da bude na samom početku. Posle ovakve intervencije nećemo, jasno, vise moći da se oslanjamo na RST &20, sistemsko skrolovanje slike i slične usluge operativnog sistema. Zauzvrat, čak ni pritisak na RESET neće prekidati naš program - i posle nemaskiranog interapta "galaksija" će pokušati da ispiše READY i ponovo započeti izvršavanje našeg programa.

Sve ovo ilustruje program sa slike 8 dat kao hex-dump. Unesite ga. u memoriju a zatim (pod uslovom da se u memoriji već nalazi startovan program, sa slike 7), otkucajte RSAVE &3BAC, &3BDD, -&1000. Isključite i uključite računar pa otkucajte OLD i startujte kasetu na koju ste maločas snimili program. Po njegovom učitavanju. na ekranu ćete videti jednu kratku poruku koju će RESET ponavljati.

Zamislite da vam je neko dao program sličan ovome i to na kaseti. Kako da ga presnimite ako ne želite da se upustite u metod koji uvek daje dobre rezultate presnimvanje uz pomoć dva kasetofona? Ne brinite, nije mnogo teško. Najpre utvrdite njegovu početnu (MMMM) i krajnju (NNNN) adresu. Otkucajte OLD 200 i učitajte program koji će ovim biti relociran za 200 bajtova. Zatim, koristeći program sa slike 7, otkucajte RSAVE MMMM+200, NNNN+200, -200 i mirno snimite program na novu kasetu.

Može li da se napravi bolja zaštita? Može ako sastavite program koji će biti toliko dugačak da za njegovo relocirano upisivanje nema mesta (npr. program koji bi se prostirao od &2BAC do &3FFF) što možete da učinite jedino ako posedujete memorijsko proširenje. Takav program će biti prilično dobro zaštićen od onih koji nemaju toliku memoriju, ali oni sa hardverom poput vašeg i dalje neće imati problema, a snaći će se i jedan deo "lukavijih" sa RAM-om od 6 Kb: sastaviće program za prepisivanje koji će počinjali od &2A00 i smestiti ga u područje numeričkih varijabli koje u toku učitavanja programa nije mnogo bitno.

Ukoliko, najzad, sastavljate program uz pomoć nekog drugog računara sa mnogo memorije ili disk jedinicama, nema prepreke da napišete rutinu dugu nekih 54 kilobajta koja će, samom svojom dužinom, biti prilično dobro zaštićena (možete li da sastavite program koji bi presnimio i ovakvo nešto? Ne zaboravite da iza svakog bajta na kaseti može da postoji i pauza duža od 5.36 ms), ali takva rutina neće biti baš mnogo komercijalna jer će njeno učitavanje trajati.

Svi "galaksijini" bagovi

Redovni čitaoci naših napisa u "Galaksiji" su se u poslednje vreme upoznali sa pojmom "bag", ali neće biti loše da, u cilju opšteg kompjuterskog obrazovanja, još jednom kažemo nekoliko reči o njemu.

Bag je greška u operativnom sistemu računara koja se ispoljava u nekim specijalnim situacijama kao reakcija na neku nepredviđenu akciju korisnika. Ne treba misliti da je bag trenutak kada računar ispiše SYNTAX ERROR ili WHAT? - tada je sve pod potpunom kontrolom operativnog sistema. Posledice baga su obično daleko teže: gubitak linije, programa ili sadržaja čitave memorije, pogrešan ispis na ekranu ili gubitak njegovog sadržaja, remećenje bitnih sistemskih promenljivih...

Svi računari imaju bagove koji predstavljaju manju ili veću smetnju njihovim korisnicima. Izuzetno, kod nekih računara sa "zatvorenim" operativnim sistemom (bez PEEK i POKE) bagovi mogu da budu korisni, jer otvaraju pristup područjima memorije koja su inače tabu za korisnika. Proučavanjem i sistematizacijom bagova računara HP41C članovi američkog PPC kluba su razvili sintetičko programiranje koje im je omogućilo kompletnu kontrolu ovog čuvenog džepnog računara.

Što se kućnih kompjutera tiče, njihovi bagovi uglavnom prave samo probleme: BBC mikroračunar i dalje ima bagova (najozbiljniji od njih praktično onemogućava korišćenje zareza u naredbi PRINT), premda njegov operativni sistem predstavlja dvanaestu verziju istog programa. Spectrum (pogotovu stariji modeli) ima pregršt bagova od kojih je, na svu sreću, malo "pogubnih", naredbe za editovanje kod TRS 80 izazivaju bezbrojne probleme kod neiskusnih korisnika koji teže da primene sve što su našli u uputstvu za upotrebu... Nije ništa bolje ni kod drugih kompjutera.

Iako smo uložili dosta truda da pronađemo i eliminišemo sve "galaksijine" bagove, nismo se nikada zavaravali nadom da ih neće biti. Teši nas jedino činjenica da su sve "galaksijine" bagove pronašli oni koji su radili na njegovom razvoju - sudeći po vašim pismima, nijedan čitalac "Galaksije" nije naišao na neki bag svoga računara. Mi ćemo, naravno, navesti pronađene bagove da bi se čitaoci ovih redova čuvali situacija koje mogu da izazovu probleme.

BUG 1: Otkucajte punu programsku liniju (obeležje 10 i slova A sve dok računarev bafer ne bude pun, na primer). Zatim otkucajte EDIT 10 i, kada se linija pojavi na ekranu, pritisnite DEL nekoliko puta a zatim i ENTER. Pritisnite LIST - ko je rekao da se u memoriji "galaksije" nalazi neki program?

BUG 2: Otkucajte liniju koja će glasiti 10 A= zatim tridesetak otvorenih zagrada, pa neki broj, pa isto toliko zatvorenih zagrada, a zatim startujte program. Posledice su iste kao kod baga 1. Napominjemo da će "normalan" broj od dvadesetak otvorenih zagrada izazvati "normalnu" reakciju HOW?

BUG 3: Ovaj bag je toliko dobro sakriven da još nismo uspeli da ga lociramo. U nekim retkim situacijama naredbe za rad sa numeričkim nizom A(I) će izazvati poruku SORRY. PRINT MEM daje neki negativan broj. Problem se rešava kucanjem naredbe ARR$(-1), posle koje sve postaje normalno.

Svi ovi bagovi bi, jasno, mogli da se isprave odgovarajućim promenama ROM-a, ali ove promene verovatno neće nikada biti izvršene. Odgovor na pitanje zašto? je sasvim jednostavan: ako promenimo ROM adrese svih sistemskih potprograma (pa i onih koji su pomenuti u ovom poglavlju) će se promeniti, što znači da programi neće biti kompatibilni sa obe verzije ROM-a. Tako ćemo najverovatnije ostati kod 28 verzije ROM-a koju smo proglasili konačnom (PRINT BYTE (55) će vas uveriti da vaš računar ima 28. verziju ROM-a).

l uputstvo za upotrebu "galaksije" nije imuno na bagove: u mapi sistemskih promenijivih na strani 26 postoje dve sistemske promenljive na adresi &2BB1, ali će svakome iole pažljivom čitaocu biti jasno da registar za REPT zauzima ćeliju &2BB4. Osim toga, "horizontalna pozicija teksta" zaista ima inicijalnu vrednost 11 ali dekadno a ne heksadekadno. Za autora ovoga teksta je najbolnije da kaže da program sa dna strane 7 ima grešku i to ne štamparsku nego logičku: on dobro radi za vrednosti iz primera, ali čim bi se putovanje odužilo preko jednog časa... Obzirom da nam se čini da svaki programer početnik (baš tako) može da napiše ovakav program tako da radi ispravno, ovde ne dajemo novu verziju.

Time smo došli do kraja ovoga prilično opširnog poglavlja koje je posvećeno računaru "galaksija". Autor ovoga teksta duguje veliku zahvalnost Voji Antoniću, konstruktoru "galaksije", za pomoć pri izboru tema koje će biti obrađene, saradnju na pripremi primera upotrebe raznih tehnika i, posebno, za sve podatke o ROM-u koje niko drugi nije ni mogao da zna. Zahvaljujući ponajviše ovim podacima, naša "galaksija" je postala jedan od vrlo retkih računara koji, kako rekosmo i u naslovu poglavlja, "nema tajni"!

 

horizontal rule

 

Kako se unose mašinski programi

U okviru poglavlja koje je posvećeno malim tajnama računara "galaksije" dajemo dosta primera koji treba da ilustruju opisivane tehnike. Neki od tih primera, međutim, mogu da budu interesantni i kao uslužni programi koje biste rado uneli u računar i koristili u raznim prilikama (ovde najpre mislimo na programe RSAVE i TIME). Za to unošenje će poslužiti hex-dump svakog od tih programa i kratka rutina UTM koju ovde donosimo.

Mašinski program se u računar unosi na jedan od tri načina: pomoću UTM-a ili nekog sličnog programa, pomoću asemblera ili, kao krajnja solucija, preko asemblera nekog drugog računara koji je povezan sa "galaksijom". Kada ćemo koristiti koju od ovih solucija? Drugi računar je neobično zgodan ako pišemo komplikovaniji sistemski program (npr. ROM 2) koji će, u toku razvoja, više puta "krahirati". Posle svakog ovakvog "kraha", moraćemo da brišemo "galaksijinu" memoriju pri čemu izvorni, asemblerski, program u memoriji drugog računara neće biti izgubljen. Korišćenje asembler programa je zgodno kada pišemo igre ili neke druge uslužne programe i, naročito, kada posedujemo ovakav asembler. Program UTM ostaje kao rešenje neobično zgodno za unošenje gotovih programa koji su objavljeni u nekom časopisu i čije nas modifikacije ne zanimaju - želimo samo da otkucamo program i da ga koristimo.

Šta je UTM?

UTM je Ultra Tiny Monitor i dat je na slici 1. Kada pogledate koliko je dugačak, verovatno ćete pomisliti da ni ono "Ultra Tiny" u nazivu ne ilustruje dovoljno njegove slabosti u odnosu na prave monitor programe. Ali nije baš tako - videćeta da je UTM, za primene za koje je napisan, sasvim dovoljan. On omogućava unošenje programa u proizvoljni segment memorije, testiranje i promenu sadržaja proizvoljne memorijske lokacije i kontrolu sadržaja većih segmenata memorije. Evo uputstva za njegovu upotrebu.

Po stanovanju programa, "galaksija" ispisuje njegovo zaglavlje i upitnik. Kada god se pojavi upitnik možete da izaberete jednu od sledećih opcija:

Ukoliko otkucavate neki četvorocifren heksadekadni broj, kome ovog puta na sme da prethodi oznaka &, računar će prikazati sadržaj memorijske ćelije čija je adresa data tim brojem i proglasiti tu adresu za "tekuću".

Ukoliko otkucavate neki jedno- ili dvocifreni heksadekadni broj, kome ne sme da prethodi oznaka &, računar će taj broj smestiti u memorijsku ćeliju čija je adresa u tom momentu označena kao "tekuća". Zatim će automatski biti izvršena sledeća opcija.

Ukoliko jednostavno pritisnete RET odnosno ENTER, tekuća vrednost će biti povećana za jedan, pa će na ekranu biti prikazan sadržaj te memorijske ćelije koju zatim slobodno možete da menjate primenom opcije 2.

Kako da otkucate neki mašinski program pomoću UTM-a? Startujte UTM sa RUN (ne smete da zaboravite da, ukoliko mašinski program počinje od &2C3A, treba da pomerite UTM kucajući NEW NNNN pre kucanja UTM-a ili NEW NNNN OLD NNNN WORD &2C3S, NNNN+&2E3E pre njegovog unošenja sa kasete: NNNN je bar za jedan veći broj od dužine mašinskog programa, pri čemu treba zaboraviti da NNNN mora da bude dekadni broj), otkucajte početnu adresu programa a zatim, bajt po bajt, sadržaje svake memorijske lokacije. Koristite stalno heksadekadni sistem, koji je uobičajen kod programera. Posle unošenja poslednjeg bajta, možete da pritisnete BRK i tako prekinete rad ili ponovite početnu adresu i, uzastopnim pritiscima tastera ENTER, proverite sadržaj memorije koji treba da odgovara hex-dampu. Ukoliko pronađete grešku, lako ćete je ispraviti kucanjem novog sadržaja.

5 CALL 240
10 ARR$(4)
20 Y$=""
30 I=0
40 X$=""
50 H=I:CALL 160
60 PRINT "'";
70 H=BYTE(I):CALL 160
80 PRINT "     ";
90 INPUT X$
100 IF EQ X$,Y$ I=I+1:GOTO 50
110 IF (BYTE(PTR X$+l)=0)+(BYTE(PTR X$+2)=0) CALL 130:BYTE I,H:X$="":GOTO 100
120 CALL 130: I =H : GOTO 40
130 X$(0)="&"+X$
140 H=VAL(PTR X$(0))
150 RETURN
160 FOR K=4 TO 1 STEP -l
170 G=H
180 H=INT(H/16)
199 G=G-16*H
200 IF G<<10 X$<<K>>=CHR$<<G+48>>: ELSE X$(K)=CHR$(G+55)
210 NEXT K
220 FOR K=1 TO 4: PRINT X$(K);:NEXT K
230 RETURN
240 HOME
250 PRINT AT 480; "GALAKSIJA"
260 PRINT
270 PRINT "UTM VERSION 1.0"
288 PRINT
290 RETURN
 

horizontal rule

 

Važne adrese Galaksijinog operativnog sistema

 

Funkcija Call &
   
Aritmetika pokretnog zareza  
Izraz adresiran sa DE (IX) AB2

HL (IX)

ABC

(HL) (IX)

A45

(IX) HL

A6D

(IX) (HL)

73B

Izraz u zagradi adresiran sa DE (IX)

781

Sabiranje

B32

Oduzimanje

B1E

Množenje

AE6

Deljenje

AF7

Poređenje elemenata na vrhu aritm. steka

B10

RND (IX)

C8F

Adrese bejzik interpretatora

Izraz adresiran sa DE (celobrojno) HL  008, RST &8
zraz u zagradi adresiran sa DE HL  A6A
Preskakanje blankova adresiranih sa DE 104
Ako DE adresira zarez, kao RST &8 inače WHAT? 5
EY(O) uz podršku BRK, DEL i LIST CF5
Karakter iz A na ekran uz &D, &C i &1D 20; RST &320
Štampanje HL na ekranu kao ASCII niz 8FB
Štampanje alfanumerika adresiranog sa DE, terminator je 00 (nema novog reda) ili &D (izdaje se novi red) 937
Lociraj varijablu čije ime pokazuje DE. U HL se smešta PTR; ako je C setovan nije varijabla; ako je Z setovan numerička varijabla a u protivnom alfanumerička 125
Prepoznavanje sledeće naredbe 30, RST &30

Stanje aritmetičkog steka    

8F6

Slobodna memorija (od ARR$ do bejzika) HL 183
Snimanje bajta na kasetu. Bajt je u A. E68
Bajt sa kasete u C EDD

 

horizontal rule

 

Slika 1

10 ! CLEAR
20 ! DAJE VREDNOST NULA
30 ! NUMERIČKIM PROMENLJIVIMA
40 ! A-Z
50 !
60 !
70 !
80 <
90 ORG &3000
100 OPT 3
110 LINK EQU &2BA9
120 KOMANDA EQU &75B
130 PREPOZNAJ EQU &39A
140 DFILE EQU &2800
150 NUMVAR EQU &2A00
160 LD A,&C3 ! &C3 = JUMP
170 LD (LINK), A
180 LD HL, PROG
190 LD (LINK+1),HL
200 RET
210 PROG
220 EX (SP),HL
230 PUSH DE
240 LD DE,KOMANDA
250 RST &10
260 POP DE
270 JR Z,NAREDBA
280 EX (SP),HL
290 RET
300 NAREDBA
310 LD HL,TABLICA-1
320 JP PREPOZNAJ
330 TABLICA
340 TEXT "CLEAR"
350 BYTE CLEAR>8+&80
360 BYTE CLEAR#&FF
370 BYTE BACK>8+&80
380 BYTE BACK#&FF
390 BACK
400 RET
410 CLEAR
420 POP AF
430 PUSH DE
440 LD DE,NUMVAR
450 CYCLE
460 LD HL,ZERO
470 LD BC,4
480 LDIR
490 LD A,E
500 CP &68
510 JR NZ,CYCLE
520 POP DE
530 RST &30
540 ZERO
550 WORD &0018
560 WORD &4000
570 >
580 A=USR(&3000)

Slika 2

10 !
20 ! DISPLAY (PPP)
30 ! DAJE ASCII KOD KARAKTERA
40 ! U VIDEO MEMORIJI 
50 ! (PREMA MAPI)
70 !
80 <
90 ORQ &3000
100 OPT 3
110 LINK EQU &2BA9
120 FUNKC EQU &777
130 PREPOZNAJ EQU &39A
140 DFILE EQU &2800
150 KRAJHL EQU &ABC
160 IZRAZ EQU &A6A
170 LD A,&C3 ! &C3 - JUMP
180 LD (LINK),A
190 LD HL,PROG
200 LD (LINK+1) ,HL
210 RET
220 PROG
230 EX (SP),HL
240 PUSH DE
250 LD DE,FUNKC
260 RST &10 ! POREDI HL I DE
270 POP DE
280 JR Z,NAREDBA
290 EX (SP),HL
300 RET
310 NAREDBA
320 LD HL,TABLICA-l
330 JP PREPOZNAJ
340 TABLICA
350 TEXT "DISPLAY"
360 BYTE DISPLAY#&FF00>8+&80
370 BYTE DISPLAY#&FF
380 BYTE NEGDE#&FF00>8+&80
390 BYTE NEGDE#&FF
400 NEGDE
410 RET
420 DISPLAY
430 POP AF
440 CALL IZRAZ
450 PUSH DE
460 LD DE,DFILE
470 ADD HL,DE
480 POP DE
490 LD A,(HL)
500 LD L,A
510 LD H,0
520 JP KRAJHL
530 >

Slika 3

10 !
20 ! REC (RECIPROČNA VREDNOST)
30 !
40 ! ILUSTRACIJA FLOATING POINT
50 ! ARITMETIKE
60 !
70 <
80 ORG &3000
90 OPT 3
100 LINK EQU &2BA9
110 FUNKC EQU &777
120 PREPOZNAJ EQU &39A
130 NUMIX EQU &A45
140 IZUIX EQU &781
150 DELI EQU &AF7
160 LD A,&C3 ! &C3 = JUMP
170 LD (LINK), A
180 LD HL, PROG
190 LD (LINK+1), HL
200 RET
210 PROG
220 EX (SP), HL
230 PUSH DE
240 LD DE,FUNKC
250 RST &10
260 POP DE
270 JR Z,NAREDBA
280 EX (SP),HL
290 RET
300 NAREDBA
310 LD HL,TABLICA-l
320 JP PREPOZNAJ
330 TABLICA
340 TEXT "REC"
350 BYTE REC>8+&80
360 BYTE REC#&FF
370 BYTE NEGDE>8+&80
380 BYTE NEGDE#&FF
390 NEGDE
400 RET
410 REC
420 POP AF.
430 LD HL,JEDAN
440 CALL NUMIX
450 CALL IZUIX
460 CALL DELI
470 RET
480 JEDAN
490 BYTE 0 ! BROJ 1
500 BYTE 0
510 BYTE &80
520 BYTE 0
530 >
540 A=USR(&3000)

Slika 4

10 !
20 ! USPORENO ISPISIVANJE
30 !
40 ! ILUSTRACIJA LINKA
50 ! ZA VIDEO
60 !
70 !
80 <
90 ORG &2C3A
100 OPT 3
110 LINK EQU &2BAC
120 LD A,&C3 ! &C3 = JUMP
130 LD (LINK),A
140 LD HL,PROG
150 LD (LINK+1),HL
160 RET
170 PROG
180 PUSH AF
190 LD HL,&l000
200 DELAY
210 DEC HL
220 LD A,H
230 CP 0
240 JR NZ, DELAY
250 POP AF
260 RET
270 >
2B0 A=USR(&2C3A)

Slika 5

10 !
20 ! ZAMENA READY
30 ! ILUSTRACIJA LINKA
40 ! ZA VIDEO
50 !
60 !
70 !
80 <
90 ORG &2C3A
100 OPT 3
110 LINK EQU &2BAC
120 LD A,&C3 ! &C3=JUMP
130 LD (LINK),A
140 LD HL,PROG
150 LD (LINK+1),HL
160 RET
170 PROG
180 PUSH AF
190 CP 64
200 JR Z,MIPRO
210 LD A,(RADNI)
220 CP 0
230 JR Z,NOPRINT
240 DEC A
250 LD (RADNI),A
260 BACK
270 POP AF
280 POP HL
290 POP HL
300 RET
310 NOPRINT
320 POP AF
330 RET
340 MIPRO
350 LD A,6
360 LD (RADNI),A
370 PUSH DE
380 LD HL,PORUKA
390 LD DE,(&2A68)
400 LD BC,11
410 LDIR
420 LD (&2A68),DE
430 POP DE
440 JR BACK
450 PORUKA
460 BYTE 64
470 BYTE 39
480 TEXT "GALAKSIJA"
490 RADNI WORD 0000
500 >
510 A=USR(&2C3A)

Slika 6

10 !
20 ! PERMANENTNI SAT
30 !
40 ! ILUSTRACIJA LINKA U
50 ! INTERAPTU
60!
70 <
80 ORG &2C3A
90 OPT 3
100 DFILE EQU &2800
110 INTER EQU &FD
120 Y EQU &2A80
130 HALT
140 LD IY,ENTRY
150 RET
160 ENTRY
170 LD A,(&2BB0)
180 CP 0
190 JR NZ,BACK
200 LD A,(Y+2)
210 CP ":"
220 JR NZ,BACK
230 LD A,(Y+5)
240 CP "."
250 BACK
260 JP NZ,INTER
270 LD DE,DFILE+20
280 LD HL,Y
290 DISP
300 LD A,(HL)
310 AND A
320 JP Z,INTER
330 LD (DE),A
340 INC HL
350 INC DE
360 JR DISP
370 >
380 A=USR(&2C3A)

Slika 7

5 ! RSAVE
6 ! RELOCIRANO SNIMANJE
10 <
20 ORG &3F00
30 OPT 3
40 LINK EQU &2BA9
50 Z6B3 EQU &75B
60 X343 EQU &39A
70 DFILE EQU &2800
80 NUMVAR EQU &2A00
90 BVTEA EQU &E68
100 WORDHL EQU &E63
110 ZAREZ EQU 5
120 LD A, &C3 ! &C3 = JUMP
130 LD (LINK),A
140 LD HL,PROG
150 LD (LINK+1),HL
160 RET
170 PROG
180 EX (SP),HL
190 PUSH DE
200 LD DE,Z6B3
210 RST &10
220 POP DE
230 JR Z,NAREDBA
240 EX (SP),HL
250 RET
260 NAREDBA
270 LD HL,TABLICA-l
280 JP X343
290 TABLICA
300 TEXT "RSAVE"
310 BYTE RSUB>8+&80
320 BYTE RSUB#&FF
330 BVTE BACK>B+&80
340 BVTE BACK#&FF
350 BACK
360 RET
370 RSUB
380 POP AF
390 LD HL,&66
400 PUSH HL
410 RST 8
420 PUSH HL
430 CALL ZAREZ
440 INC HL
450 PUSH HL
460 CALL ZAREZ
470 LD B,H
480 LD C,L
490 POP HL
500 POP DE
510 PUSH BC
520 LD B,&60
530 DI
540 LEADER
550 XOR A
560 CALL BYTEA
570 DJNZ LEADER
580 LD A,&A5
590 CALL BYTEA
600 POP BC
610 PUSH HL
620 PUSH BC
630 LD H,D
640 LD L,E
650 ADD HL,BC
660 LD B,&A5
670 CALL WORDHL
680 LD A,B
690 POP BC
700 POP HL
710 PUSH HL
720 ADD HL,BC
730 LD B,A
740 CALL WORDHL
750 POP HL
760 JP &E57
770 >
780 A=USR(&3F00)

Slika 8

&3BAC: 00 00 00 00 00 00 00 00
&3BB4: 00 00 21 FF 29 36 20 2B
&3BBC: CB 5C 20 F9 21 CD 2B 11
&3BC4: E7 28 01 11 00 ED B0 18
&3BCC: FE 41 55 54 4F 53 54 41
&3BD4: 52 54 20 50 52 4F 47 52
&3BDC: 41 4D
Napomena: Ovaj tekst je unesen sa štampanog teksta iz "Računara 2" uz korišćenje OCR programa. Molim Vas da mi ukažete na greške koje primetite.