Altair BASIC

1975 januárjában a Popular Electronics magazin bemutatta az Altair 8800 típusú számítógépet. A számítógépet 439 dolláros áron kit készletként (a felhasználónak otthon kellett összeforrasztania a gépet) árulták, de kb. másfélszeres áron (621 dollár) összeszerelve is meg lehetett vásárolni. A gépben az Intel 8080-as processzora volt, alapkiépítésben 256 byte RAM-ot tartalmazott. Szoftver viszont nem volt hozzá...
1974 telén Paul Allen, egy 21 éves, nagy szakállú, hosszú hajú fickó, hetek óta próbálta meggyőzni barátját, hogy hagyja ott az egyetemet, és alapítsanak együtt egy szoftvercéget. A két évvel fiatalabb srác azonban az utolsó pillanatban meggondolta magát, és folytatta tanulmányait a Harvardon. Az illetőt Bill Gates-nek hívták. 1975 januárjában aztán megjelent a Popular Electronics, címlapján az Altair 8800-zal. Allen felismerte a gép jelentőségét, tudta, hogy erre vártak eddig - egy olcsó számítógép, szoftver nélkül. Az egész éjszakát átbeszélték. Másnap felhívták Ed Roberts-et, a MITS főnökét, és blöfföltek: "Van egy BASIC-ünk", mondták. Miután Roberts már tucatjával kapott naponta hasonló hívásokat, rutinosan szerelte le a fiúkat: "Aki először mutat egy működő BASIC-et, azé a szerződés".
A feladat tehát adott volt. Gyorsan írni kellett egy BASIC értelmezőt, mielőtt más megelőzné őket. Volt azonban egy kis probléma. A fiúk még csak fényképen láttak Altair-t, és ezidáig még az Intel 8080-t se ismerték. Allen tehát fogta az Intel 8080 dokumentációját, és gyorsan írt egy emulátort PDP-10-re. Szerencsére ez a feladat nem volt idegen számára, korábban már írt egy Intel 8008 emulációt, így volt gyakorlata ilyen téren. Eközben Gates abbahagyta tanulmányait a Harvard-on, és elkezdte tervezni a BASIC-et - fontos kritérium volt, hogy beleférjen 4kB-ba. Miközben Gates évfolyamtársai egyszerű kártyajátékokat írtak BASIC-ben, addig ő assembly-ben egy új BASIC értelmezőt fejlesztett. A matematikai lebegőpontos rutinok azonban kifogtak rajtuk, emiatt harmadik embernek felfogadták maguk mellé Monte Davidoff harvardi diákot, akinek volt már tapasztalata hasonló rutinok elkészítésében.
A program végül alig három hónap alatt elkészült. A BASIC-et Paul Allen vitte el Új-Mexikóba, a MITS-hez, egy papírszalagon. Az út közben, a repülőgépen ülve írta meg a jegyzetfüzetébe azt a pár tíz bájtos programot, amivel a lyukszalagról lehetett beolvasni az Altair-be a BASIC-et. Induláskor aggódtak, vajon működni fog-e a program - az emulátoron ugyan működött, de mi van, ha hibás az emuláció?
Szerencsére működött, az első parancs, amit kipróbáltak, a PRINT 2+2 volt.
A szerződés megköttetett. Paul Allen és Bill Gates megalapította a Micro-Soft-ot (akkoriban még így, kötőjellel írták a cég nevét), és az Altair BASIC lett az első kereskedelmi szoftver, ami mikroszámítógépre jelent meg. A programot a MITS árulta, a Micro-Soft jogdíjat kapott minden eladott példány után. A 4kB-os változat 60$-ba, a 8kB-os 75$-ba került.

PoviSoft-ot ihlette meg, hogy interneten megtalálható a BASIC disassemblált kódja és készített Enterprise-verziót. Ugyan az Enterprise-ban Z80-as processzor "dobog", ez elvileg nem kell, hogy problémát okozzon, hiszen gépi kód szintjén felülről kompatibilis az Intel 8080-nal (az Intel-ből kivált mérnökök tervezték a Z80-at). A gyakorlat mást mutatott: a Z80 processzor másképp kezeli a paritás jelzőbitet, mint az Intel 8080, ez okozott némi galibát átírásnál.

Konfigurálás
A BASIC sikeres betöltése után, a terminálon - esetünkben a képernyőn - megjelenik az első kérdés: MEMORY SIZE?
A kérdésre bájtban kell megadni a rendelkezésre álló memória méretét. (A BASIC 8K-s verziójában itt elrejtettek egy easter egg-et: ha 'A'-t nyomunk válasznak, a "WRITTEN FOR ROYALTIES BY MICRO-SOFT" üzenet jelenik meg.) Ha nem írunk be semmit, csak ENTER-t nyomunk, a program "kideríti", mekkora RAM-unk van.
Sajnos két hibalehetőség is van:

  1. 1. Több memóriát írunk válasznak, mint amennyi valójában van.
    Mivel a program nem végez ellenőrzést, hogy valóban van-e akkora RAM-unk, mint amennyit válasznak beírtunk, a veremmutató nem létező tárterületre fog mutatni, aminek előbb-utóbb szép kis fagyás lesz a vége.

  2. 2. A gépben 64kB RAM van, és csak ENTER-t nyomunk.
    Ez egy bug. A memória méretének kiderítésekor a program egy ciklusban növelt pointer által mutatott területre próbál írni egy bájtot a memóriába, egészen addig, amíg a visszaolvasott érték nem egyezik az előzőleg beleírt értékkel (vagyis olyan területre értünk, ahol nincs RAM). A ciklusból viszont kimaradt a mutató értékének a vizsgálata, így a RAM tetejét elérve (ekkor 0xFFFF az értéke) a következő lépésben túlcsordulás lesz, a pointer a RAM aljára fog mutatni, majd szépen felülírja saját magát a program, és lefagy.
    Jó kérdés, vajon véletlenül maradt-e benne ez a bug a programban, vagy tudatosan spóroltak így öt bájtot a mutató ellenőrzésének elhagyásával? Akkoriban ugyanis elképzelhetetlennek tűnt, hogy bárkinek is 64kB RAM-ja legyen. Először is, megfizethetetlen lett volna, több, mint 4000$-ba került ennyi memória 1975-ben, másrészt pedig fizikailag sem lehetett volna megvalósítani: egy bővítőkártyán összesen 4kB RAM volt elérhető akkoriban, ebből 16 db-ra lett volna szükség, azonban a gépben csak 15 szabad bővítőhely volt, miután a 16. hely foglalt volt a CPU-kártya számára. Véleményem szerint azonban ez egyszerű bug, hiszen a 4.0-ás verzióban már javították ezt a hibát.

