ZX81 bez tajni

ZX81, svakako, spada u računare kod kojih je otkrivanje skrivenih karakteristika imperativ za svakog ozbiljnog korisnika. Razloge nije previše teško pogoditi: mogućnosti ovog računara su relativno male, a postoje mnogobrojne dobre osobine koje su mu nepoznate. Na svu sreću, konstruktori ZX81 su u njegov operativni sistem uključili naredbe PEEK, POKE i USR, koje otvaraju vrata programiranja na mašinskom jeziku i time omogućavaju korisniku da zaobiđe operativni sistem koji su konstruktori zamislili.

Ako malo eksperimentišete sa naredbom POKE, videćete da se za većinu adresa ne primećuju nikakve reakcije, ali da smeštanje brojeva na adrese 16384 - 16508 izaziva raznorazne posledice. U ovom području se, naime, nalaze takozvane "sistemske promenljive", odnosno brojevi koji govore računaru kakav se program nalazi u memoriji, koliko memorije ima na raspolaganju, koliko redova ekrana je ispunjeno, koja je greška nastupila i slično. Bezmalo, svaka sitemska promenljiva zauzima dva bajta; u tom prostoru su smeštena dva broja koja odvojeno posmatrano nemaju smisla, ali koji mogu da se ujedine u jedan značajan broj.

Spuštanje i podizanje RAMTOP-a

Uzmimo, na primer, sistemsku promenljivu nazvanu RAMTOP (ime RAMTOP - vrh, kraj memorije - je samo figurativno i za ZX81 ne znači ništa; PRINT RAMTOP neće na ekranu prikazati vrednost neke sitemske promenljive) koja se nalazi u ćelijama memorije 16388 i 16389. Da bismo pronikli u njen sadržaj, otkucaćemo PRINT PEEK 16388+256*PEEK 16389 i pritisnuti uobičajeno NEWLINE. Ukoliko naš ZX81 nema proširenu memoriju, na ekranu će se ukazati broj 17408 - to je adresa poslednjeg postojećeg bajta u memoriji. Na prvi pogled izgleda da nema nikakve potrebe za ovom sistemskom promenljivom s obzirom na to da računar uvek ima konstantnu memoriju, ali nije tako: kada uključimo ZX81, on najpre proverava da li je priključen modul od 16 (ili možda 32 ili čak 64) kilobajta i rezultat te provere ubeležava u sistemsku promenljivu RAMTOP. Kada kasnije zahtevamo od računara da smesti neki program u memoriju, on neće morati da proverava da li je ona dovoljno velika za njegovo smeštanje - jednostavno će pročitati sadržaj RAMTOP-a.

Nema nikakve prepreke da pomoću POKE promenimo sadržaj RAMTOP-a - otkucajmo POKE 16388, 255 NEWLINE POKE 16389, 255 NEWLINE i računar će imati utisak da je priključeno 56 kilobajta memorije. Znači li to da ne moramo da trošimo novac na dodatne memorijske module? Naravno, ne znači. Mi jesmo naveli računar da poveruje da ima više memorije ali time nismo stvorili fizičke jedinice koje je podržavaju - pokušaj da smestimo nešto u nju može da izazove krah našeg računara. Zbog svega toga nema mnogo smisla "podizati" RAMTOP, ali njegovo spuštanje može da se pokaže vrlo korisnim.

Spuštanjem RAMTOP-a smo stvorili utisak da radimo sa manje memorije. Zar je to dobro? Odgovor je, začudo, potvrdan: ponekad može da bude korisno da se odreknemo dela memorije. Najbanalniji primer je simuliranje osnovne verzije ZX81. Ukoliko, na primer, želimo na isprobamo neki program koji radi na ZX81 sa 1 K (ili da se uverimo da će neki program koji smo pisali moći da upotrebe i oni koji nemaju proširenje memorije) ne moramo da isključujemo računar i vadimo modul - dovoljno je da otkucamo POKE 16388, O NEWLINE POKE 16389, 68 NEWLINE NEW NEWLINE (pažnja - poslednja naredba će obrisati čitavu memoriju računara, pa program koji se u njoj nalazi treba prethodno da snimite na kasetu) PRINT USR 1040 NEWLINE. Vaš ZX81 je time pretvoren u računar sa samo 1 K memorije!

Trikovi sa vrhom memorije

Sledeća upotreba sistemske promenljive RAMTOP je nešto manje očigledna. ZX81, naime, ima ružnu osobinu da, kada se otkuca komanda SAVE, snima na traku sadržaj čitave memorije. Ukoliko je program koji se nalazi u njoj kratak, snimaćemo gomilu praznih bajtova. Što je još gore, kada pokušamo da učitamo neki program sa kasete, računar insistira na tome da upiše i sadržaje svih promenljivih i nizova. Ako, dakle, imamo podatke koje želimo da prosledimo od jednog programa do drugog, moraćemo manuelno da ih prepišemo (ili, ako ga posedujemo, upotrebimo printer) i ponovo otkucamo kada drugi program bude u memoriji. Zar tu ne postoji neki bolji metod?

