Commodore BASIC

mikroszámítógépes BASIC programozási nyelv

A Commodore BASIC vagy PET BASIC a BASIC programozási nyelvnek a Commodore International 8 bites személyi számítógépeiben használt dialektusa, az 1977-es PET-től az 1985-ös C128-asig. A nyelv alapját a 6502-es mikroprocesszoron futó Microsoft BASIC képezte, ezért sok közös vonása volt a kor más 6502-es BASIC-jeivel, mint amilyen az Applesoft BASIC is volt. A Commodore részéről Jack Tramiel egyszeri fizetéssel vásárolta meg a Microsofttól a BASIC korlátlan licenceit, azzal utasítva el Bill Gates 3 dolláros gépenkénti ajánlatát, hogy „már házas vagyok”, így összesen 25 000 dollárt költöttek az öröklicencre.[1]

Commodore BASIC
Megjelent1977
MegvalósításokPET-től a C128-ig
Hatással volt ráMicrosoft BASIC

Története szerkesztés

A Commodore a megvásárolt BASIC forráskódot fejlesztette tovább a többi 8 bites személyi számítógépükre. Csak a Commodore 128 megjelenésével (a V7.0-nál) kezdték a Microsoft szerzői jogát megjeleníteni. A kód eredeti, a Commodore PET-en futó 2.0 verziójában lévő, a Microsoft által elrejtett üzenet (Easter egg) a WAIT 6502, 1 beírása után a Microsoft! feliratot jelenítette meg a képernyőn. A kód jól el volt rejtve – az üzenetet nem látszott a parancsértelmező kódjában.[2]

A népszerű Commodore 64 a ROM-ba épített BASIC v2.0-val jelent meg, annak ellenére, hogy addigra a PET/CBM-sorozatban már a 4.0 változat is megjelent. Ennek oka az volt, hogy a 64-est otthoni számítógépnek szánták, míg a PET/CBM sorozatot üzleti és oktatási célra, ahol feltették, hogy a beépített programozási nyelv nagyobb használatnak lesz kitéve. Ez csökkentette a gyártási költségeket, mivel a V2-es kisebb ROM modulokban is elfért.

Technikai részletek szerkesztés

 
A C64 karaktertáblája, „direkt módú” paranccsal kilistázva
 
A Simons' BASIC indítóképernyője
 
Tipikus, Commodore BASIC-ben fejlesztett irodai alkalmazás (CBM 3032)

A Commodore memóriarezidens (ROM-ban tárolt) BASIC parancsértelmezőjének és KERNAL-jának kényelmes funkciója volt a teljes képernyős, szöveges szerkesztőfelület.[3][4] Bár a Commodore-ok billentyűzete csak két nyílbillentyűvel rendelkezett, melyek mozgatási irányát a shift lenyomásával lehetett megfordítani, a teljes képernyős szerkesztővel a képernyő bármely területén ki lehetett adni közvetlen parancsokat vagy szerkeszteni lehetett a programsorokat. Ha a képernyő egy sora számmal kezdődött, azt sorszámként értelmezte, és tokenizálás után a programmemóriában tárolta. A nem számmal kezdődő sorokat a RETURN gomb megnyomása után végrehajtotta, amennyiben a kurzor éppen azon a soron tartózkodott. Ez jelentős előrelépés volt a korábbi otthoni számítógépek BASIC-jeinek beviteli felületéhez képest, melyek általában külön EDIT paranccsal aktiválható sorszerkesztőt használtak vagy „copy cursort”, ami a kurzor pozíciójának megfelelő helyen egyetlen karaktert engedett módosítani.