Miért volt szükség erre a kérdésre, ha a program egyébként is ki tudta deríteni a rendelkezésre álló RAM méretét? Azért, mert a válaszként kisebb számot is írhattunk, mint amennyi RAM telepítve volt a gépbe. Ekkor garantálva volt, hogy a maradék tárterületet (a RAM tetejét) nem írja felül a BASIC a működése során. Ez azért volt jó, mert a BASIC betöltése előtt ide saját rutint is elhelyezhettünk, amit aztán a BASIC-ből is meg lehetett hívni.

A rendelkezésre álló memória beállítása után megjelenik a második kérdés: TERMINAL WIDTH?
Itt a terminálon (teletype-on) egy sorban elférő karakterek számát kell megadni, alapértelmezett esetben (ha nem írunk be semmit, csak ENTER-t nyomunk) az értéke 72. Enterprise-on célszerű 78-at megadni, hisz a képernyőn ennyi karakter fér el egy sorban.

Végül az utolsó kérdés: WANT SIN?
Itt eldönthetjük, hogy szükségünk van-e a szinusz- RND és négyzetgyök-függvényekre. Ha nem akarjuk azokat használni, akkor a BASIC felszabadítja a rutinok által lefoglalt tárhelyet, így 246 bájttal több szabad RAM-mal fogunk rendelkezni. Ebben az esetben ha mégis megpróbálnánk hívni a fenti függvények egyikét, akkor érvénytelen függvényhívás hibaüzenetet fogunk kapni.

 

A 4K BASIC (3.2-es verzió) korlátai
Mivel a programnak bele kellett férnie 4kB-ba úgy, hogy még maradjon elegendő hely a BASIC forráskódnak, a változóknak, és a veremnek is, egy sor kompromisszumot kellett meghozni, ami korlátozta a program használhatóságát.

Szerkesztés a BASIC-ben
A szerkesztés nem a ma megszokott módon történik (A "teljesképernyős szerkesztés" akkoriban még ismeretlen fogalom volt, így nincsenek kurzormozgató billentyűk sem.), hanem egy kicsit körülményesebb. Az aktuális sor törlése a kukac "@" karakterrel lehetséges. Ekkor a kurzor a következő sor elejére kerül, és az addig begépelt sor törlődik a bufferből. Ha csak karakterenként szeretnénk visszatörölni a sorban, akkor ezt ERASE billentyűvel lehet megtenni.
A "szerkesztési" lehetőségek ezzel ki is merültek, így mindenképen célszerű programjainkat inkább külső szerkesztővel készíteni / javítgatni (akár a WP is jobb erre), hisz a programokat szöveges formában fogjuk tárolni. A szöveges állománnyal szemben támasztott egyetlen kritérium: a forráskód sorvégi lezáró jelnek CR/LF-nek, vagy CR-nek kell lenni! (Ellenkező esetben az utolsó sort nem olvassa be a BASIC.)

Az Enterprise verzió ki lett egészítve forrásfájl betöltő és kimentő paranccsal, ezek az F1 és F2 billentyűvel érhetők el (használja a FILE bővítést). A 8K verzió CLOAD és CSAVE parancsai ki lettek iktatva - nem csinálnak semmit. A 4K verzióban elérhető RAM 16kB.
Az abszolút retro-érzés kedvéért a CTRL+P gomb megnyomásával válthatjuk a kimenetet a nyomtató és a monitor között.
A STOP megnyomásával megszakítható a futtatott BASIC program. (Hatása megegyezik a CTRL+C billentyűkombináció megnyomásával.)
A BASIC-ből való kilépésre az F8 billenntyű szolgál. Nem kér megerősítést, óvatosan a használatával!

Szintaxis
A BASIC interpreter kétféle üzemmódban működik: parancs üzemmódban, vagy program üzemmódban. Azt, hogy a melyik üzemmódban értelmezi a bevitt sort az interpreter, az az adott sor első nem szóköz karakterétől függ. Ha ez szám, akkora a BASIC úgy tekinti, hogy programsort vittünk be, és elhelyezi a memóriába (ha van már ilyen sorszámú sor, az felülíródik). Ha az első karakter nem számjegy, akkor parancsnak értelmezi és rögtön végrehajtja. Az interpreter a legtöbb BASIC utasítást parancs- és program üzemmódban is végrehajtja.

Az egyes BASIC programsorok - növekvő sorszám szerint rendezve - követik egymást a memóriában. Minden sor előtt egy 2 byte-os mutató áll, amelyik a következő sor elejére (pontosabban az azt megelőző mutató első byte-jára) mutat. Ezt követi a sorszám 2 byte-on. A programsorban előforduló BASIC alapszavakat egyetlen byte-on tárolja. Ennek a byte-nak az értékét az illető alapszó tokenjének hívjuk. A " £ $ % ( ) , : ; jeleket a megfelelő ASCII kóddal ábrázolja. Az idézőjelek közötti szövegkonstansokat, a REM utasításban szereplő karaktereket ugyancsak ASCII kódjukkal ábrázolja. A programsorok végét egy 0 byte jelzi.

Foglalt szavak
4k verzió:

ABS CLEAR DATA DIM END FOR
GOSUB GOTO IF INPUT INT LET
LIST NEW NEXT PRINT READ REM
RESTORE RETURN RND RUN SGN SIN
SQR STEP STOP TAB THEN TO
USR          

8k verzió:
Az összes előbb felsorolt szó, továbbá az alábbiak:

ASC AND ATN CHR$ CLOAD CONT
COS CSAVE DEF EXP FN FRE
INP LEFT$ LEN LOG MID$ NULL
ON OR NOT OUT PEEK POKE
POS RIGHT$ SPC STR$ TAN VAL
WAIT          

Konstansok
A 4K verzióban csak valós (lebegőpontos) számkonstansokat használhatunk.
A valós számkonstansok egymás utáni összetevői a következők lehetnek: előjel, egészrész, tizedespont, törtrész, kis vagy nagy E betű, kitevő. Az egészrész és törtrész decimális számjegyek sorozata. Ha az előjelet elhagyjuk, a szám pozitív lesz. A számokat megadhatjuk tizedes és hatványkivevős alakban is. A szám első hét számjegye szingifikáns. A legnagyobb ábrázolható szám: 1.70141E+38. A legkisebb, még ábrázolható pozitív szám 1^-38.
A számkonstansok megjelenítésének szabályai:

  1. A pozitív előjel helyett szóközt tesz a szám elé a BASIC.
  2. Ha a szám abszolút értéke 0 és 999999 közé eső egész szám, egész számként kerül kinyomtatásra.
  3. Ha a nem egész szám 0,01 és 999999.9 köz esik, fixpontos jelöléssel jelenik meg.
  4. Ha a szám nem a 2., vagy 3. pontnak megfelelő alakú, a számot exponenciális formában, normálalakban jeleníti meg a BASIC.

Példák helyes számkonstansokra:

Szám: Kiírt alak:
+1 1
-1 -1
6523 6523
06523 6523
1E20 1E+20
-12.3456E-7 -1.23456E-06
1000000 1E+06
0.1 .1
.001 1E-03
.000123 1.23E-04

A 4K verzióban szövegkonstansokat csak a PRINT utasítás paramétereként használhatunk. Ezen konstans maximális hosszát csak az köti meg, hogy a képernyőről legfeljebb 78 karakter hosszú sort lehet bevinni. A szövegkonstansokat idézőjelek közé kell zárni, de a záró idézőjel elhagyható. Két egymást követő zárójel ("") üres stringet jelöl, ez nem egyenlő a CHR(0)-val.
Szövegkonstans típusú változók - és string műveletek - használatára csak a 8K verzióban van lehetőség, az ilyen típusú változókban maximum 25 karakter hosszú szövegfüzéreket tárolhatunk.

Operátorok
Operátoroknak nevezzük a különféle műveleti jeleket, amelyek összekapcsolják a kifejezésben szereplő operandusokat. Az operandusok alatt változókat, konstansokat, függvényértéket értünk, de bármelyik operandus lehet egy újabb kifejezés.

- negálás (Pl.: a=-a)
^ hatványozás (csak a 8K-s változatban)
*, / szorzás, osztás
+, - összeadás, kivonás
= egyenlő
<> nem egyenlő
< kisebb
> nagyobb
<= kisebb vagy egyenlő
>= nagyobb vagy egyenlő

Egyenrangú műveletek esetén a kiértékelés balról jobbra haladva történik meg. A kiértékelés sorrendjét természetesen a zárójelek használatával megváltoztathatjuk.

63 AND 16 = 16
4 OR 2 =6

Szintaktikai szabályok
A BASIC program programsorokból áll, minden sor sorszámozott. Egy sorban több utasítás is állhat, kettősponttal elválasztva. A programsor maximális hossza 71 karakter. Az egyes nyelvi elemek között tetszőleges számú szóköz karakter állhat, mint elválasztó karakter, de ez akár teljesen el is hagyható (ez a program olvashatóságát persze nagymértékben rontja). Az alábbi három program lefuttatása egymással egyenértékű eredményt ad:

10 A$="Altair 8800"
20 FOR I=1 TO LEN(A$)
30 PRINT MID$(A$,I)
40 NEXT I

10 A$="Altair 8800": FOR I=1 TO LEN(A$): PRINT MID$(A$,I): NEXT I

10A$="Altair 8800":FORI=1TOLEN(A$):PRINTMID$(A$,I):NEXTI

A változókat - beleértve a maximum 11 elemű tömböket - az első használat előtt nem szükséges deklarálni, ebben az esetben a valós változók kezdőértéke 0, a string-változóké üres szövegfüzér.

Parancsok és utasítások

CLEAR  
 
Törli a változókat. A tárban lévő program sértetlen marad.
A 8k-s verzióban még egy funkciója van az utasításnak: a stringek tárolására fenntartott (alapértelmezés szerint 50 byte) helyet állíthatjuk be, az alábbi formában használva: <CLEAR aritmetikai kif.>
A CLEAR 200 utasítás hatására a szövegfüzérek tárolására fenntartott hely 200 byte lesz, a BASIC program tárolására ennyivel kevesebb hely marad, amiről a FRE függvénnyel meg is győződhetünk. (A sting-kifejezések eredményeiként előálló szövegfüzérek a BASIC munkaterület végén tárolódnak.)
Parancs üzemmódban is használható.
CLOAD  
  (Csak a 8k-s változatban)
Eredetileg a megadott nevű programot betölti kazettáról. Az Enterprise változatban hatástalan.
CONT  
 
(Csak a 8k-s változatban)
A STOP, vagy END utasítással, vagy a CTRL+C, STOP billentyűkkel megszakított program végrehajtását folytatja a programmegszakítás helyétől. A STOP utasítás felhasználásával ellenőrzőpontok iktathatók be a programba, majd megállítás - és pl. a változók értékeinek ellenőrzése - után a CONT-tal folytatható. A CONT parancs nem hajtható végre, ha a programon változtattunk, vagy hibával állt le.
Csak parancs módban használható.
CSAVE  
  (Csak a 8k-s változatban)