Naravno, postoji. Računar, kao što smo rekli, posle SAVE snima na traku čitavu memoriju. Ali, kako on zna kolika je ta "čitava memorija"? Razume se, tako što konsultuje promenljivu RAMTOP! Ako u RAMTOP unesemo neki broj manji od realnog, svi podaci koji se nalaze na kraju memorije biće zaštićeni od brisanja. Ukoliko, veštom upotrebom PEEK i POKE, u taj prostor prenesemo sadržaj nekog niza ili matrice, učitamo nov program i obavimo "inverznu transformaciju", izbeći ćemo prepisivanje i prekucavanje podataka i tako ispraviti jedan od ozbiljnih propusta konstruktora ZX81.

Kao primer upotrebe RAMTOP-a dajemo program koji vam omogućava da u memoriji držite nekoliko sadržaja ekrana i razmenjujete ih prema potrebi. Data su, zapravo, dva programa: jedan je pisan na bejziku ali nije namenjen praktičnoj upotrebi - previše je spor. Ipak, on će početnicima pružiti šansu da shvate kako radi jedan mašinski program, koji može da bude koristan potprogram za mnoge igre u kojima je potrebna animacija ekrana.

Pre nego što startujete bejzik program, morate da promenite sadržaj RAMTOP-a tako da se na vrhu memorije nađe dovoljno prostora za jedan ili više sadržaja ekrana. Da, na primer, smestite dva sadržaja ekrana, potrebno vam je najmanje 793*2=1586 bajta. Ukoliko, posle uključivanja kompjutera, otkucate POKE 16389,121 NEWLINE NEW NEWLINE (ovo NEW je uvek potrebno da bi ZX81 reinicijalizovao stek na novu poziciju; ako ne znate šta je stek, zanemarite ovu napomenu s obzirom na to da sa aspekta korisnika nije mnogo bitna). Zatim unesite bejzik program, popunite ekran nekim rečima i brojevima i startuje program. Demonstracija je, čini nam se, prilično efektna.

Mašinski potprogram možda nije lako analizirati, ali početnici ovaj posao mogu da ostave i za "srećnija vremena". I samo unošenje ovog program u prvu REM liniju (???) predstavlja svojevrsnu zagonetku. No, ne budimo nestrpljivi: na nekoj od sledećih strana ćemo upoznati način na koji se mašinski programi unose, pa ćemo iskoristiti i ovaj. Oni koji bolje poznaju mašinsko programiranje će uneti program u prvu REM liniju od adrese 16516, smestiti na adrese 16514 i 16515 broj koji odgovara oznaci ekrana koji smeštaju ili pozivaju (0,0 za prvi ekran, 25,3 za drugi i tako dalje) i smestiti ekran u memoriju sa RAND USR 16516, a povratiti ga sa RAND USR 16534.

Sve sistemske promenljive

Čitava priča nas je prilično udaljila od područja sistemskih promenljivih koje proučavamo. Čini nam se da će većini čitalaca biti od koristi da se vratimo na početak i izložimo mogućnosti upotrebe nekih drugih sistemskih varijabli (reč varijabla se u programerskom žargonu koristi daleko češće od lepe domaće reči promenljiva iz nepoznatih razloga). Počećemo od samog početka - promenljive ERR NR koja se nalazi na lokaciji 16384. Kao što joj i ime govori, u okviru ove promenljive računar smešta kod greške koja je nastupila. Ukoliko, na primer, vaš program završite sa POKE 16384,29, računar će prijaviti inače nepostojeću U error koja, prema časopisu "Sinclair User", može da označi grešku korisnika (User error). Isti časopis predlaže da pokušate da u ovu sistemsku promenljivu smestite brojeve 43, 70,72, 73, 74, 75, 81, 82 i 89. Zašto ih ne poslušate?

Sistemska promenljiva PPC se nalazi na lokacijama 16391 i 16392. U okviru nje računar smešta linijski broj bejzik naredbe koja se trenutno izvršava. Ukoliko promenite ovaj broj, ne izlažete se prevelikoj opasnosti s obzirom na to da se on koristi samo kada računar završava sa radom (tada se, na primer, na ekranu pojavi 0/123, što znači da se izvršavanje programa završilo linijom 123 pa se u promenljivoj PPC nalazio isti broj). Dakle, ova sistemska promenljiva može jedino da se iskoristi za ispisivanje neobičnih poruka na kraju programa.