Képes volt továbbá névvel ellátott fájlként elmenteni a programot bármilyen eszközre, köztük magnókazettára – ami népszerű tárolóeszköz volt a PET idejében, és a 8 bites Commodore gépek életciklusa alatt végig olcsó tömeges tárolóeszköznek számított. Analóg hangfelvételi médiaként széles körben elterjedtek voltak. A legtöbb rendszer csak mágneslemezen tette lehetővé fájlnevek használatát, ami a többi tárolóeszközön nehézkessé tette egynél több fájl lementését. A felhasználó annyit tehetett, hogy feljegyezte a magnó számlálójának a fájl kezdetekori állását, de ez pontatlan és bizonytalan megoldás volt. A PET (és a BASIC 2.0) megjelenésével lehetett a fájlokat név szerint bekérni a kazettáról. Az eszköz ilyenkor is szekvenciálisan olvasta a kazetta tartalmát, átlépve a megadottól eltérő fájlneveken. A kazettás tároláshoz hatékony rekordstruktúra is tartozott. A Commodore kazettákon digitálisan tárolták az adatokat, szemben az akkoriban gyakori, kevésbé megbízható (bár olcsóbb) analóg megoldásokkal. Ezért specializált kazettás egységet, a Commodore Datasette-et kellett használni. Léteztek a szokásos szalagos egység használatát lehetővé tevő analóg-digitális átalakítók, de ezek alig voltak olcsóbbak a Datasette-nél.

Mivel a Commodore ugyanazt a BASIC nyelvet használta különböző hardverarchitektúrákon, ezért a LOAD parancs egy paraméterével befolyásolni lehetett, hogy a program milyen memóriacímre töltődjön be. A

LOAD "*",8

parancs a programot a BASIC memóriaterület elejére tölti be, míg a

LOAD "*",8,1

parancs arra a területre, ahonnan elmentésre került. BASIC programoknál általában az első változatot alkalmazták, mivel a BASIC memóriaterülete az egyes modelleknél más-más volt. Egyes Commodore BASIC-változatok ismerték a BLOAD és BSAVE parancsokat, melyek – az Applesoft BASIC-beli megfelelőjükhöz hasonlóan – a megadott memóriaterületekről bittérképeket mentettek ki vagy töltöttek be oda.

A kiindulásul szolgáló Microsoft BASIC értelmezőhöz hasonlóan a Commodore BASIC is jóval lassabb a natív gépi kódnál. Tesztek szerint 16 kilobájtnyi adat ROM-ból RAM-ba történő másolása gépi kódban kevesebb mint egy másodpercet vesz igénybe, BASIC-ben pedig egy percnél is többet. A BASIC programok felgyorsítására a programozók különböző technikákat alkalmaztak. Az egyik az volt, hogy a gyakran használt lebegőpontos értékeket változókban tárolták, mert a változónevet gyorsabban dolgozta fel a parancsértelmező a konstans értékeknél. Mivel a lebegőpontos volt az alapértelmezett számformátum, gyorsabb volt az egész számok helyett ezeket használni. Egyes programozók a valóban sebességkritikus programhelyeket 6502-es vagy 6510-es assembly nyelvre konvertálták, a BASIC program végén található DATA kulcsszavakból a memóriába POKE-olták vagy külön fájlból betöltötték, és a SYS BASIC paranccsal elindították (BASIC loader). Amikor pedig az assembly kód futási sebessége túl nagy, például egy számítógépes játékban, vagy amikor a program felhasználói adatbevitelre várakozik, programozott lekérést (polling) hajtanak végre a végrehajtás késleltetésére vagy felfüggesztésére, méghozzá a megfelelő memóriaterületek PEEK-elésével (ez pl. $A6 a C-64-en vagy $D0 a C-128-on, ami a billentyűzet-várakozási sor méretére utal).

A Commodore BASIC kulcsszavai általában rövidíthetők az első karakter shift nélküli, majd a következő shifttel történő lenyomásával. Ez a karakter legfelső bitjét 1-re állítja, amire a parancsértelmező abbahagyja az olvasást és egy keresőtábla alapján próbálja értelmezni a kifejezést. Tehát a teljes parancs beírása helyett az első néhány karakter beírása elegendő. Mivel azonban az összes BASIC parancsszó a memóriában egybájtos tokenekként tárolódik, ezért ez csak a bevitelt teszi kényelmesebbé, a program tárolását nem optimalizálja.