Eredetileg a tárban lévő programot a megadott néven kimenti kazettára. Az Enterprise változatban hatástalan.
DATA  
 
A DATA utasítás nagy mennyiségű adat (számokat, stringeket) tárolására alkalmas, melyeket a READ utasítás segítségével olvashatunk be változóba, abban a sorrendben, ahogy a DATA utasításban követik egymást. A konstanslista elemei egymástól vesszővel elválasztott konstansok. A szövegkonstansokat nem szükséges idézőjelek közé rakni, kivéve, ha tartalmaz vessző karaktert is.
A DATA utasításokban tárolt adatok beolvasási sorrendje a RESTORE utasítással megváltoztatható.
Csak program üzemmódban használható.
DEF  
 
(Csak a 8k-s változatban)
Az utasítás segítségével aritmetikai függvényt definiálhatunk, melyre aztán az FN függvényhívás segítségével hivatkozhatunk. Minden a felhasználó által definiált függvénynek egyetlen paramétere lehet, de a program változóinak értékét felhasználhatjuk a kifejezésben. Alakja:
  DEF FN<azonosító>(paraméter)=<aritmetikai kif.>
Az azonosító (a függvény neve) maximum 5 karakterből állhat, de csak az első két karakter szignifikáns. Az FN foglalt szó és az azonosító között nem állhat szóköz. A paraméter valós típusú változó. A függvényt definiáló aritmeti9kai kifejezés legfeljebb egy sornyi lehet.
Csak program módban használható.
Pl:
  DEF FNSEC(X)=1/COS(X)
  DEF FNSCS(X)=1/SIN(X)
DIM  
 
A DIM utasítást követően megadott nevű, típusú tömbváltozót deklarálja a zárójelben megadott felső indexhatárokkal. 14755 Az alsó indexhatár minden esetben 0, a megadható felső indexhatár elvileg 14755, de ez a 8K verzióban is OM (elfogyott a memória) hibakódot eredményez. Egymás után több tömbváltozót is létrehozhatunk egy DIM utasítással. A 4K-s verzióban csak egydimenziós tömb definiálására van lehetőség, a 8K-s verzióban a dimenziók száma nincs korlátozva, a memória mérete miatt azonban maximum 7 dimenziós tömböt hozhatunk létre, de ez is csak elméleti lehetőség.)
Parancs üzemmódban is használható.
Pl:
  DIM A(3),B(10)
  DIM C$(5,6)
  DIM A(N,N*2)
END  
 
Az END végrehajtása a program futásának azonnali befejezését jelenti, ha a program tartalmaz magasabb sorszámú sort, az nem hajtódik végre. A CONT parancs a program futtásának folytatását eredményezi.
Az interpreter parancs üzemmódban is végrehajtja, bár ennek nyilvánvalóan nincs értelme.
FOR  
 
Ciklusszervező utasítás, növekményes ciklusnak is nevezik, mert a ciklusmag egy ciklusváltozó egymás utáni értékeire hajtódik végre egy kezdőértéktől egy végértékig. A FOR ciklus szerkezete:

FOR utasítás
utasítások (ciklusmag)
NEXT ciklusváltozó

A FOR utasítás a FOR kulcsszóból, az azt követő ciklusváltozó azonosítójából, az értékadás-szimbólumból ( = ), a ciklusváltozó kezdeti értékét meghatározó kifejezésből, a TO kulcsszóból, a ciklusváltozó végértékét meghatározó kifejezésből, valamint a STEP kulcsszóból és a lépésközt meghatározó kifejezésből áll. Ha a kívánt lépésköz egy, a STEP és az azt követő kifejezés el is maradhat:

FOR ciklusváltozó=kifejezés1 TO kifejezés2 STEP kifejezés3
FOR ciklusváltozó=kifejezés1 TO kifejezés2

A lépésköz negatív is lehet, ebben az esetben a kifejezés2 értékének kisebbnek kell lennie, mint a kifejezés1 értéke. Ha a kifejezés1 (a ciklusváltozó kezdeti értéke) nagyobb mint a kifejezés2, és nincs STEP, vagy van de a kifejezés3 értéke pozitív, a ciklusmag akkor is lefut egyszer a ciklusváltozó kezdeté értékével.
A ciklusváltozó értéke a ciklusmagban felhasználható. Az interpreter nem tiltja, hogy a ciklusmagban a ciklusváltozónak nyíltan értéket adjunk, de ez egyáltalán nem javasolt, kiszámíthatatlan programfutást és végtelen ciklust eredményezhet. (ezt a lehetőséget felhasználhatjuk viszont egy FOR ciklus feltételtől függő, idő előtti befejezésére) A FOR utasításban szereplő kifejezés egyetlen alkalommal (a ciklusba belépéskor) értékelődnek ki. A ciklusmagot a NEXT utasítás határolja. A NEXT kulcsszót a ciklusváltozó azonosítója követi (a 8k-s verzióban a NEXT után a ciklusváltozó már elhagyható, ez még gyorsít is a programon).
Az interpreter megengedi a FOR utasítások egymásba ágyazását is.
FOR ciklust parancsmódban is használhatunk.
Pl:

  10 FOR I=1 TO 10
  20 PRINT I
  30 NEXT I

GOSUB  
 
Alakja: GOSUB <sorszám>
Végrehajtja a GOSUB után megadott sorszámú programsorban kezdődő alprogramot. Az alprogram végét a RETURN kulcsszó jelzi. Ez azt jelenti, hogy feltétel nélküli vezérlésátadás jön létre a GOSUB utasításban megadott számú sorra. Amikor ezt követően a legközelebbi RETURN utasításhoz ér a program, a vezérlés visszakerül a GOSUB utasítást követő utasításra.
A GOSUB utasítások egymásba ágyazhatóak. Ennek azonban határt szab - nem csak a program áttekinthetősége -, hanem a verem nagysága is.
Parancs módban is használható.
GOTO  
  Alakja: GOTO <sorszám>