Sistemska promenljiva DF-CC saopštava korisniku mesto na kome će štampati sledeća naredba PRINT. Kao i obično, sistemska promenljiva se sastoji od dve memorijske lokacije koje treba ujediniti u jedan broj primenom naredbe LET A=PEEK 16398+256*PEEK 16399. Posle toga, promenljiva A sadrži adresu koja može prilično korisno da se upotrebi. Otkucajmo, na primer, POKE A, 123 i na odgovarajućem mestu ekrana će se pojaviti karakter čiji je kod 123. Ništa naročito, reći ćete, to može da se postigne i naredbom CHR$. Pa dobro, otkucajmo LET B=PEEK A i promenljiva B će sadržati kod karaktera koji se već nalazi tamo gde će sledeća PRINT naredba ciljati. Taj broj možemo da ispitamo i tako otkrijemo da li je, na primer, svemirski brod u nekoj igri izašao iz dopuštenog dela svemira koji je ograđen debelim linijama.

Sistemske promenljive VARS (16400-16401) i E-LINE (16404-16405) saopštavaju adrese početka i kraja dela memorije koji je namenjen smeštanju promenljivih koje se koriste u bejzik programu. S obzirom na to da prenošenje argumenata iz bejzik programa u mašinski može da se ostvari na daleko jednostavniji način, ove promenljive nisu previše često u upotrebi.

Na lokaciji 16418 krije se sistemska promenljiva DF-SZ koju početnici "obožavaju". Ona saopštava računaru koliko je linija na kraju ekrana rezervisano za naredbe koje korisnik kuca. Tamo se normalno nalazi broj 2 ali, uz odrđen rizik da dođe do kraha, ova promenljiva može da dobije vrednost 1, čime se efektivno dobija još jedan red. Sa druge strane, ukoliko nam nedostaje memorija možemo da damo DF-SZ vrednost veću od 2, čime se korisno upotrebljeni deo ekrana smanjuje, uz odgovarajuću uštedu memorijskog prostora.

Sistemsku promenljivu NXTLIN (16425-16426) koriste mahom bolji programeri. Ovde se nalazi apsolutna adresa početka sledeće BASIC naredbe koja može da bude neobično korisna za startovanje mašinskih programa. Ukoliko se, na primer, u REM liniji broj 101 nalazi neki mašinski program, on može da bude startovan iz linije 100 primenom naredbe LET A=USR (PEEK 16425+256*PEEK 16426+5) (broj 5 potiče otuda što linijski broj i druge informacije koje sadrži početak programske linije 101 zauzimaju čitavih pet bajtova).

Završimo ovu kratku priču o sistemskim promenljivim adresama onih koje nemaju nikakvu funkciju: 16417, 16507 i 16508. Ukoliko ne posedujete printer ili ovaj nije priključen, slobodno koristite sistemske varijable na adresama 16444-16476. Ovako dobijenih 35 bajtova možete da upotrebite za smeštanje poadataka za koje nemate gde drugde da rezervišete prostor.

Gde smestiti mašinac

Upoznali smo sistemske promenljive, pa možemo da se orijentišemo na mašinske programe. Prvi problem je gde da ih smestimo. S obzirom na izloženi, učinilo bi se da je pravo mesto za ove programe iznad RAMTOP-a - tamo ih neće ometati niti pomerati nikakve izmene bejzik programa, pa čak ni naredba NEW. No, postoje i loše strane lokacija iznad RAMTOP-a - ne mogu da budu snimljene na kasetu sa matičnim bejzik programom. Ostaje nam, dakle, da ih smestimo iz bejzika? Ni to nije naročito dobro jer bi svaka promena bejzik programa (a promene su česte, pogotovo u toku sastavljanja i testiranja program) pomerila mašinski program i tako učinila da on prestane da radi (većina JP naredbi, na primer, sadrži apsolutne adrese, što podrazumeva da program neće biti pomeran). Ostaje nam samo da mašinski program smestimo unutar bejzika, nadajući se da tamo neće nikome smetati. Ali, kako onda da ga "sakrijemo" tako da ga bejzik interpretatora ne primeti, što bi izazvalo prijavljivanje greške? Jednostavno, smestićemo mašinski program u prvu REM naredbu i to pomoću programa koji je poznat kao "Machine Code Loader" ili program za unošenje mašinskih programa. Upotreba programa je sasvim jednostavna: otkucaćemo najpre REM naredbu koju prati bar onoliko jednakih slova koliko će mašinski program imati instrukcija, a zatim RUN. Unosićemo mašinski program bajt po bajt, koristeći heksadekadni sistem (heksadekadni sistem je nešto što ne bi trebalo da predstavlja nepoznanicu za one koji čitaju ovo poglavlje). Po unošenju mašinskog programa možemo i da ga startujemo otkucavši RAND USR 16514.