Az alapértelmezett, csupa nagybetűs karakterkészletben a shiftelt karakterek grafikus szimbólumokként jelennek meg; például a GOTO parancs G{Shift-O}-ként rövidíthető (ami a képernyőn így mutatkozik: GΓ). A legtöbb ilyen parancs kétbetűs, egyes esetekben hosszabb. Kétértelműség esetén több shifteletlen karaktert kellett beütni, például a GO{Shift-S} (GO♥) a GOSUB parancsnál. Egyes parancsokat nem lehetett rövidíteni, rövidségük vagy más parancsokkal való összetéveszthetőségük miatt. Például az INPUT-nak nem volt rövidítése, mert a parancsszó alakja ütközött az INPUT# paranccsal, ami közelebb helyezkedett el a kulcsszó-keresőtábla elejéhez. A gyakran használt PRINT parancsnak a többi BASIC dialektushoz hasonlóan a ? volt a rövid alakja. A parancsok shiftelt alakkal való rövidítése a Commodore BASIC egyedi sajátossága.

A kulcsszavak rövidítésével valamivel több kód fért el egy programsorban (a program egy sora 2 vagy 4 képernyősor hosszúságú lehetett, modelltől függően). Ez jelentett némi megtakarítást, mivel minden új sorhoz tartozott némi memória-overhead, de nem túl sokat. Minden BASIC parancs token formájában tárolódott és csak egyetlen bájtot foglalt a memóriából (illetve a BASIC 7 és 10 esetében több parancs két bájtot) a beírás módjától függetlenül. Ráadásul az ilyen hosszú sorokat utólag elég nehéz volt szerkeszteni. A LIST parancs mindig a teljes kulcsszavakkal listázta a programot – akkor is, ha így a sorok túlterjeszkedtek a 2 vagy 4 képernyősor hosszúságon, ami még lehetővé tette a bevitelüket.

További optimalizálást tett lehetővé,[5] hogy a BASIC programok nem igényelnek szóközöket (bár a LIST parancs a sorszám és a parancs közé automatikusan beszúr egyet), pl. a

100 IFA=5THENPRINT"YES":GOTO160

egy érvényes programsor. Gyakori is volt a szóközök nélküli programozás, mivel a kulcsszavak közötti szóközöket a tokenizált programban extra 0x20 bájtokként tárolták, amiken a parancsértelmező futtatás során átlépett. A sorok okozta overhead megtakarítására szokás volt továbbá minél több kódot egyetlen sorba írni, az egyes parancsokat kettősponttal elválasztva.

Az elágazás nélküli programvégrehajtás során a végrehajtás sorrendjét nem a sorszámozás határozza meg. A BASIC program ugyanis egyszeresen láncolt lista: minden sor a következő sor elejére mutató kétbájtos mutatóval kezdődik (ahol a 0 pointer a program végét jelzi), a következő két bájt a sor száma, majd a nullbájttal lezárt tokenizált parancssor következik.[6][7] Mivel a GOTO és GOSUB parancsok fix programsorszámokra hivatkoznak, a konstansok kódolása miatt a GOTO 10000 parancs három bájttal többet foglal a memóriából a GOTO 10 parancsnál; emiatt a programok átsorszámozása 1,2,3… sorszámokra a lehetséges optimalizációk közé tartozott (az egymást követő sorok összevonása, szóközök kihagyása stb. mellett), melyek utólagos elvégzésére külön segédprogramok léteztek.[5] A program sorról sorra történő beírásakor a BASIC azonnal átrendezi a memóriában a programsorokat, hogy a sorszámok és a mutatók emelkedő sorrendben legyenek. Ha már a program a memóriában van, PEEK és POKE utasításokkal a sorszámok átírhatók, vagy akár minden sor száma megegyezhet. Azokban az időkben, amikor BASIC nyelven kereskedelmi programokat írtak, ezt a megoldást használták is a programok módosítása elleni védelmi technikaként.

A változónevek csak két karakter erejéig voltak megkülönböztetve, így a VARIABLE1, VARIABLE2 és VA mind ugyanarra a változóra utalt.