Feltétel nélküli vezérlésátadás. A program a GOTO utasításban megadott számú sor végrehajtásával folytatódik.
Parancs üzemmódban is használható.
IF  
 
Feltételes vezérlésátadást hoz létre, attól függően, hogy az IF kulcsszót követő feltétel teljesül-e, vagy sem. Ha igen, akkor a THEN kulcsszót követő utasítás / utasítások kerülnek végrehajtásra, ha nem, akkor a következő programsorra kerül a vezérlés.
Alakja:

  IF <logikai kif.> THEN <utasítás>

Mivel az igaz ág utasításait csak a THEN kulcsszó után lehet írni, egyetlen programsorba, nagyon gyakori az IF feltétel THEN GOTO <sorszám> szerkezet. Az interpreter megengedi, hogy ilyen esetben a GOTO kulcsszót elhagyjuk:

  IF <logikai kif.> THEN <sorszám>

Az IF szerkezetet parancs módban is használhatjuk.

INPUT  
 
Az utasítás lehetővé teszi, hogy a billentyűzetről közvetlenül adatokat adjunk át egy futó BASIC programnak. Alakja:
INPUT <változólista>
A változólista egy, vagy több (egyszerű-, vagy tömb-) változót tartalmaz, vesszővel elválasztva. Az utasítás végrehajtásakor egy kérdőjel jelenik meg a kurzor aktuális pozíciójában és a program adatbevitelre vár az ENTER megnyomásáig. Ha több változót vár az INPUT, azokat vesszővel elválasztva adhatjuk meg, vagy egyenként, minden érték bevitelét ENTER-rel lezárva.
Mivel a megjelenő kérdőjel nem segíti a program felhasználóját, hogy megértse mit vár tőle a program, gyakori megoldás a PRINT és az INPUT egymás utáni használata. Pl.:
  PRINT "Hany eves vagy";:INPUT E

Az előbbi példában szereplő PRINT utasítás "megspórolására" a 8k-s verzióba az INPUT utasítást az alábbi formában is használhatjuk:
INPUT "szöveg";<változólista>
Az utasítás hatására először az idézőjelben szereplő szöveg jelenik meg, és a kérdőjel és cask azután vár adatbevitelre. Pl:
  INPUT "Hany eves vagy";E
Természetesen a "szöveg" rész elhagyható, ebben az esetben az INPUT működése azonos a 4k-s változatban megszokottal.

A 8k-s változatban hibát okoz, hogy ha számot vár az INPUT és szövegfüzért adunk meg. A 4k-s változatban mindenképen számot vár az utasítás, ezért a beolvasást az első betűig végzi. Pl. ha csak betűket adunk meg, a beolvasott érték nulla lesz.
Az INPUT csak program módban használható.

LET  
 
Értékadó utasítás. Alakja:
  LET <valós változó>=<aritmetikai kif.>
  LET <string változó>=<string kif.>

A LET kulcsszó kiírása nem kötelező. Ha egy utasítás első karaktere nem token, akkor az interpreter LET-et tételez fel.
A megadott változó az egyenlőségjel jobb oldalán álló kifejezés értékét veszi fel. A változók egyszerű és tömbváltozók is lehetnek. A változók értékei akárhányszor, a program bármely részén megváltoztathatók. Az Altair BASIC nem ismeri a lokális- és globális változók fogalmát. Ez különösen az alprogramok megtervezésekor okozhat problémát. Ha egy rutint a program több részéről is meghívunk, akkor változóit más célokra nem célszerű használni.
Parancs üzemmódban is használható.
LIST  
  Alakja:
  LIST
  LIST <sorszám
>
A tárban lévő programot listázza ki a megadott sorszámú sortól, vagy a program elejétől kezdve.
Program üzemmódban is használható.
NEW  
 
Törli a memóriában tárolt programot és a változókat. Az utasítás valójában nem törli a memória tartalmát, csupán a BASIC munkaterülethez kapcsolódó mutatókat állítja kezdőértékükre. Az interpreter ezután úgy tekinti, hogy üres a tár.
Parancs és program üzemmódban is használható.
NEXT  
 
A FOR ciklus végét jelző utasítás. Alakja:
  NEXT <ciklusváltozó>
(a 8k-s verzióban a NEXT után a ciklusváltozó már elhagyható.)
Az utasítás hatására a vezérlés közvetlenül a NEXT-nek megfelelő FOR-t követő első utasításra kerül, feltéve, hogy a STEP-ben specifikált értékkel - ennek hiányában eggyel - megnövelt ciklusváltozó még mindig a megengedett tartományba esik. Ha nem, a NEXT-et követő első utasítás hajtódik végre.
Lásd még a FOR utasítást.
ON  
 
(Csak a 8k-s változatban)
Többirányú elágazást tesz lehetővé a GOTO vagy GOSUB utasításokkal együtt használva. Formája:
  ON <aritmetikai kif.> GOSUB <sorszámlista>
vagy
  ON <aritmetikai kif.> GOTO <sorszámlista>
A sorszámlista egymástól vesszővel elválasztott előjel nélküli egész konstansokat tartalmaz. Az aritmetikai kifejezést értékeli ki először az interpreter (az értékének 0-255 intervallumba kell esnie), majd a sorszámlista annyiadik elemének megfelelő programsorra adódik át a program vezérlése. Ha a kifejezés értéke 0, a programvégrehajtás az ON ... GOTO / ON ... GOSUB utasítást követő soron folytatódik.
GOSUB esetén a verembe még a visszatérést biztosító információk is bekerülnek.
Példa:
  ON (INT(RND(1)*5))+1 GOTO 100,200,300,400,500
OUT  
  Csak a 8k-s verzióban.
Alakja:
  OUT I,J
