Spectrum

Kategória: Elektronika.

Áttekintés

A '80-as évek ikonikus személyi számítógépei a Commodore 64, a ZX Spectrum és az Atari voltak. Nekem a '90-es évek elején volt szerencsém találkozni közelebbről is a ZX Spectrummal, azon tanultam meg programozni, és lényegében ez alapozta meg későbbi karrieremet.

The Spectrum

Megdobbantotta a szívemet az, amikor 2024-ben szembe jött egy reklám: a Retro Games kiadja a régi számítógépek retró változatait, többek között a ZX Spectrumot is, The Spectrum néven! Ráadásul elérhető áron, kb. 100 Euróért. Számos forgalmazója van.

A ZX Spectrum igazi különlegessége a gumi billentyűzet, ami azóta is egyedülálló. Mai szemmel nézve nem is túl praktikus, de mindenképp különleges, és szép élmények kapcsolódnak hozzá: az első programozási sikerek.

A készülék így néz ki:

spectrum.jpg

(A kép forrása: https://mikeshouts.com/retro-games-ltd-the-spectrum-personal-computer/.)

Még meg van az eredeti ZX Spectrum is, de az ezer sebből vérzik:

  • A billentyűzet valójában nem strapabíró, könnyen tönkre megy, és nem cserélhető. Rengeteget volt a készülék szervizben, ahol egy ügyes kezű ember rendre megforrasztotta, de azt nem tudom megmondani, hogy most működne-e.
  • Ahhoz tévé kimenet volt; nem tudom, hogyan lehetne a mai képernyőkhöz csatlakoztatni.
  • A játékokat kazettáról olvastuk be, és a programokat oda mentettük, de kérdés, hogy sikerülne-e ezeket működésre bírni.

Szóval annak ellenére, hogy a készülék még valahol meg van, a retró változat megvásárlása mellett döntöttem. Ehhez nem kell kazetta, USB pen drive-ot tudunk csatlakoztatni. A monitor kimenete HDMI (amit időnként nem talál, újra kell indítani). USB-C töltője van. Összesen 4 USB partja van, ahova elvileg akár joystickot és egyéb eszközöket is tudunk csatlakoztatni, ezeket nem próbáltam.

Szóval tisztára modern 2024! Vagy mégse? Ezen az oldalon a lehetőségeket járom körbe.

A beépített játékok

A konzol 48 beépített játékkal érkezik. Meglepő, de 47 közülük számomra ismeretlen, az egyetlen ismert játék a Manic Miner, amit annak idején végigjátszottam. Mondjuk nem is elsősorban a játék miatt vettem, de ha már rajta van, miért ne próbálnám ki?

Nem is olyan egyszerű a használata! Eltartott egy darabig, mire rájöttem, hogy az 5-ös és 8-as billentyűkkel tudok lépkedni. Játék indítása: M.

manicminer.png

(A kép forrása: https://en.wikipedia.org/wiki/Manic_Miner.)

Mozogni a nyilakkal tudunk: balra 5, jobbra 8, az ugrás pedig vagy a felfele nyíl (7), vagy a SPACE. Amit nem is olyan egyszerű megnyomni. Eltartott egy darabig, mire sikerült végigjátszani az első pályát.

Visszatérni a főmenübe a konzol hátulján található HOME gomb megnyomásával lehet.

Játék betöltése USB-ről

Ez nem volt olyan egyszerű, mint gondoltam! Egy boot-olható, FAT32-vel formázott pen drive-ra van szükség. Egy 16 GB-os pen drive-ot formáztam FAT32-re. Letöltöttem a legfrissebb Ubuntut (https://ubuntu.com/download/desktop), a Rufus nevű alkalmazást (https://rufus.ie/), és ennek segítségével készítettem egy boot-olható Linux telepítőt.

A neten kerestem játékokat. Meglepő, hogy az ikonikus PacMan nincs a 48 játék között, így erre esett a választás. A következő oldalon találtam meg: https://worldofspectrum.org/archive/software/games/pac-man-atarisoft. Itt nem egyértelmű, hogy mit kell letölteni: a Files alatt a másodikat érdemes: "Atarisoft - (non-TZX) TAP tape image". (A "Atarisoft - Original release - Perfect TZX TAP tape" szimulálja a betöltést, azaz 5 percig nem történik semmi. Bár az igazi retró élményhez az is hozzátartozik.)

Ha esetleg elveszne, innen letölthető, ami az ottani másolata: PACMAN.TAP.

Ezt a fájlt másoljuk az USB meghajtó gyökerébe, majd a pen drive-ot dugjuk be a Spectrum baloldali USB meghajtójába. Betöltés: a játékok között meg kell keresni a pen drive ikont, majd betöltés (M), megjelenik a Media select, itt navigáljunk a nyilakkal (5, 6, 7, 8) a PACMAN-re, és ismét nyomjunk M-et, majd Enter. Játék indítása: S. Navigálni a nyilakkal tudunk.

pacman.png

(A kép forrása: https://en.wikipedia.org/wiki/Pac-Man.)

Hasznos weboldalak

Programozás BASIC-ben

Az igazán érdekes - számomra - a Spectrum programozása. Vajon mai (2025) fejjel, a mostani standardok birtokában mennyire használható, vagy máshonnan megközelítve: mennyire borzasztó a Spectrum programozása? Spoiler: NAGYON!

Az ikonikus barna színű könyvet sajnos nem adták ki újra, viszont letölthető több helyről is:

A The Spectrum felhasználói kézikönyve viszont azt a színvilágot tükrözi, és letölthető innen: https://retrogames.biz/support/thespectrum/manuals/

Csapjunk a lovak közé!

A programokat sajnos nem tudtam PC-n forráskódként megjeleníteni, így másoltam. Sajnos másolási hibák elvben előfordulhatnak.

Klasszikus módba lépés

Nem egyszerű megtalálni:

  • SPACE (Options)
  • Advance options: kétszer meg kell nyomni a 6-os gombon található lefele nyilat, majd M (Select)
  • Switch to classic mode: mint az előző lépésben

És máris megjelenik a ZX Spectrum prompt!

A billentyűzet használata

Az elmúlt évtizedekben a PC-k billentyűzetéhez és a modern programozáshoz szokott ember számára akkor is idegen a Spectrum billentyűzete, ha annak idején évekig ezt használta. Néhány hasznos tudnivaló:

  • Alapból egy K betű villog, ami a kulcsszóra (keyword) utal. Ekkor ha megnyomunk egy billentyűt, akkor a rajta, alul található kulcsszó jelenik meg, pl. P esetén a PRINT. (A Spectrum programozása során tehát a kulcsszavakat nem kell beírni, az automatikusan rajta van a billentyűzeten.) Ebben az állapotban számokat is be tudunk írni, ami az adott program adott sorát jelenti.
  • Az utasítás mindenképp kulcsszóval kezdődik. Ha beírtunk egy kulcsszót, akkor több kulcsszót már nem lehet beírni, és a prompt átvált villogó L-re, ami a betűre (letter) utal. Ekkor tudunk normál betűket beírni: alapból kisbetűket, ill. a CAPS SHIFT-tel nagybetűket.
  • A CAPS SHIFT + 2 megnyomásával C módba kerülünk, ami a csupa nagybetűs mód (CAPS LOCK). Ha még egyszer megnyomjuk, akkor visszatérünk L módba.
  • A billentyűn található piros feliratot a SYMBOL SHIFT segítségével tudjuk beírni, és ez tetszőleges módban működik.
  • A billentyű feletti zöld és alatti piros felirathoz E (extended) módba kell lépni, a CAPS SHIFT és a SYMBOL SHIFT (tehát a két shift) egyidejű lenyomásával. Ez egyetlen lenyomásig marad érvényben. Ebben az E módban alapból a billentyű feletti zöld szöveget tudjuk beírni, a SYMBOL SHIFT segítségével pedig a billentyű alatti pirosat.
  • A CAPS SHIFT és a 9 lenyomásával jutunk grafikus módba, aminek a segítségével a számjegyeken található grafikus jeleket tudjuk beírni.
  • Törölni a CAPS SHIFT és 0 együttes lenyomásával lehet.

Még van egy-két lehetőség, pl. színessel írni, de most azzal nem foglalkozunk.

Helló, világ!

Készítsük el első programunkat! A Spectrumban a sorokat sorszámozni kell. Konvencionálisan 10-esével sorszámozzuk, 10-zel kezdve, hogy ha be kell szúrni valamit, akkor legyen hely. És ez pont olyan rossz, mint amilyennek hangzik: túl sok kódot nem tudunk beszúrni, ha csak nem sorszámozzuk át egyesével a teljes programot. Mert alapból nem ad erre eszközt a Spectrum. Valójában talán ez az a legerősebb tulajdonsága, ami lehetetlenné teszi a komolyan vehető fejlesztést.

Írjuk be ezt:

10 PRINT "Hello, world!"

Segítség:

  • Nem kell begépelni azt, hogy PRINT, elég a P-t megnyomni.
  • Idézőjel: SYMBOL SHIFT + P
  • Felkiáltójel: SYMBOL SHIFT + 1
  • A végén ENTER-t kell ütnünk.

A program indítása:

RUN

Adott sor szerkesztése: a CAPS SHIFT + 6 és CAPS SHIFT + 7 segítségével tudunk a sorokon lépkedni (amit most nem tudunk megtenni, mert csak egyetlen sorunk van); egy > jel jelzi az aktuális sort. Az adott sor szerkesztése: CAPSH SHIFT + 1 (Edit). Ezen belül balra és jobbra a CAPS SHIFT + 5 ill. CAPS SHIFT + 8 kombinációkkal tudunk.

Ha új sorszámot adunk neki, akkor kétszer is szerepelni fog. Sort úgy tudunk törölni, hogy beírjuk a sorszámát és ENTER-t ütünk. Tehát átsorszámozni úgy tudjuk, hogy egyesével létrehozunk új sorokat, majd egyesével a régit kitöröljük. Tehát az átsorszámozás egy iszonyatosan lassú, nehézkes folyamat.

A programok mentése USB-re

A programok mentése nagyon nem egyszerű; ez a leírás segített a legtöbbet a megértésében: https://www.reddit.com/r/zxspectrum/comments/1h57f18/the_spectrum_and_saving_to_usb/.

Nulladik lépésben üresben létre kell hozni egy szalagot, azaz tape-et. Töröljük ki a programot (pl. CLEAR)

SAVE "fcstape"

Ezt írja ki:

Start tape, then press any key.

ENTER után ezt:

0 OK, 0:1

Ezt követően tegyük a következőt: HOME nyomógomb a hátulján -> Media select -> M -> fcstape_WR -> M -> ENTER

Most valósítsuk meg a programot:

10 PRINT "Hello, world!"

Mentsük le:

SAVE "hello"

Ez a korábban beállított tape-re mentette. A tapasztalatom szerint a név 10+ hosszú nem lehet, csak annál rövidebb. Nem találtam, hogy hogyan lehetne felülírni vagy törölni; egyből jól kell megírni, mert javításra nincs lehetőség.

Később ha be szeretnénk olvasni, akkor ki kell választani a Media select-ben a tape-et, és utána a következőképpen tudjuk beolvasni:

LOAD "hello"

Tapasztalatom szerint mentés után nem működik egyből; ekkor ki kell lépni a HOME-ba, Media select, majd vissza.

A programokat a szalag nevének újbóli megadásával lehet kilistázni:

LOAD "fcstape"

Ha kiadjuk egyesével a LOAD-ot üres stringgel, akkor kiírja a nevét és be is tölti a következőt:

LOAD ""

Számolás

Új programot a NEW segítségével tudunk létrehozni. Ez figyelmeztetés nélkül törli az előzőt, mintha újraindulna a gép.

Változókat a LET segítségével tudunk létrehozni. Típusok külön nincsenek. A változónév a tapasztalatom szerint bármi lehet

10 LET a=3
20 LET b=2
30 LET c=a+b
40 PRINT c

Az eredmény: 5.

Beolvasás

Kérjük be a felhasználó nevét, és köszönjünk neki!

A string típusú változók csak egybetűsek lehetnek, és $ jellel végződnek.

10 PRINT "What is your name?"
20 INPUT n$
30 PRINT "Hello, ";n$;"!"

A string konkatenálás a ; jellel történik.

Faktoriális

Számoljuk ki 5 faktoriálisát! Ehhez használnunk kell a FOR ciklust:

10 LET factorial=1
20 FOR i=2 TO 5
30 LET factorial=factorial*i
40 NEXT i
50 PRINT factorial

A FOR ciklusnál a TO a SYMBOL SHIFT + F, tehát nem szabad betűkkel beleírni. A NEXT a ciklus vége. A futtatás eredménye: 120.

Faktoriális paraméterrel

Számoljuk ki n!-t, ahol n egy globális változó. A Spectrumban eljárások vannak, aminek nincs paramétere és visszatérési értéke; az őt hívó programmal globális változókon keresztül kommunikál. Eljárás hívása: GO SUB. Visszaérés a szubrutinból: RETURN. Itt fontos a STOP utasítás is, amivel befejeződik a program, hogy nehogy ráfusson a szubrutinra. a REM a remark rövidítése, és megjegyzést jelent.

  10 REM factorial with subroutine
  20 LET n=6
  30 GO SUB 1000
  40 PRINT n;"!=";f
  50 STOP
1000 REM f = n!
1010 LET f=1
1020 FOR i=2 TO n
1030 LET f=f*i
1040 NEXT i
1050 RETURN

Eredmény: 6!=120.

Ismétlés nélküli kombináció

Az n alatt a k képlete: n!/(k!*(n-k)!). Ez nem nagy dolog más nyelvekben, a Spectrumban viszont a sok globális változó miatt kihívás, de nem lehetetlenség. A programban a faktoriális az 1000- sortól indul, ahol az 'a' változó faktoriálisát számolja ki, az eredmény az 'f' változóba kerül. Az n alatt a k az 'n' és 'k' változókat kapja inputként, segédeljárásként a faktoriálist használja, az eredmény a 'c' változóba kerül.

  10 REM 5 choose 2
  20 LET n=5
  30 LET k=2
  40 GO SUB 2000
  50 PRINT n;" choose ";k;"=";c
  60 STOP
1000 REM f = a!
1010 LET f=1
1020 FOR i=2 TO a
1030 LET f=f*i
1040 NEXT i
1050 RETURN
2000 REM c = n choose k
2010 LET a=n
2020 GO SUB 1000
2030 LET c=f
2040 LET a=k
2050 Go SUB 1000
2060 LET c=c/f
2070 LET a=n-k
2080 Go SUB 1000
2090 LET c=c/f
2100 RETURN

Az eredmény: 5 choose 2=10.

Prímellenőrzés

Írjuk ki a prímszámokat 20 alatt!

10 REM primes <= 20
20 FOR n=2 TO 20
30   LET p=1
40   FOR i=2 TO SQR n
50     IF n/i=INT (n/i) THEN LET p=0
60   NEXT i
70   IF p=1 THEN PRINT n
80 NEXT n

Az eredmény: 2, 3, 5, 7, 11, 13, 17, 19, egymás alatt.

Legnagyobb közös osztó

Az Euklideszi algoritmust használjuk. A Spectrumban nincs WHILE ciklus sem modulo, így a megvalósításhoz trükkökhöz kell folyamodnunk.

10 REM greatest common divisor
20 LET a=30
30 LET b=12
40 IF b=0 THEN PRINT "GCD: ";A: STOP
50 LET r=a-INT (a/b)*b
60 LET a=b
70 LET b=r
80 GO TO 30

Az eredmény: 6.

Lista

A Spectrum BASIC rendkívül gyenge a modern adatszerkezetek területén. Mindössze egyetlen fix listát támogat, aminek még a hosszát sem lehet lekérdezni, és módosítani sem lehet, tehát tudását tekintve bőven a klasszikus tömb alatt van. Lássunk egy példát összeadásra!

  10 REM sum numbers
  20 RESTORE 1000
  30 LET sum=0
  40 FOR i=1 TO 3
  50   READ d
  60   LET sum=sum+d
  70 NEXT i
  80 print sum
1000 DATA 3,2,5

A RESTORE azt mondja meg, hogy hol található az adat; jelen esetben az 1000-es sorban. A READ ezeket olvassa be egyesével. Az eredmény: 10.

Rajzolás

A ZX Spectrum egyik erőssége a rajzolás volt, persze a '80-as évek mércéjével mérve. A koordináta rendszer mérete: x-tengely 0…255, y-tengely 0…175; a (0, 0) koordináta a bal alsó sarokban van. Pontot rajzolni a PLOT x,y, míg egyenest az adott pontból a DRAW dx,dy utasítással lehet. Láttunk egy példát, melyben egy sokszöget rajzolunk ki, és trigonometriai számításokkal határozzuk meg a vonal irányát!

10 REM draw polygon
20 LET n=7
30 LET pi=3.14
40 LET l=50: REM length
50 PLOT 150,20
60 FOR i=1 TO n
70   LET a=i*pi*2/n
80   DRAW l*COS a,l*SIN a
90 NEXT i

Programozás assembly-ben

Áttekintés

A legizgalmasabb, egyben a leginkább agyament dolog az assembly programozás. Valójában assembly-ben nem is lehet programozni, csak gépi kódban. Tekintsük a következő kódot:

10 DATA 4,1,5,0,201
20 LET s=32768
30 READ l
40 FOR n=0 to l-1
50   READ a
60   POKE s+n,a
70 NEXT n
80 PRINT USR s

Futáskor ezt kapjuk: 5.

De mi is történik ebben a fekete mágiában? A DATA sor a tulajdonképpeni gépi kód. Az első szám a program hossza, és utána jönnek a bájtok egymás után. A POKE utasítással tudunk beírni egy memóriahelyre adatot, tehát pl. a POKE 32768,201 azt jelenti, hogy a 32768. bájtba a 201 érték kerül. A kiolvasás egyébként a PEEK. A programban a 20-70 sorok írják be a memóriába egyesével a bájtokat.

A 80. sorban az USR az, amelyik meghívja a gépi kódú programot, az eredmény pedig a BC regiszter értéke lesz. A regiszterekről később lesz szó részletesebben. Ezt az értéke a PRINT utasítással kiírjuk. Tehát a gépi kód annyit csinál, hogy ebbe a regiszterbe 5-öt tesz, majd visszatér, amit kiírunk.

Az assembly kód a következő

LD  BC, 5
RET

Magyarázat:

  • LD BC, 5: a BC regiszterbe 5 kerül. ENnek a gépi kódja az 1, ami 2 paramétert vár, előbb a C majd a B értékét. Tehát a sorrend meg van fordítva. Így ennek az utasításnak a gépi kódja: 1, 5, 0.
  • RET: visszatér a hívó oldalra, azaz BASIC módba. Ennek a gépi kódja a 201.

Az USR-t önmagában nem lehet meghívni, azt mindenképp egy utasítás paramétereként kell megadni. Ha nem szeretnénk semmit sem kezdeni, akkor a szokásos módszer a következő:

RANDOMIZE USR 32768

Ez a T billentyűn található (RAND), és ez állítja be a véletlen szám generátor magját.

Regiszterek

A regisztereket leginkább a magasabb programozási nyelvek változóihoz tudjuk hasonlítani, ám annál speciálisabbak, és a tulajdonképpeni változónak a memóriacím felel meg. Felfoghatjuk úgy is, mint előre létrehozott változók, speciális céllal. A Spectrumban az alábbi regisztereket használhatjuk:

  • Fő regiszterek
    • A: akkumulátor. A legtöbb művelet eredménye ide kerül.
    • B, C: általános célú. Gyakran párban használják (BC) leginkább számlálásra és címzésre.
    • D, E: általános célú. Párban (DE) adatok mozgatására használják a memóriában.
    • H, L: általános célú. Párban (HL) címzési regiszter.
  • Speciális regiszterek
    • SP: stack pointer, azaz veremmutató.
    • PC: program counter, azaz a végrehajtandó utasítás címe.
    • IX, IY: index regiszterek; ritkábban használtak.
  • Állapotregiszter: F, amelynek a bitjei a fontosak
    • 7: S (sign); előjel bit. Negatív-e az utolsó művelet eredménye.
    • 6: Z (zero); nulla bit. Nulla-e az utolsó művelet eredménye.
    • 4: H (half carry); BCD számításoknál használatos.
    • 2: P/V (parity/overflow); párosság vagy túlcsordulás.
    • 0: C (carry); átvitel pl. összeadásánál.

Utasítások

A Spectrum utasításkészletének fontosabb elemei az alábbiak.

  • Adatmozgatás (LD, load): az adott regiszterbe kerül az érték
    • LD A, n: 62, n (A = n)
    • LD B, n: 6, n (B = n)
    • LD C, n: 14, n (C = n)
    • LD D, n: 22, n (D = n)
    • LD E, n: 30, n (E = n)
    • LD H, n: 38, n (H = n)
    • LD L, n: 46, n (L = n)
    • LD BC, nn: 1, n2, n1 (BC = nn; előbb jön a C, utána a B)
    • LD DE, nn: 17, n2, n1
    • LD HL, nn: 33, n2, n1
    • LD SP, nn: 49, n2, n1
    • LD B, A: 71 (B = A)
    • LD C, A: 79 (C = A)
    • LD D, A: 87 (D = A)
    • LD E, A: 95 (E = A)
    • LD H, A: 103 (H = A)
    • LD L, A: 111 (L = A)
    • LD (HL), A: 119 (a HL által mutatott memóriacímbe kerül az A tartalma)
    • LD A, (HL): 126 (az A regiszterbe kerül a HL által mutatott memóriacím tartalma)
  • Aritmetikai műveletek
    • ADD A, n: 198, n (A = A + n)
    • ADD A, B: 128 (A = A + B)
    • ADD A, C: 129 (A = A + C)
    • ADD A, D: 130 (A = A + D)
    • ADD A, E: 131 (A = A + E)
    • ADD A, H: 132 (A = A + H)
    • ADD A, L: 133 (A = A + L)
    • SUB A, n: 214, n (A = A - n)
    • INC A: 60 (A = A + 1)
    • DEC A: 61 (A = A - 1)
    • INC B: 4 (B = B + 1)
    • DEC B: 5 (B = B - 1)
    • INC C: 12 (C = C + 1)
    • DEC C: 13 (C = C - 1)
  • Logikai műveletek
    • AND A, n: 230, n (A = A AND n)
    • OR A, n: 246, n (A = A OR n)
    • XOR A, n: 238, n (A = A XOR n)
    • CP A, n: 254, n (A és n összehasonlítása; a megfelelő F jelzőbitek állítódnak be)
  • Ugrások és hívások
    • JP nn: 195, n2, n1 (ugrás abszolút címre)
    • JP NZ, nn: 195, n2, n1 (ugrás abszolút címre, ha a Z jelzőbit nincs beállítva)
    • JP Z, nn: 195, n2, n1 (ugrás abszolút címre, ha a Z jelzőbit be van állítva)
    • JP NC, nn: 195, n2, n1 (ugrás abszolút címre, ha a C jelzőbit nincs beállítva)
    • JP C, nn: 195, n2, n1 (ugrás abszolút címre, ha a C jelzőbit be van állítva)
    • JR n: 195, n (rövid ugrás előre vagy hátra)
    • JR NZ n: 195, n (rövid ugrás, ha nincs Z jelzőbit)
    • CALL nn: 205, n2, n1 (függvényhívás)
    • RET: visszatérés a hívásból.

Hasznos lehet még a NOP utasítás is, ami 0, egy órajelig tart, és nem csinál semmit.

A fenti utasítások és regiszterek segítségével tehát el kell készítenünk az assembly kódot, majd ki kell keresni az egyes utasítások gépi kódját, és ezt soroljuk fel a DATA utasításnál.

Két olyan könyvet találtam a neten, amely tartalmazza a teljes utasításkészletet:

A memória felépítése

A ZX Spectrum 64 kB memóriája tartalmazza a ROM-ot (ahol az operációs rendszer található), a képernyő memóriát (amit ma videókártyának hívunk), egyéb fenntartott területet és a tulajdonképpeni RAM-ot, a következőképpen:

  • 0-16383: ROM
  • 16384-22527: képernyő memória
  • 22528-23295: attribútummemória (színek és villogás)
  • 23296-23733: fenntartott memóriaterület
  • 23734-65535: program, adatok és stack (ez utóbbi felülről)

A példákban a 32768-as memóriaterülettől programozunk.

Összeadás

Valósítsuk meg azt a kódot, ami összeadja 3-at és 2-t. Műveletet az A regiszterben tudunk végrehajtani, tehát oda töltjük be a 3-at és adjuk hozzá a 2-t. Majd ezt át kell másolni a BC regiszterbe, mert azt írja ki a BASIC program. A BC regiszter 16 bit, az A pedig 8, emiatt közvetlenül nem tudjuk bemásolni. A B regiszter értéke 0 lesz a C regiszeré pedig az A értéke. Tehát a program:

LD  A, 3
ADD A, 2
LD  B, 0
LD  C, A
RET

Most írjuk mellé a listából a gépi kódot:

LD  A, 3 ; 62, 3
ADD A, 2 ; 198, 2
LD  B, 0 ; 6, 0
LD  C, A ; 79
RET      ; 201

Ez tehát összesen 8 bájt. A DATA ezzel kezdődik, majd sorban a számok:

10 DATA 8,62,3,198,2,6,0,79,201
20 LET s=32768
30 READ l
40 FOR n=0 to l-1
50   READ a
60   POKE s+n,a
70 NEXT n
80 PRINT USR s

Futtatás eredménye: 5.

Kiírás

A fenti programban az eredményt a BASIC PRINT utasítása írta ki. Assembly-ben ez meglehetősen bonyolult. Ennek a szakasznak az elkészítésében a http://www.breakintoprogram.co.uk/hardware/computers/zx-spectrum/assembly-language/z80-tutorials/print-in-assembly-language oldal, a fent felsorolt könyvekben a gépi kódok táblázata, valamint a türelmem és a józan szem segített.

A módszer a következő:

  • Töröljük a képernyőt, egyúttal megnyitjuk a csatornát.
  • Az A regiszterbe beletesszük a kiírandó karakter ASCII kódját.
  • Meghívjuk a RST 0x10 rutint.
  • Az előző két lépéssel egyesével kiírjuk karakterenként a szöveget.

Képernyő törlése

A 0x0DAF memóriaterületet kell meghívni, itt van ugyanis megvalósítva a ROM-ban a törlés:

CALL 0x0DAF

A CALL gépi kódja a 205, és utána 2 bájtot vár: a fenti memóriacímet, és fordított sorrendben, azaz előbb jön az AF és utána a 0D hexacedimális értékek, azaz decimálisan a 175 és a 13 értékeket.

A karakterek kiírása egyesével

LD  A, 72
RST 0x10

Azt szeretnénk kiírni, hogy "Hello". A H betű ASCII kódja a 72. Az LD A, 72 utasítás gépi kódja decimálisan a 62, 72. A RST 0x10 gépi kódja decimálisan a 215. Tehát a 62, x, 215 sorozatot kell megadni minden egyes betűhöz, ahol az x az aktuálisan kiírandó betű ASCII kódja.

A teljes assembly program és gépi kód

CALL 0x0DAF  ; ROM_CLS
LD  A, 72    ; 'H'
RST 0x10
LD  A, 101   ; 'e'
RST 0x10
LD  A, 108   ; 'l'
RST 0x10
LD  A, 108   ; 'l'
RST 0x10
LD  A, 111   ; 'o'
RST 0x10
RET

A RET kódja a 201. A teljes kód tehát a következő: 205, 175, 13, 62, 72, 215, 62, 101, 215, 62, 108, 215, 62, 108, 215, 62, 111, 215, 201. Ez 19 bájt

A BASIC program

A BASIC programot a fentiek alapján állítjuk össze, ahol a DATA most már 20 számot tartalmaz: a hosszt (19) és a fenti gépi kódot.

Másik változtatás az utolsó sor: ebben már maga a gépi kód írt ki, a BASIC nem, így az utolsó sor PRINT helyett a RANDOMIZE utasítást tartalmazza.

10 DATA 19, 205, 175, 13, 62, 72, 215, 62, 101, 215, 62, 108, 215, 62, 108, 215, 62, 111, 215, 201
20 LET s=32768
30 READ l
40 FOR n=0 to l-1
50   READ a
60   POKE s+n,a
70 NEXT n
80 RANDOMIZE USR s

Eredmény

Hello

Összefoglaló

Jó móka volt elővenni és eljátszani vele. Az egyértelműen elmondható, hogy modern szemmel a Spectrum egy katasztrófa. Nyilván az összesen 64 kB (amiben benne van az operációs rendszer, a képernyő memória és a teljes RAM) mai szemmel iszonyat kevés; ma már ennek a milliószorosával dolgozunk. De ettől eltekintve is igazi katasztrófaturizmussal felérő élmény volt:

  • A sorszámozás egészen elképesztő, amit már a PC BASIC nyelvei is elengedtek.
  • A billentyűzet használata rendkívül nehézkes, egyrészt a ritkásan elhelyezkedő gumi billentyűk, másrészt a nehézkes használata miatt. Például a módokat egy-két hónap elteltével is teljesen elfelejtettem; utána kellett néznem, hogy mit hogyan tudok elérni.
  • Mivel be begépeljük a kulcsszavakat, hanem kikeressük, egy-egy kulcsszó megtalálása hosszú időt vehet igénybe.
  • A modern programozási nyelvek konvencióit egyáltalán nem követi. Bizonyos szokásos műveletek vagy egyáltalán nem léteznek, vagy egészen máshogy.
  • A változókezelés borzasztó. Az, hogy csak egybetűs a string, óriási korlát.
  • Alapvető struktúrák hiányoznak, pl. nincs blokk, szinte mindent a GOTO-val kell megoldani, ami karbantarthatatlan kódot eredményez már nagyon kis programok esetén is.
  • Nincsenek függvények. A szubrutinnak nincs paramétere és visszatérési értéke, csak globális változókkal dolgozik. Azon túl, hogy ez áttekinthetetlenné teszi a kódot, még az olyan alapvető műveleteket sem engedélyezi, mint pl. a rekurzió.
  • Nincs védelem és visszavonás. Pl. egy hibásan beírt sorszám egyből törli a sort, a NEW egyből törli a programot.
  • Az assembly programozás még assembly mércével mérve is különösen nehézkes. (Egy assembly fordítót igazán beletehettek volna a retró kiadásba!)
  • És a The Spectrum kiadása sem egyszerűsítette az életet, gondoljunk csak az USB pen drive nehézkességére, a klasszikus módba lépés nehézkességére és egyebekre.
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License