Az eredeti MS BASIC-kel megegyezően a Commodore BASIC natív számformátuma is lebegőpontos. A legtöbb kortárs BASIC-implementáció három bájtot használt az értékes számjegyekre (mantissza) és egy bájtot a kitevőre (karakterisztika). A három bájtos mantisszával a lebegőpontos számok pontossága kb. 6,5 decimális jegy, a kerekítési hibák gyakoriak. A Commodore azonban az MS BASIC négy bájtos mantisszáját vette át, ami a Commodore BASIC-et sokkal használhatóbbá tette az üzleti alkalmazások számára.

Bár a Commodore BASIC támogatja a (százalékjellel jelölt) előjeles egész szám változótípust, melynek értéke −32768 és 32767 közé eshet, a gyakorlatban ennek előnyei kizárólag tömbváltozóként jelennek meg: memóriát spórol, mivel így a tömb tagjai egyenként csak két bájtot foglalnak. Az egyszerű skalár változót egész számnak jelölve a BASIC mindig visszakonvertálja azt lebegőpontossá, ami lelassítja a program futását, és még pazarló is, hiszen a százalékjel egy bájtot elfogyaszt a memóriából. Az előjeles egész változókkal nem is lehet megcímezni a memória 32767 fölötti részeit a POKE vagy PEEK utasításokkal.

A karakterlánc típus jelölése a változónév után írt dollárjellel történik. Tehát az AA$, AA és AA% változókat a Commodore BASIC mind különbözőnek tekinti.

A gyári BASIC 2.0 hiányosságai miatt a Commodore 64-hez számos BASIC-kiterjesztést dobtak piacra. Az egyik legnépszerűbb kiterjesztés a Commodore 1541 Test/Demo Disken megtalálható DOS Wedge volt. Ez az 1 KB-os kiterjesztés főleg lemezkezelési parancsokkal bővítette az eredeti utasításkészletet, például lehetővé tette a lemez tartalomjegyzékének listázását a memóriában lévő program törlése nélkül. Ezeket a képességeket később több BASIC-kiterjesztés örökölte, köztük a népszerű Epyx FastLoad cartridge is. Más BASIC-kiterjesztések például a sprite-ok, hangok és a nagy felbontású grafikus mód kezelését tették lehetővé, ilyen volt például a Simons' BASIC.

Bár a BASIC 2.0-nak a grafika és a hang kezelésében mutatott hiányosságai a felhasználók számára frusztrálóak voltak, egyes kritikusok szerint még hasznosak is voltak, mert rákényszerítették a felhasználók a gépi kódú programozás elsajátítására.

A C64-es BASIC 2.0 korlátai miatt gyakran előfordult, hogy BASIC-ből a beépített ROM-ban lévő vagy saját gépi kódú rutinokat hívtak meg.

A Loadstar nevű C64-es diszkmagazin a hobbiprogramozók színtere volt, akik (egyebek mellett) saját gyártású BASIC parancsokat is megosztottak egymással, melyeket a

SYS memóriacím + eltolás

paranccsal lehetett meghívni.

Modern programozási megközelítésből a Commodore BASIC korai verziói számos rossz programozási gyakorlat csapdájába ejtették a felhasználót. A legtöbb ilyen probléma a Microsoft BASIC-ből fakadt, bár gyakorlatilag minden korabeli mikroszámítógép BASIC-e hsaonló problémákkal küzdött.[8] A Microsoft BASIC programok minden sorához egy sorszám tartozott. Ezeket gyakran fix értékkel (5, 10 vagy 100) növelték, hogy megkönnyítsék későbbi programsorok beszúrását a program továbbfejlesztése vagy hibakeresés céljából. Ha nem sikerült jó előre megtervezni a program szerkezetét, később új programrészek beszúrásához az egész kódot át kellett strukturálni. Ennek elkerülésére az egyik technika az volt, hogy a program alacsony sorszámokon, egy ON...GOSUB ugrótáblával kezdődött, a programot pedig főbb programrészekre osztották, melyek a nekik kijelölt nagyobb sorszámoknál kezdődtek, pl. 1000, 2000 stb. Ha egy nagyobb szekcióval kellett bővíteni a programot, a következő nagyobb sorszámtól lehetett kezdeni a számozását, a sorszámot pedig csak be kellett illeszteni az ugrótáblába.