Az I számú portra adatot (J) ír ki. Az I, J aritmetikai kifejezés, értéküknek a 0-255 intervallumba kell esnie.
POKE  
 
Csak a 8k-s verzióban.
Az utasítás segítségével egy tetszőleges RAM címre közvetlenül beírhatunk egy byte értéket. Alakja:
  POKE aritm.kif1,aritm.kif2
Az aritm.kif1 a memóriacímet jelöli, értékének 0-65535 közé kell esnie. Az aritm.kif2 a beírandó érték, értékének 0-255 közé kell esnie.
Parancs- és program üzemmódban is használható.
PRINT  
 
Aritmetikai kifejezéseket, változók értékeit, szövegfüzéreket nyomtat az elsődleges kimenetre, általában a képernyőre. A szövegfüzéreket idézőjelek között kell megadni. A nyomtatási kép kialakítására használhatjuk a következő szeparátorokat: vessző (,), pontosvessző (;), SPC, TAB függvények.
Ha a kiírandó elemeket pontosvesszővel választjuk el egymástól, a nyomtatás a következő karakterhelytől folytatódik, ha vesszővel -, a következő tabulátor pozícióban. Ha a PRINT utasítást nem zárja szeparátor, automatikusan CR/LF karakterpár is kiírásra kerül (azaz a következő PRINT új sorban folytatja a kiírást.
A 8k-s verzióban nem csak megjeleníthető karaktereket tartalmazó szövegfüzéreket írhatunk ki, hanem vezérlő karaktereket is (a CHR$ függvény segítségével). A 26-os ASCII kód kiírásával (PRINT CHR$(26)) képernyőtörlést hajthatunk végre.
A 8K-s változatban a PRINT kulcsszó helyettesíthető a kérdőjellel (?).
Pl:
  PRINT "2+3=";2+3
  PRINT A,B,C
  ?"Altair 8800"
READ  
 
A DATA utasításokban definiált értékeket olvassa be sorban és rendeli hozzá az utasításban megadott változókhoz. Alakja:
  READ <változólista>
A változólista tetszőleges típusú, egymástól vesszővel elválasztott egyszerű- vagy tömbváltozókat tartalmaz. Legalább egy változó megadása kötelező. Hibát eredményez, ha a változó és a DATA utasításban talált érték típusa nem felel meg egymásnak, vagy ha a DATA utasításokban tárolt adatok elfogytak. (Ezen segíthet a RESTORE utasítás).
REM  
  Lehetővé teszi megjegyzések (tetszőleges karaktersorozat) beírását a program szövegébe. Az interpreter a REM észlelésétől a sor maradék részét már nem hajtja végre, hanem a következő sor elejétől folytatja a program végrehajtását.
RESTORE  
  Az utasítás hatására a READ újra az első DATA sorból olvassa a következő értéket.
RETURN  
  Az utasítás hatására a program vezérlése az utolsó GOSUB utasítást követő első utasításra kerül.
RUN  
 
Alakja:
  RUN
  RUN <sorszám
>
A memóriában tárolt programot az elejétől (a legalacsonyabb sorszámú sortól), vagy a megadott sorszámú sortól futtatja. Törli a változókat, és legelső DATA sor lesz aktuális.
Program üzemmódban is használható.
STEP  
  Lásd FOR.
STOP  
 
Megállítja a program futását, a 8k-s verzió kiírja, hányadik sorban állt meg a program. A program futtatása a CONT utasítással folytatható. Az utasítást elsősorban programfejlesztés során használjuk, segítségével töréspontokat helyezhetünk el a programban. A program megszakítása után a PRINT segítségével ellenőrizhetjük a program változóinak értékét.
THEN  
  Lásd IF.
TO  
  Lásd FOR.
WAIT  
 
Csak a 8k-s verzióban.
Alakja: WAIT I,M1,M2 vagy WAIT I,M1
Ahol 0 <= I, M1, M2 <= 255.
Az utasítás felfüggeszti a program végrehajtását, amíg a paramétereiben specifikált esemény be nem következik. Az I kifejezés egy port címét jelenti. Az utasítás először kiszámítja az (INP(I) EOR M2) AND M1 értékét (EOR) a kizáró VAGY). Ha az eredmény nullától különböző a program végrehajtása a következő sortól folytatódik. Ha az eredmény nulla, az interpreter a fenti műveletet - akár a végtelenségig - ismétli. I-nek tehát olyan címnek kell lennie, amit megszakító rutin vagy a perifériák használnak. Ha M2-t nem adtuk meg, akkor az értéke nulla, tehát csak a INP(I) AND M1 hajtódik végre.
Az az esemény, amelyik a BASIC program futásának folytatását eredményezi az I port értékének valamely bitjének magasba és/ vagy alacsonyra állítódása lehet. Az M1-ben magasra kell állítani azokat a biteket, amelyek értékére kíváncsiak vagyunk, a többit pedig alacsonyra. M2-ben azokat a biteket kell magasra állítani, amelyek értékének alacsonyra kell váltania a futás folytatásához. Ha például M1 = 00011000 = 24 és M2 = 00010000 = 16, akkor a program addig áll, amíg I port 4 bitje alacsony és 5. bitje magas nem lesz.

Függvények

Az Altair BASIC-ben valamennyi függvénynek (a MID$ függvény kivételével) egy vagy két argumentuma van, akkor is, ha az csak formális paraméter. Ezért a függvények alakja minden esetben a következő:

  függvénynév(argumentum1)

vagy

  függvénynév(argumentum1,argumentum2)

ABS  
  Az ABS függvényt zárójelben követő aritmetikai kifejezés abszolút értékét adja. Az ABS mindig egy nem negatív értékkel tér vissza:
ABS(3) = 3
ABS(0) = 0
ABS(-2) = 2
ASC  
  (Csak a 8k-s változatban)
A paraméterként megadott szövegfüzér első karakterének ASCII kódját adja:
ASC("ABC") = 65
ATN  
  Csak a 8k-s verzióban.