Svaki čitalac ovih redova je verovatno poželeo da isproba novi program za unošenje mašinskih programa. Zašto da ne? Sledeći program koji objavljujemo će u mnogome unaprediti tastaturu vašeg računara uvodeći funkciju poznatu pod imenom autorepeat! To, praktično, znači da će duži pritisak na neki taster naterati računar da na ekranu proizvede efekat kao da je taster bio pritisnut više puta što, na primer, može da bude korisno za lako kreiranje REM naredbi za unošenje mašinskih programa koje ćete sami sastaviti. Kada unesete sledeći program, otkucajte uobičajeno RAND USR 16514 i u gornjem levom uglu ekrana će se pojaviti kvadrat koji će treperiti sve dok je autorepeat aktivan. Pritisnite, na primer, taster A i posmatrajte ekran. ZX81, izgleda, ume svašta; treba mu to samo dobro objasniti.

Zaštita i kako je skinuti

Sledeći redovi će biti posvećeni radu sa kasetofonom ili, preciznije rečeno, zaštićenim programima. Skuplji kompjuteri najčešće imaju manje ili više efikasne metode zaštite programa od neovlašćenog prepisivanja ili, kako se to u žargonu kaže, "piratovanja". ZX81, doduše, nema posebne naredbe kojima se ova zaštita ostvaruje ali od pomoći može da bude jednostavno smeštanje naredbe SAVE u program. Vratimo se, na primer, na prethodni program za automatsko ponavljanje i zamislimo da želimo da ga damo nekome ko neće smeti dalje da ga presnimava. Unećemo ovaj program u prvu REM liniju, dodati program

2 SAVE "REPEAT"
3 RAND USR 16514

i otkucati RUN. Računar će zanemariti REM liniju, naići na SAVE i snimiti čitav program na kasetu. Kada onaj kome ste dali program unese kasetu i otkuca LOAD"", računar će učitati program i primetiti po nekim informacijama koje su zapisane uz program da se SAVE koje ga je snimilo nalazilo u programu. ZX81 je programiran tako da automatski nastavi izvršavanje ovakvog programa i, po nailasku na naredbu broj 3, "skoči" na mašinski potprogram koji se nalazi u REM liniji. U našem primeru mašinski program će trenutak docnije prestati sa radom, pa će njegov vlasnik bez problema moći da ga ponovo snimi na isti način. No, šta da se u mašinskom programu nije nalazila ni jedna HLT odnosno RET naredba? On bi se neprekidno izvršavao, ali njegov korisnik ne bi mogao da ga zaustavi da bi ga presnimio. Lukavo, zar ne?

Svima nam je poznato da kod nas, i pored ovakve zaštite, ima dosta preprodavaca koji na neki "tajanstven" način uspevaju da prekopiraju i preprodaju programe. Kako im to uspeva? Neki poseduju mašinski program koji imitira naredbu LOAD i unosi program u memoriju bez njegovog startovanja. No, iskusnijim programerima je poznat daleko bolji trik: prebacimo računar u FAST mod i otkucajmo RAND USR (836). Očekujete da su uputstva tek počela? Greška - upravo su završena. Računar je "prevaren" tako da učita mašinski i bejzik program i ne stratuje ih! Jedno SAVE će ga zatim snimiti na neku drugu traku.

Simulacija funkcije VERIFY

Još jedan trik vezan za snimanje na kasetu je simulacija funkcije VERIFY. Ova funkcija, kao što je vlasnicima Spectruma, BBC, TRS 80 i drugih kompjutera poznato, služi da se proveri da li je upravo snimljeni program korektno zapisan. ZX81, na žalost, nije opremljen ovom funkcijom, što znači da postoji određena mogućnost da program koji ste čitavog dana radili bude nekorektno snimljen i tako zanavek izgubljen. Moguće je sastaviti mašinski program koji bi verificirao ono što je snimljeno (nevolja je samo u tome što bi i sam program za verifikaciju morao da se snima zajedno sa svakim drugim programom, jer ZX81 snima čitavu memoriju), ali postoji i bolji (na žalost i manje siguran) trik. Kada snimite program, premotajte kasetu na njegov početak i otkucajte LOAD "ime programa", pa pritisnite NEWLINE i startujte kasetofon. Ako se posle izvesnog vremena pojavi poruka 0/0, postoji značajna mogućnost da je računar korektno učitao i snimio program. Na taj način je provereno da li je ime programa korektno prepoznato, a za slučaj da nije, nikakav program nije učitan, pa možete da pokušate da ponovo snimite vaš program (on se i dalje nalazi u memoriji) ne neku drugu kasetu. Nedostatak metoda je u tome što postoji mogućnost da je traka bila fizički oštećena i da je, premda je početak korektno upisan, nastupila greška u sredini programa. Dovoljno je da jedan bajt ne odgovara istini i program će verovatno propasti! 

Spectrum i njegove neobičnosti Moja home strana