A Commodore és más platformok későbbi BASIC-verzióiba már bekerültek az átstrukturálást segítő DELETE és RENUMBER parancsok, valamint az AUTO sorszámozó parancs, ami a beállított növekmény szerint automatikusan megadta a következő sorszámot.

A Commodore BASIC-ben minden változó globális. Nehéz jól definiált ciklusokat létrehozni, ezért a programozó gyakran a GOTO utasításra hagyatkozik (ezt később a BASIC 3.5-ben a DO, LOOP, WHILE, UNTIL és EXIT parancsokkal hozták helyre). Egyes feladatokhoz muszáj volt flag változókat létrehozni. A Commodore korai BASIC-változatai nem rendelkeztek a debugolást segítő parancsokkal, ezért a hibakeresés és optimalizálás a beépített eszközökkel nehézkes volt.

Felhasználói felületként szerkesztés

Más otthoni számítógépekhez hasonlóan a Commodore-modelleknél is a rendszerindítás közvetlen a BASIC parancsértelmezőt indította el. A BASIC fájlkezelő és programozási parancsait interaktív üzemmódban („direkt mód”) be lehetett írni, például programok betöltésére és futtatására. Egy program futását a RUN/STOP billentyűvel megállítva, a változók értékei a memóriában maradtak, és ki lehetett PRINT-elni őket hibakeresés céljából. A fejlett teljes képernyős szerkesztővel együtt ez már szinte a Lisp-féle REPL-szerű programozási környezetre emlékeztetett; a programozók a képernyőn bárhol szerkeszthették a programot, beilleszthettek sorokat, interaktívan építve a programot.[9] Az előbbiekkel szemben a kor üzleti célú operációs rendszerei, mint a CP/M vagy az MS-DOS jellemzően egy parancssoros felhasználói felülettel indultak el. Ha egy programozási nyelvre volt szükség, azt külön be kellett tölteni.

Bár a Commodore BASIC egyes verziói tartalmaztak lemezspecifikus DLOAD és DSAVE parancsokat, a népszerű Commodore 64 BASIC-ében a felhasználónak kellett megadnia a lemez eszközszámát (jellemzően 8 vagy 9), egyébként a LOAD parancs alapértelmezésben a kazettás egységre vonatkozott. A Commodore 64-ben található BASIC 2.0 másik hiányossága volt, hogy nem volt benne a memóriában lévő program felülírása nélküli tartalomjegyzék-listázást végző DIRECTORY parancs.

Verziók és képességek szerkesztés

 
A tartalomjegyzék listázása a beépített BASIC parancsokkal

A CBM BASIC verziói idősorrendben, a hozzáadott újdonságokkal:

Kiadott verziók szerkesztés

  • V1.0: PET 2001 olcsó gumis billentyűzettel és beépített Datassette-tel (az eredeti PET)
    • a tömböknek legfeljebb 256 eleme lehet
    • A PEEK utasítások számára tiltottak a $C000 fölötti BASIC ROM-területek
  • V2.0 (első kiadás): PET 2001, már teljes utat bejáró billentyűkkel, upgrade ROM-okkal
  • V4.0: PET/CBM 4000/8000 sorozat (és a késői PET 2001-ek)
    • lemezkezelő műveletek: DLOAD,DSAVE,COPY,SCRATCH stb. (összesen 15)
    • lemezkezelési hibacsatorna változói: DS,DS$
    • nagyban javított szemétgyűjtési teljesítmény[10]
  • V2.0 (második kiadás, a 4.0 után jelent meg): VIC-20; C64
  • V4+ : CBM-II sorozat (a B, P kiadások)
    • memóriakezelés: BANK
    • további lemezkezelő műveletek: BLOAD, BSAVE, DCLEAR
    • formázott nyomtatás: PRINT USING, PUDEF
    • szoftveres megszakítás, avagy error trapping: DISPOSE
    • alternatív elágazás: ELSE
    • dinamikus hibakezelés: TRAP, RESUME, ERR$()
    • rugalmas DATA-beolvasás: RESTORE [linenumber]
    • füzéskeresési függvény: INSTR
  • V3.5: C16/116, Plus/4
    • hang- és grafikakezelő parancsok
    • botkormány-bemenet: JOY
    • decimálishexadecimális közötti konverzió: DEC(),HEX$()
    • strukturált ciklusok: DO, LOOP, WHILE, UNTIL, EXIT
    • a funkcióbillentyűk programozhatósága: KEY (interaktív üzemmódban is)
    • programbevitel/szerkesztés: AUTO, DELETE, RENUMBER
    • debug (nyomkövetés): TRON, TROFF
    • gépi kódú monitorprogram belépési parancsa: MONITOR
    • C(1)16, Plus/4 Easter egg – SYS 52651
  • V7.0: C128
    • további hang- és grafikakezelő parancsok, köztük a sprite-ok kezelése
    • beépített sprite-szerkesztő: SPRDEF
    • Több parancsból álló blokkok az IF THEN ELSE-szerkezetekben: BEGIN, BEND
    • paddle („lapát”, egyfajta játékvezérlő) és fényceruza beviteli eszközök: POT, PEN
    • kizáró vagy függvény: XOR
    • változó címének meghatározása: POINTER
    • szöveges módú ablakozás: WINDOW
    • szabályozott késleltetés: SLEEP
    • memóriakezelés: SWAP, FETCH, STASH, FRE(1)
    • A 128-as memóriabank-váltását felhsaználva a programkódot a változóktól elkülönítve tárolta. A változóértékek a programfutások között megmaradhattak, ha a program nem a RUN, hanem a GOTO paranccsal lett elindítva.
    • további lemezműveletek: BOOT, DVERIFY
    • CPU-sebesség állítása: FAST, SLOW (2 vagy 1 MHz)
    • C64-üzemmódba váltás: GO64
    • dokumentálatlan, de működő: RREG (SYS után kiolvassa a processzor regisztereit)
    • nem implementált parancsok: OFF, QUIT
    • C128 Easter egg – SYS 32800,123,45,6

Kiadatlan változatok szerkesztés

  • V3.6 : Commodore LCD (kiadatlan prototípus). Csaknem megegyezik a V7.0-val, a következő különbségekkel:[11]
    • VOLUME a VOL helyett
    • EXIT a QUIT helyett
    • a FAST, SLOW parancsok nem léteznek
    • További parancs: POPUPS
  • V10 : Commodore 65 (kiadatlan prototípus)
    • grafikus/videoparancsok: PALETTE, GENLOCK
    • egér beviteli eszköz: MOUSE, RMOUSE
    • szövegfájlkezelő (SEQ) segédeszköz: TYPE
    • programszerkesztés: FIND, CHANGE
    • memóriakezelés: DMA, FRE(2)
    • nem implementált parancsok: PAINT, LOCATE, SCALE, WIDTH, SET, VIEWPORTPASTE, CUT

Elterjedtebb bővítőcsomagok szerkesztés

Fordítás szerkesztés

  • Ez a szócikk részben vagy egészben a Commodore BASIC című angol Wikipédia-szócikk ezen változatának fordításán alapul. Az eredeti cikk szerkesztőit annak laptörténete sorolja fel. Ez a jelzés csupán a megfogalmazás eredetét és a szerzői jogokat jelzi, nem szolgál a cikkben szereplő információk forrásmegjelöléseként.

Jegyzetek szerkesztés

Megjegyzések
BASIC 2.0
  • Angerhausen et al. (1983). The Anatomy of the Commodore 64 (for the full reference, see the C64 article).
BASIC 3.5
  • Gerrard, Peter; Bergin, Kevin (1985). The Complete COMMODORE 16 ROM Disassembly. Gerald Duckworth & Co. Ltd. ISBN 0-7156-2004-5.
BASIC 7.0
  • Jarvis, Dennis; Springer, Jim D. (1987). BASIC 7.0 Internals. Grand Rapids, Michigan: Abacus Software, Inc. ISBN 0-916439-71-2.
BASIC 10.0
  • Commodore 65 preliminary documentation (March 1991), with addendum for ROM version 910501. c65manual.txt