A radiánban megadott szög árkusz tangensének főértékét adja.
CHR$  
  Csak a 8k-s verzióban.
A megadott ASCII kódszámú karaktert adja vissza. A paraméternek a 0-255 intervallumba kell esnie.
COS  
  (Csak a 8k-s változatban)
A radiánban megadott szög koszinuszát számítja ki.
EXP  
 
(Csak a 8k-s változatban)
Exponenciális függvény, e^x kiszámítására szolgál, ahol e egy matematikai állandó, a természetes alapú logaritmus alapja, értéke körülbelül 2.718281828
FN  
  Csak a 8k-s verzióban.
A DEF utasítással definiált függvényt hívja meg. Alakja:
  FN<azonosító>(paraméter)
Példa:
  PRINT FNSEC(3)
  LET A=FNCSC(3)
FRE  
 
Csak a 8k-s verzióban.
Ha a függvény paramétere numerikus kifejezés (pl. FRE(0)), megadja byte-ban, a BASIC munkaterület számára meglévő szabad memóriaterületet.
Ha a függvény paramétere tetszőleges string típusú kifejezés (pl. FRE("")), megadja byte-ban a szövegfüzérek tárolására rendelkezésre álló szabad memóriaterületet. Ez kezdetben 50 byte, melyet a CLERAR utasítással módosíthatunk.
INP  
  Csak a 8k-s verzióban.
A megadott számú portról olvas be adatot. A kifejezés értékének a 0-255 intervallumba kell esnie.
INT  
  Az argumentum egész részét adja. : INT(3.6) = 3
Ha egy számot valóban kerekíteni akarunk, akkor 0.5-öt hozzá kell adni, és utána venni az egész részét: INT(X+.5)
LEFT$  
  Csak a 8k-s verzióban.
A string függvény egy adott szövegfüzér megadott számú első karakteréből egy új string-et képez. Formája:
  LEFT$(<szövegfüzér>,<aritmetikai kif.>)
Pl.:
  LEFT$("Kovacs Peter",6) = "Kovacs"
LEN  
  Csak a 8k-s verzióban.
A paraméterként megadott string-kifejezés karakterhosszát adja meg.
LOG  
  Csak a 8k-s verzióban.
Aritmetikai függvény, amely argumentumának e alapú logaritmusát számolja ki, Az EXP függvény inverze.
A függvény segítségével tetszőleges Y alapú logaritmusát is kiszámolhatjuk X-nek: LOGy(X)=LOG(X)/LOG(Y)
MID$  
 
Csak a 8k-s verzióban.
2 vagy 3 paraméteres string függvény, mely az első paraméterként megadott szövegfüzér bizonyos egymás után következő karaktereiből egy új stringet állít elő.
  • Kétparaméteres alak:
      MID$(<szövegfüzér>,<aritmetikai kif.>)
    Egy adott szövegfüzér elejéről törli a második paraméterben megadott számú karaktert. Pl.:
      MID$("Kovacs Peter",8) = "Peter"
    Az aritmetikai kifejezés értékének a 0-255 intervallumba kell esnie, és ha értéke nagyobb, mint a szövegfüzér hossza, üres stringet kapunk eredményül.

  • Háromparaméteres alak:
    MID$(<szövegfüzér>,<aritm.kif.1>,<aritm.kif.2>)
    Az aritm.kif.1 a szövegfüzér azon karakterét adja meg, ahonnan az új string kezdődik, az aritm.kif.2 az átmásolandó karakterek számát adja meg. Ha nincs a paraméterként szereplő string-ben már ennyi karakter, akkor string végéig másolja át a karaktereket.
    Mindkét aritmetikai kifejezés értékének a 0-255 intervallumba kell esnie.

A LEFT$ és a RIGHT$ függvények a MID$ segítségével kifejezhetők:
LEFT$(X$,N) = MID$(X$,1,N)
RIGHT(X$,N) = MID$(X$,LEN(X$)-N+1)

NULL  
   
PEEK  
  Csak a 8k-s verzióban.
Az argumentumként megadott sorszámú memóriacímen lévő byte értékét adja. A kifejezés értékének a 0-65535 intervallumba kell esnie.
POS  
 
Csak a 8k-s verzióban.
Megadja, hogy a kurzor hány karaktert mozdult el az aktuális képernyő sorban (vagyis a kurzor pillanatnyi pozíciója a visszaadott értéknél eggyel nagyobb). A függvénynek formális paramétere van, értéke lényegtelen. Általában POS(0) alakban használatos.
RIGHT$  
  Csak a 8k-s verzióban.
A string függvény egy adott szövegfüzér megadott számú utolsó karakteréből egy új string-et képez. Formája:
  RIGHT$(<szövegfüzér>,<aritmetikai kif.>)
Pl.:
  RIGHT$("Kovacs Peter",5) = "Peter"
RND  
  Forma:
  RND(aritmetikai kifejezés)
0-1 zárt intervallumba eső pszeudo-véletlen számokat generál. Az RND utasítás természetesen nem állít elő "igazi" véletlen számokat. Az argumentum előjele határozza meg, milyen eljárás segítségével számítja ki az interpreter a következő számot:

  • Amennyiben az RND függvény argumentuma negatív, az interpreter inicializálja a véletlenszám-generátor rutint. A véletlenszám-generátort elég egyszer inicializálni, mert ha ezt újra megtesszük, bizonyos szabályosság azonnal keletkezik a végrehajtási időben.
  • Ha az argumentum nulla, a függvény újra az előző véletlen számot "állítja elő".
  • Ha az argumentum pozitív, a függvény a következő véletlenszámot generálja.
A és B közötti véletlenszámot generálhatunk az alábbi kifejezéssel: (B-A)*RND(1)+A
SGN  
 
A paraméterként megadott aritmetikai kifejezés előjelét adja vissza (ha a kifejezés negatív, a visszaadott érték: -1, ha pozitív: 1, ha a kifejezés értéke nulla, a visszaadott érték is nulla).
SIN  
  A radiánban megadott szög szinuszt számítja ki.
A 4K-s verzióban nincs koszinusz függvény, ezt a SIN függvény segítségével számolhatjuk ki:
COS(x)=SIN(X+3.14159/2)
SPC  
 
Csak a 8k-s verzióban.
A paraméterként megadott számú szóközt nyomtat a kurzor aktuális pozíciójától kezdve. A függvény csak a PRINT utasításban szerepelhet. Az SPC és a ( jel között nem lehet szóköz. A paraméter értékének - lefelé kerekítés után - a 0-255 intervallumba kell esnie.
SQR  
  Az argumentum négyzetgyökét számolja ki.
SQR(X)=X^0.5
STR$  
  Csak a 8k-s verzióban.
Az argumentumként megadott aritmetikai kifejezés értékének sting-alakját adja. Pl:
STR$(123) = "123"
STR$(-1000000) = "-1E+06"
TAB  
 
Amennyiben a kurzor pillanatnyi vízszintes pozíciója az adott sorban kevesebb, mint a TAB paramétereként megadott érték, addig a pozícióig szóközöket nyomtat. A függvény csak a PRINT utasításban szerepelhet. A TAB és a ( jel között nem lehet szóköz.
TAN  
  Csak a 8k-s verzióban.
A radiánban megadott argumentumának tangensét számítja ki.
tg(x)=sin(x)/cos(x)
USR  
 
A paraméterként megadott memóriacímen kezdődő gépi kódú programot hajtja végre. A paraméter értékének a 0-65535 intervallumba kell esnie.
VAL  
 
Csak a 8k-s verzióban.
A paraméterként megadott string-kifejezést számmá konvertálja. A konverziót az első nem szám karakterig végzi.
Mivel az INPUT utasítás nem végez típusellenőrzést, hibát és a programfutás megszakadását okozza, ha a felhasználó szám helyett szövegfüzért ad meg a programnak (csak a 8ks- változatban). Az ilyen hibát lehet kivédeni azzal, ha az INPUT utasítással szövegfüzért olvasunk be, majd ezt alakítjuk számmá a VAL függvénnyel. Pl.:

VAL("123.321") = 123.321
VAL("-123") = -123
VAL("1.2 E2") = 120
VAL("1.2.3") = 1.2
VAL("12ab") = 12
VAL("ab12") = 0

Hibakódok

4K és 8K verzióban:

BS Bad Subscript.
Tartományon kívüli tömbindex. Pl. DIM A(20) utasítás után LET A(21)=...
DD Double Dimension.
Duplán deklarált tömbazonosító. Már létező tömb nevével kíséreltünk meg újabb tömböt létrehozni.
FC Function Call error.
A meghívott függvénynek hibás paramétert kíséreltünk meg átadni, vagy a tömbhivatkozás indexe negatív szám. Akkor fordulhat elő:
- ha a LOG függvényt nulla, vagy negatív értékkel, az SQR függvényt negatív értékkel hívjuk meg,
- a MID$, LEFT$, RIGHT$, INP, OUT, WAIT, PEEK, POKE, TAB, SPC függvényekben, vagy az ON ... GOTO utasításban rossz paramétert adunk meg.
ID Illegal Direct.
A DEFFN függvénydefiníciót, vagy 8K-s verzióban az INPUT utasítást parancsmódban akartuk használni.
NF NEXT without FOR.
A NEXT utasításhoz nem tartozik FOR ciklusszervező utasítás.
OD Out of Data.
A DATA sorokban definiált adatlista végére ért a program, és újabb READ utasítással próbált belőle adatot olvasni. A DATA sorokban több adatot kell megadni, vagy a RESTORE utasítást kell használni.
OM Out of Memory.
Elfogyott a memória. A program túl nagy, túl sok változót használ, vagy túl sok FOR ciklusszervező utasítás, GOSUB szubrutinhívás van egymásba ágyazva.
OV Overflow. Szám túlcsordulás.
Az aritmetikai kifejezés értéke túl nagy ahhoz, hogy a BASIC számformátumában ábrázolni lehessen. Ha alulcsordulás történik (azaz a kifejezés értéke kisebb, mint a legkisebb ábrázolható szám), akkor a művelet eredménye nulla, és a végrehajtás hibajelzés nélkül folytatódik!
SN Syntax Error.
Szintaktikai hiba. Pl. Hiányzik egy zárójel, érvénytelen karakter szerepel az utasításban.
RG RETURN without GOSUB.
A RETURN utasításhoz nem tartozik GOSUB. Pl. a főprogram nincs megfelelően elkülönítve a szubrutinoktól, és a végrehajtás valamelyik szubrutinra fut.
US Undefined Statement.
A GOTO, GOSUB, THEN utasításokban hivatkozott sorszámú programsor nem létezik.
/0 Division by Zero.
Nullával való osztás.

Csak a 8K verzióban:

CN Continue error.
A program folytatása nem lehetséges (a CONT utasítással). Vagy azért, mert a program futása hiba miatt szakadt meg, vagy a program megszakítása után módosítottuk a programot.
LS Long String.
Kísérlet történt az összefűzési operátor használatával 255 karakternél hosszabb karakterlánc létrehozására.
OS Out of String Space.
A karakterláncok tárolására fenntartott memóriaterület betelt.
ST String Temporaries.
Egy karakterlánc típusú kifejezés túl összetett. Kettő vagy több rövidebbre kell felosztani.
TM Type Mismatch.
Típus eltérés. Pl. egy numerikus változóban szövegfüzér típusú kifejezést akarunk tárolni (LET), vagy a meghívott függvénynek adtunk meg rossz típusú kifejezést paraméternek.
UF Undefined Function.
Hibás függvényhívás. Nem létező (nem definiált) függvényt kíséreltünk meghívni.

Vissza