Home | Artikel | VCFe Basic Interpreter

VCFe Vortrag vom 2007.04.28 - Basic Interpreter - am Beispiel von Commodore 64 und Dragon 32


Inhalt

Einführung

Durch den Mikroprozessor wurde Hardware für die Massen erschwinglich. Plötzlich brauchte man, dank eines Chips, der anfänglich wenige $100 kostete und später auf unter $10 fiel (sowie die dazu passenden ähnlich billigen Halbleiterspeichern), keine grossen schweren und $10'000e teuren Minicomputer mit TTL Prozessoren (und ebenso teuren Kernspeichern) mehr.

Aber neben Platz und finanziellen Aufwand gab es schon zur Minicomputer Zeit auch andere Gründe warum nur wenige Leute Computer benutzen konnten: Man braucht auch Software. Und die war entweder nicht existent, oder extrem teuer, weil der Programmieraufwand gross war und unter wenigen Usern aufgeteilt werden musste.

Die Alternative eigene Software zu schreiben war noch teuerer, wenn man seine Zeit mit Geld aufwiegen musste, weil die vorhandenen Software Werkzeuge (batch-orientierte Assembler und Compiler) extrem umständlich waren, und "dank" Lochstreifen als einziges billiges Speichermedium auch sehr langsam. Diese traf einem vor allem beim Debuggen, das dank primitiven Sprachen mit vielen Bugquellen zusätzlich lange dauerte. Und man musste beim ersten Programm zusätzlich noch viel Zeit in dessen Erlernen stecken, weil man viele für die eigentliche Aufgabenstellung irrelevante Details erlernen musste.

Bei den ersten Mikrocomputern kam noch das komplette fehlen von Software dazu. Nicht mal Werkzeuge zum Software machen gab es. Nur die wenigsten Benutzer hätten mit handübersetzten Maschinencode ein Interesse daran gehabt. Und Lochstreifen hatten die Geräte auch keine von sich aus, also musste man selbst fertige Programme jedes mal wieder eintippen (und Tippfehler debuggen), bevor Audio-Tonband als Massenspeicher aufkam.

Erst durch den Basic Interpreter wurde Software für die Massen der Normalsterblichen nicht-Techniker schreibbar, und damit der Mikrocomputer für viele Anwender nutzbar, sei das durch interessierte Benutzer die nun selber schreiben konnten, oder durch kopieren von diesen. Basic ist damit ein genauso wichtiger Teil der Mikrocomputer Revolution wie der Mikroprozessor selber.

Der Vortrag teilt sich in 3 Sektionen:

Vor Basic: RAND, JOHNNIAC, JOSS

Basic war damals als es entstand für die meisten Leute eine Revolution. Aber es gab bereits davor ein ähnliches System, das heute fast vergessen ist. Um 1960 herum wurde im RAND Labor ein System namens JOSS entwickelt, das fast alle Eigenschaften von 1970er Basic hatte. JOSS lief auf einem Einzelstück Rechner namens JOHNNIAC, welcher zu dieser Zeit schon veraltet war. 4k*40bit RAM, 12k*40bit Disk, 20bit Befehle, 20KIPS. Und die 12 Fernschreiber für Multiuser/Timesharing Betrieb mussten erst noch addiert werden. Es gab keine Fliesskomma Rechnung, keine indirekte Addressierung, keine Interrupts, nicht mal Subroutinen. Aber dafür füllte der Rechner einen ganzen Raum.

Ziel war es, trotz Multiuser Betrieb, einen offenen Zugriff ohne Accounts zu haben, der Name JOSS stand auch für JOHNNIAC Open Shop System, also eine für jeden offene Werkstatt. Der Benutzer soll einfach ein freies Terminal finden können, dies einschalten und loslegen. Es gab keine Files die beschützt werden müssen, also war keine Security nötig. Die Disk war ohnehin nur 3 mal RAM gross, und nur für Swap benutzt. Das System sollte in erster Näherung als "Taschenrechner" laufen (damals waren nicht mal elektronische Tischrechner erfunden) und einfach Kommandos ausführen. Nebenbei sollte es auch als Kommandos eingegebenen Programcode aufzeichnen und später ausführen, wie heute ein programmierbarer Taschenrechner.

Das resultierende System ist zwar ausgestorben, aber es hat einige auf ähnlichen Grundlagen aufbauende System inspiriert. Darunter auch Basic.

Ur-Basic: Dartmouth, Kenemy und Kurtz, GE265

Dartmouth College ist eine kleine Universität der freien Künste. Deren Studenten werden grösserenteils spätere Eintscheidungsträger. Nur etwa 25% sind Ingenieurs oder Wissenschafts Fachrichtungen. Nachdem es in den 1950ern klar wurde, dass Computer gesellschaftlich relevant werden, und nicht nur ein Werkzeug von Spezialisten, stellte sich dort die Frage wie man den zukünftigen Studenten zumindest ein Grundverständnis der Computerei beibringen kann, damit sie beim entscheiden nicht total verloren sind.

Dies musste aber geschehen, ohne sie dabei in "sinnlosen" Details zu ertränken, mit denen nur Techiker die die Innereien verstehen sich anfreunden können. Der Name Basic war ursprünglich ein Akronym, BASIC, das für Beginners All-purpose Symbolic Instruction Code steht, und somit genau auf diese Lern-Zielsetzung hinweist.

Die meisten dieser Details haben nur damit zu tun Berechnungen effizienter zu machen, also Programmiererzeit zu opfern, um Rechnerzeit (oder Speicherplatz) zu sparen. Dies machte damals, als Programmierer billig und Rechner teuer waren, halbwegs Sinn. Dem Basic-Miterfinder Thomas Kurtz half aber ein Erlebnis dieser Ansicht gegenüber kritisch zu werden: Er hatte nach mehrerer Monaten Assembler Programmierei 60 Minuten Debug Rechnerzeit verheizt, ohne zu einem Resultat zu kommen. Danach hatte er trotz "das ist ineffizient" Sprüchen es mit Fortran probiert, und in wenigen Versuchen ein Ergebnis bekommen, und dafür 5 Minuten Ablauf Rechnerzeit verbraucht. In korrektem Assembler hätte er es theoretisch in einiges weniger an Ablaufzeit geschafft, wären da nicht nicht die vielen abgebrochenen Debug-Läufe dazu aufaddiert. Er erkannte, Debuggen muss man bei Rechnerzeit Effizienzrechnungen mit einbeziehen, und dann sterben so simplizistische Ansichten. Leider geschieht dies nur allzu langsam, auch heute.

Aber auch Fortran hatte viele unnötigen Details, die bei viele Male Debuggen und dann nur ein mal ablaufen von Studentenprogrammen zum Nachteil werden. Auch die Alternative Algol (Vorläufer von Pascal) wurde verworfen, weil es zwar schön strukturiert ist, aber die Strukturierung ebenfalls als unnötige Details empfunden wurde, nur von Nutzen bei grossen Projekten. Vereinfachte Subsets der beiden Sprachen wurden probiert und dann verworfen, weil die entfernten Elemente zu zentral waren.

Auch der Betrieb mit Lochkarten (oder gar Lochstreifen) wurde als zu umständlich angeschaut. Statt dessen sollte der Benutzer nur einen Fernschreiber benutzen müssen. Sein Code wird direkt im Speicher (bzw auf Swapdisk Platz) temporär gespeichert, dort editiert, und von dort unsichtbar Compiliert und ausgeführt (und nach der Ausführung das Compilat weggeworfen). Damit entstand eine Umgebung wie bei JOSS, aber mit einem echten Compiler, damit grossse Programme möglich waren (weil kein Interpreter den Speicher teilen muss). Und die Programme liefen schneller als bei einem Interpreter.

Neben dem unsichtbaren Compilieren gab es auch sonst keine Trennung von System/Editor/Sprache/Ablauf. Alles erscheint aus einem Guss, alles ist immer präsent, auf einer einzigen Kommandozeile, keine Modi, keine inkonsistenten Syntaxe, keine Verwirrung dadurch.

Speziell war auch der verwendete Rechner, der GE265. Dieser war eine Kombination aus:

Beide Rechner haben Anschluss an ein gemeinsames Disklaufwerk. Der Datanet-30 tritt auch als "automatischer Operator" des GE235 auf. Der RUN Befehl sorgt einfach dafür, dass dieser sobald der GE236 frei wird dort den Compiler anwirft, und dann das Compilat anwirft, und danach das Compilat löscht, und am Schluss die auf Disk gespoolte Ausgabe auf dem Benutzer seinen Fernschreiber (langsam!) ausgibt.

Das Ur-Basic hatte, wegen diesem asymmetrischen Doppelprozessor Aufbau, keinen INPUT Befehl, weil es zur Laufzeit vom GE235 aus keinen Zugriff auf den Fernschreiber des Benutzers hatte, und man den GE235 nicht mit auf Benutzereingaben warten lassen blockieren wollte, da kein Prozessumschalten auf dem Einzelprogram GE235 möglich war, und der Datanet-30 nicht genug Kontrolle dafür ausüben konnte. Daher gab es für Eingabedaten DATA Zeilen im Programmcode (es waren auch keine Files auf Disk möglich!) und den READ Befehl der aus diesen las. Ausgabe war bereits normal mit PRINT, da dies auf Disk gespoolt wurde, und ebenfalls nach der Ausgabe automatisch wieder gelöscht wurde.

Verbreitung: Minicomputer, PDP-8, HP2000

Auch den Minicomputer Herstellern der 1960er war klar, dass selbst Fortran noch nicht das Bestmöglichste war, um Programmieren genug zu vereinfachen, zum alle potentiellen Kunden eine genug einfache (Programmier-)Lösung ihrer Rechnungsaufgaben verkaufen zu können. 2 Firmen fanden in Basic ihre Lösung: DEC welche ein Basic für ihre PDP-8 Rechner herausgab, und HP welche dies für ihre 2000er Serie machte. DEC vermarktete eine PDP-8 mit 2-8 4kWort Bänke Speicher, 1 für den Basic Interpreter und 1-7 für die Benutzerprogramme von 1-7 Fernschreiber Benutzern an Schulen (als Educ8, ausgesprochen Educate). Auf diese Weise wurde Basic aus der Uni in die Welt hinausgetragen, und vielen Leuten bekannt. Auch HP hatte ihren Anteil, der Apple I und ][ Erbauer Steve Wozniak war ein ex HP Mitarbeiter.

Hier wurde gezielt von Compiler auf Interpreter umgestellt. Einerseits waren die Rechner schneller im interpretieren, weil modernerer Befehlssatz. Anderseits langsamer im Rechnen weil schmalere Register. Und zumindest beim PDP-8 war damit eine Aufteilung Interpreter PDP-8 Maschinencode vs Basic Daten (auch der zu interpretierende Bascicode!) in 2 Speicherbänke möglich. Und ohne User Maschinencode war sicherer Multiuser Betrieb auch mit nur einem Prozessor und Interpreter-internem Timesharing möglich. Und kompakter war das Basic Programm dadurch auch noch.

Für die Verbreitung von Basic zum den Mikrocomputern entscheidend war Bob Albrecht, ein Applikationsanalyst bei Control Data Corp (CDC), der Kunden die bei IBM Fortran gelernt hatten (bzw eben nicht gelernt hatten!) Nachhilfeunterricht gab, damit sie CDC Rechner benutzen konnten (und dafür auch kaufen wollten). Nachdem er um 1970 herum Basic kennenlernte, erachtete er Fortran als tot, und fing an mit einer PDP-8 und einem Fernschreiber und Basic zu missionieren, und es so unter die Leute zu bringen. Zuerst in Form eines fahrendes Rechnerdemos in einem VM Bus mit dem er Schulen besuchte, später mit einem Internetcafe-artigen Betrieb in Menlo Park (Silicon Valley), sowie mit einer Zeitschrift (aus dessen wachsenden Programmlisting Teil das Dr Dobbs Journal (DDJ) sich abspaltete) das später Basic Interpreter Techniken programmieren den Mikrocomputer Techies beibrachte.

Dort im "Internetcafe" lernten sich auch mehrere der späterern frühen Mikrocomputerbastler kennen (Z.B. die Gruppe die den Sol-20 baute), und auch ein Teil der späteren Gründer vom Homebrew Computer Club aus dem heraus z.B. Apple entstand (Wozniak sah dort seinen ersten Mikroprozessor, einen 8008).

Bereits dort entstanden auch die ersten Iterationen des Konfliktes zwischen der Ansicht dass echte Hacker Assembler benutzen vs den "Normalsterblichen" die "faschistoides" Basic benutzen. Das frühe Basic kannte damals noch keine PEEK()/POKE/SYS/USR() Befehle, mit denen es erst möglich wurde, Basic-Komfort mit Assembler-Hardwarezugriff und -Geschwindigkeit zu kombinieren.

Trotzdem galt auch dort bereits die anfangs 1980er sehr treffend formulierte Erkenntnis, dass man mit einem Tag Rechnerzugang entweder in Basic 10min schreiben kann, aber danach in 8h laufen lassen muss, oder in Assembler 10min laufen lassen kann, aber davor in 8h schreiben muss. Die meisten Leute ziehen 7h50m mehr andersweitig nutzbarer Zeit vor, und sei dies nur schlafen während der Rechner üner Nacht rechnet. Mein Vater hat diese Entdeckung wiederholen dürfen, als er Weihnachten 1984 auf meinem Dragon 32 in einer Woche ein Projekt durchrechnete und sich davon überzeugte, und danach in der Firma mehrere Wochen in Fortran "ernsthafte" Rechnungen machte welche das Management dann überzeugten. Die selbige Erkenntnis brachte auch die Unix Leute dazu, derart auf Shellscripts statt compilierten Code zu setzen. Auch die im Web eingesetzten perl und PHP Scripte folgen der selbigen Erkenntnis, im Gegensatz zu C oder C++ oder Java oder C# die geistig im Batch Zeitalter stehengeblieben sind.

Mikrocomputer: Microsoft, Pittman, Apple, CBM, CP/M, IBM, MSX

Frühe Mikroprozessorsysteme kannten nur rohen Maschinencode. Ein MITS Altair 8800 (oder sein Klon, der IMSAI 8080) hatte von Hause aus 0 (null!) Bytes ROM oder BIOS, keinerlei eingebauten Code. Man musste zuerst mit der "Hilfe" von 8 der Frontpanel Schaltern sowie ein paar Tastern jedes Byte Bit-für-Bit in den Speicher editieren. Erst danach konnte man den Prozessor überhaupt starten, sonst stürzte er sofort wegen Mangel irgendwelchen Programes ab! Nach Ausschalten des Rechners musste man das eingeben wiederholen, oder für ein nächstes Program. Folglich lief der Prozessor die meiste Zeit gar nicht. Zum Glück passten im Altair nur 256 Bytes Code und Daten hinein, was aber die Nützlichkeit weiter reduzierte.

Auf einem mit mehr Speicher sowie einem Fernschreiber Interface erweiterten Altair musste man "nur noch" einen Bootlader eineditieren (ausser man erweiterte den Rechner auch mit einer PROM Karte und hatte einen PROM Brenner zum das dafür nötige PROM zu brennen), und konnte den Rest per Prozessor von Lochstreifen einlesen lassen.

Der Processor Technology Sol-20 und der Apple 1 waren bereits beide so fortschrittlich, dass sie neben genug Speicher (1-stellige kBytes) auch einen Speichereditor auf Hexzahlen Basis in PROM Chips (Sol-20 1-2k, Apple 1 256 Bytes!) beinhalteten, der zusammen mit den eingebauten Schreibmaschinen Tastaturen und Schwarzweiss TV Monitor Anschlüssen lief. Ausserdem hatten sie einen Audio-Tonband Anschluss (3-30 mal schneller als Lochstreifen) und einen darauf aufbauenden Bootlader (im Sol-20 beides fest eingebaut, Apple 1 beides als Erweiterungskarte, mit weiteren 256 Bytes an PROM).

Diese Software-leere Welt animierte Bill Gates und Paul Allen einen Basic Interpreter für den Altair zu schreiben. Eine kleine Version die mitsamt Benutzerprogram in die 4k DRAM Erweiterungskarte des Altair passte und eine grosse die 8k (2 Karten) brauchte. Das ganze war ein Hack, der in ein paar Wochen gemacht wurde, nachdem sie MITS (dem Altair Hersteller) ein Angebot gemacht hatten, bevor auch nur 1 Zeile geschrieben war. MITS hatte geantwortet, dass sie das erste Basic nehmen, dass ihnen fertig laufend demonstriert wird, was dann die Eile ergab. (Diese Taktik wurde übrigens sowohl 1980 mit MS-DOS gegenüber IBM (noch nicht eingekauft), wie auch 1983 mit Windows gegenüber Endkunden vermarkten (noch nicht mal schreiben angefangen) wiederholt).

Später wurde dieses Basic bzw Microsoft berühmt (und berüchtigt) durch ihre Beschwerde, dass Leute ihr Basic kopierten statt bei MITS zu kaufen, was nur mit der defekten 4k DRAM karte möglich war (Microsoft bekam pro Exemplar Bezahlung).

Eine Folge dieser Beschwerde war die Entstehung eines vollständig als offenen Source (in Zeitschrift Form publiziert!) erhältlichen TinyBASIC durch Tom Pittman. Dieses lief auf 6800 Prozessoren (Microsoft unterstützte damals nur den 8080 das Altair) und war damit auch leicht auf einen 6502 zu portieren. Dieses wiederum animierte Steve Wozniak ein Basic für den Apple 1 anzubeiten. Es war ihm aber zu schwach, also schrieb er ein erweitertes. Apple bot dies auf einem Kassetten-Tonband, zusammen mit der Tonband Schnitstelle an. Auch da bereits die Apple Taktik, komfortable Software als Verkaufsargument für durchschnittliche Hardware anzuschauen.

Sehr bald wurde Klar, dass Basic für die meisten Leute alles ist was sie programmieren können und wollen, und dass nach jedem Einschalten wieder von Tonband einzulesen unerwünscht ist. Und da ROM Chips auch noch pro Bit billiger sind als RAM, kam die 2. Welle an massenproduzierten Mikrocomputern mit Basic in ROM eingebaut, Tonband wird nur noch für Benutzerprogramme (und -daten) speichern benutzt. Hierdurch waren dann auch grössere Basics möglich, mit 8k oder 16k oder gar 32k ROM. Und das ist nur das Basic, ohne Benutzerprogram/-daten. Das ist was im Apple ][, in den Commodore Rechnern, dem Atari 800 (als ROM Modul!), dem TI 99/4A, und später dem Dragon, sowie auch in Sinclair und Amstrad und MSX usw eingebaut wurde. Die Bootzeiten solcher Rechner, nur Bruchteile von Sekunden, trotz nur wenige-MHz 8bit Prozessor, stellen heutige PCs weit in den Schatten.

Mikrocomputer Hersteller, auf der Suche nach einem fertigen Basic (weil einkaufen billiger und schneller ist als selber schreiben) kauften diese Interpreter fast immer von Microsoft, weil die Firma bekannt für Basic war. MS Basic wurde damit zum Standard auf Homecomputern. Und da die billigsten ROMs industriell vorprogrammiert produziert werden müssen, und nicht zuhause kopiert werden können, kam MS damit zu sehr viel Geld, und hat letzlich von der Altair Basic Kopiererei profitiert, durch die einerseits Bedarf generiert wurde und anderseits ihr Name in die Welt hinaustragen wurde. Diese unabsichtliche Strategie verbreitete später auch MS Word und Office, weil überdurchschnittlich schwacher Kopierschutz.

Inzwischen hatten manche Altair Rechner (und die Klone) auch die langsam billiger werdenden Floppy Laufwerke und Controller erhalten, und ein sehr primitives (weniger als 10 Kommandos!) Betriebssytem namens CP/M wurde dafür geschrieben, mitsammt Hardware abstrahierende Treibern, wenn auch diese nur für Disk und dummes Terminal waren (der Kern von CP/M waren Filesystem und Kommandointerpreter, beide Hardwareunabhängig). Microsoft witterte eine Chance und offerierte ihr Basic für alle Systeme die einen CP/M Port haben, als generisches MBASIC.COM, sowohl via den Hersteller und auch direkt an den Endbenutzer, statt nur via den Hersteller spezifisch für die Hardware angepasst.

Das alles galt auch bereits zu dem Zeitpunkt, als IBM für ihren PC sowohl ROM Basic wie auch Disk Basic (GWBASIC.COM) von Microsoft einkauften. Dies gab dann MS die Gelegenheit, nach IBMs Desaster beim CP/M Einkauf, mit MS-DOS und später Windows die Welt zu dominieren.

Später versuchte Microsoft, auf der Basis von standardisierten Hardware Komponenten (Z80 Prozessor, TMS9918 Videochip, AY-3-8910 Soundchip, 8255 PIO Chip) und ein inzwischen gross gewordenes Basic namens MSX (MicroSoft eXtended), einen Rechnerstandard zu setzen. Es war aber zu spät zum damit die etablierten 8bit Rechner zu verdrängen (Atari 800 und C64 und Sinclair Spectrum, ausser in Asien wo diese noch nicht etabliert waren), und zuwenig zum 16bit aufhalten. Es floppte, vergleichbar mit dem Win-CE PDA Flop später.

Nach Mikrocomputer: QB4, VB, VBA, 8052AH, PIC und BasicStamp

Mit dem IBM PC begann aber auch der Abstieg von Basic. Mit dem Floppy und DOS basierten System kamen andere mächtigere, aber auch weitaus kompliziertere Sprachen auf. Trotzdem lebte Basic auf 2 Arten weiter, die beide nicht unterschiedlich sein könnten.

Einerseits hat Microsoft, deren Erfolg mit Basic begann, es im PC Bereich am Leben erhalten. Unter DOS wurde nach dem Erscheinen von TurboPascal das QuickBasic 4.0 (QB4) produziert, welches einen GUI-artigen Editor beinhaltet, in dem Basic Zeilen decompiliert und editiert werden. Seit MS-DOS 5.0 ist ein Subset davon namens QBASIC.EXE enthalten. Daraus entstand unter Windows dann Visual Basic (VB), das eigentlich ein GUI Toolkit mit Basic zum Abläufe auscoden ist. Später wurde VB zur Basis von MS ihrer vereinheitlichten Macro-/Scriptsprache für Office Applikationen, Visual Basic for Applications (VBA) erweitert.

Anderseits passierte am genau entgegengesetzten Ende gegenüber der hochleistungs PC Computerei eine weitere Basic Revolution. Intel hatte nach 1971/72 den 4004/8008 Mikroprozessoren auf einem Chip weitergemacht, und 1977 einen vollen Prozessr+ROM+RAM+Timer+IO Rechner auf einen einzelnen Chip integriert, den 8048 Mikrocontroller, und diesen dann 1980 in Form des 8051 erweitert. Intel nahm dann einen dieser mit mehr Speicher, den 8052AH, und baute einen Basic Interpreter in dessen 8k ROM ein. Dieser benutzte das interne 256Byte RAM für den Basic Status, und die 4 8bit Ports (teils) zum das Speicherzugriffsverhalten eines normalen Prozessors zu simulieren. Daran hängt man normale Speicherchips an, in denen dann der Basic Code und dessen Daten kommen. Der ganze 8052AH sieht von aussen aus wie ein Prozessor der Basic statt Maschinencode ausführt, und wurde, voll der Minicomputer Basic Tradition folgend, als einfach zu programmierendes System für nicht geschwindigkeitskritische Steuerungen verkauft.

Später wurde unter dem Namen BasicStamp das selbige mit einem PIC16 Microcontroller von Microchip wiederholt, nur noch einiges minimaler. Nur 3k an ROM, nur um 100Bytes an RAM, und die Variablen (ganze 26 8bit Ganzzahl Variablen namens A bis Z sowie ein(!) String namens $) mussten auch ins interne RAM. Nur der auf einem PC vorcompilierte Basic Code kommt von extern, per einigen wenigen IO Pins (der PIC hat nur 16 davon) aus einem SEEPROM Chip ausgelesen. Inzwischen gibt es auch Kopien dieser Variante, mit grösseren Chips, z.B. das auf PIC18 laufenden PICBasic, oder der Wilke BasicTiger der selbst das Basic-Program in internes Flash speichert.

Programmieren in Basic

Nachdem wir jetzt wissen woher Basic kam, und wieso es auf Mikrocomputern auftauchte, schauen wir nun mal an wie Basic eigentlich aussieht und benutzt wurde. Dieser Teil des Vortrags setzt etwas Kenntnis voraus wie man Programme schreibt, also genau das was zum Lehren Basic erfunden wurde.

Da Basic mit dem Ziel entwickelt wurde, keine unnötig komplizierten Kenntnisse erlernen oder berücksichtigen zu müssen, fehlt folglich vieles was in anderen Sprachen drin ist und als nicht nötig empfunden wurde. Am Schluss verbleibt:

Vereinfachte Arithmetik von Fortran
Diese besteht nur aus: Alles was mit 0..9 anfängt ist eine Konstante (in dezimaler oder exponentieller Schreibweise). Alles was mit A..Z anfängt und dahinter ein einzelnes A..z oder 0..9 hat ist ein Variablenname. Ein Variablenname mit Klammer dahinter ist eine Arrayvariable. Mehrere A..Z mit einer Klammer dahinter ist ein Funktionsaufruf. Es braucht daher keinen Unterschied eckige vs runde Klammern, nur runde. Als Operatoren gibt es + - * / und ^ (Exponent). Und Klammern ohne ein A..Z davor haben die in der Mathe übliche Bedeutung.
Simple Zuweisungen wie in Fortran
Anfänglich als Kommando LET Variable = Ausdruck geschrieben. Die meisten neueren Basics erlauben es, das LET wegzulassen. Wie bei allen anderen Kommandos wird keinerlei Schlusszeichen benötigt. Ebenso wird nicht unterschieden zwischen Gross- und Kleinschreibung.
Simple eingebaute Funktionen
Angeboten wurden Absolutwert ABS(), Ganzzahl INT(), Quadratwurzel SQR(), Exponentialrechnung EXP() und LOG(), Trigonometrie SIN() COS() TAN() und ATN(), sowie Zufallszahl generieren RND(). Mit DEF FNA..Z = Ausdruck und FNA..Z() gab es dazu noch 26 vom Benutzer als einzelnen Ausdruck (ohne Ablauflogik!) definierbare Funktionen. Alle Funktionen werden mit nur einem Parameter in Klammern aufgerufen.
Nur einen Datentyp für Zahlen
Es gibt keine Unterscheidung zwischen Ganzzahlen vs Fliesskommazahlen. Diese verkompliziert, und dient nur der Geschwindigkeit. Selbst Array Index Rechnungen werden in Fliesskomma gerechnet und intern vor Gebrauch umgewandelt. Später wurden zwar Ganzzahlen syntaktisch addiert (Prozent Zeichen hinter Variablennamen), aber oft Hirnrissig implementiert, als umwandeln in Fliesskomma, so rechnen und dann zurückwandeln, was den Geschwindigkeitsvorteil ad Absurdum führte. So z.B. im C64
Text gibt es als String Datentyp
Alles was mit einem Anführungszeichen anfängt, bis zum beendenden zweiten Anführungszeichen ist eine Stringkonstante. Das war anfangs alles was es an Text gab, nur als Konstanten zum ausdrucken! Später kamen Stringvariablen (Dollar Zeichen hinter dem Variablennamen), und Stringausdrücke. Es gibt keinen Unterschied von Strings zu einzelnen Zeichen, auch das wär eine Komplikation die nur für die Geschwindigkeit relevant ist. Strings sind echte Datentypen, keine Arrays von Zeichen, mit all derer Problemen.
Komfortable Stringfunktionen ohne Pointer
Von Strings kann die Länge gemessen werden mit LEN($), sie zerlegt werden mit LEFT$() MID$() und RIGHT$(), sowie mit + zusammengefügt, zu/von Zahlen gewandelt werden mit VAL($) und STR$(), sowie Zeichen erzeugt oder analysiert mit CHR$() und ASC($) werden.
Autoformatierte Ausgabe
Mit PRINT String Ausdruck, String Ausdruck, ... kann man mehrere Zahlen berechnen und mit Text ausgeben lassen, automatisch in Spalten positioniert bei jedem Komma. Nach Einführung von Stringfunktionen und Stringausdrücken wurde Print umdefiniert, dass es Strings und Zahlen beliebig gemischt ausgeben kann.
Eingabe anfangs ohne Benutzer
Anfänglich liefen Basic Programme ohne auf den Fernschreiber des Benutzers zugreifen zu können. Files zum einlesen gibt es auch keine, weil das einen Editor, Filenamen und Accounts benötigen würde. DATA Zeilen geben daher im Programcode hineineditierte Eingabedaten vor. Am ehesten ist das mit den heutigen "here document" (das "<< EOF") in Unix Shells vergleichbar. Diese Zeilen werden mit READ gelesen. Der INPUT Befehl erschien zuerst zum Daten von Files lesen (nachdem Files addiert wurden), und wurde dann aber auch für die Tastatur benutzt (nachdem Basic auf Rechner mit Tastaturzugriff kam). INPUT kann auch in einem Schub einen String ausgeben (z.B. Angabe was einzugeben ist), und mit dem Cursor gleich dahinter dann die Daten einlesen.
Kommentare als Kommandos
Es gibt keinen speziellen Komentarsyntax/-zeichen. Vielmehr gibt es ein "mach nichts" Kommando, mit dem Namen REM, kurz für "remark".
Sofortige Ausführung
Alle Kommandos die nicht mit einer Zahl anfangen werden sofort ausgeführt nachdem sei eingegeben worden sind, wie auf einer Kommandozeile. Damit kann man z.B. mit PRINT beliebige Variablen anschauen gehen, oder auch Taschenrechner mässig schnell etwas ausrechnen, aber auch Variablen verändern und dann weiter rechnen, ideal zum Experimentieren und Debuggen.
Kein separater Source/Editor/Compiler
Ein Programm wird modifiziert indem man einem Kommando eine Zahl voranstellt, die Zeilennummer. Diese gibt vor, wo ins Programm diese Zeile eingesetzt (oder ersetzt) werden soll. Eine Zeilennummer ohne Kommando dahinter löscht die passende Zeile. Der LIST Befehl zeigt was für Zeilen momentan im Program drin sind. NEW löscht alles. SAVE und LOAD erlauben es das momentane Program abzuspeichern und es (oder ein anderes!) wieder zu laden. Es gibt keinen von der reinen Fernschreiber Kommandozeile verschiedenen Editor mit Sourcefile drin, nix zum scrollen, nur die momentan gespeicherten Zeilen, die mit RUN den Zeinennummern nach sortiert ausgeführt werden.
Keine Blockstrukturen
Die Algol Blockstrukturierung wurde von den Basic Erfindern als zu kompliziert angeschaut. Für Grossprojekte von Profi Informatikern sind sie sinnvoll zum Ordnung schaffen, aber nicht zum simpel Programieren lernen. Interessanterweise hab ich Programmieren mit Pascal erlernt und kam nach der ersten Basic Begegnung zum Schluss, dass Pascal umständlich ist, genau wegen diesen, sowie den ganzen Deklarationen. Also wurde von Fortran die GOTO Zeilennummer Methode übernommen, aber ohne die explizit zu vergebenden Labelzahlen. Statt dessen wurden die zum Editieren ohnehin vorhandenen Zeilennummern auch als Sprungziele benutzt. Damit man, ohne beliebig vergebbare Nummern, Platz hat zum Zeilen dazwischen einfügen, wird üblicherweise anfangs in 10er Schritten nummeriert, dann setzt man erstmals 5 dazwischen, dann 2 oder 3 bzw 7 oder 8.
Verzweigungen
Mit IF Bedingung THEN Zeilennummer wird verzweigt. Ein "else" macht man mit einem normalen GOTO nach dem ersten Fall seinem Code. Das THEN Zeilennummer ist eigentlich nix anderes als ein GOTO Zeilennummer und manche Basics kennn das als alternative Schreibweise. Was fehlt ist die logische Konsequenz daraus, ein generisches IF Bedingung beliebiges Kommando.
Schleifen
Schleifen kann man mit IF machen, aber für die häufige indexierte Schleife hat es Spezialbefehle: FOR Variable = Anfagswert TO Schlusswert, mit fakultativ STEP Schrittwert dahinter, gefolgt von Kommandos und abgeschlossen mit NEXT, welche weniger Tipperei geben, alle Angaben lesbar sammeln, und schneller ablaufen.
Unterprogramme ohne Parameter
Unterprogramme können mit GOSUB Zeilennummer (wie einem GOTO funktionierend, aber merkt sich welche Zeile danach gekommen wäre) aufgerufen werden, und mit RETURN zur dabei aufgezeichneten Zeile hin verlassen werden. Am auffallendsten ist der totale Mangel an Parametern. Auch diese wurden als unnötige Komplikation angeschaut. Man setzt einfach einen für jedes Unterprogram festgelegten Satz von Variablen. Auch lokale Variablen wurden als Komplikation angeschaut, nur zum Grossprojekte organisieren sinnvoll. Zumeist werden Subroutinen ab Zeile 10000 in je einem 1000er oder 10000er Block angelegt, je nach der erwarteten Grösse.
Lowlevel Zugriff aus Basic heraus
Dies gab es in den 1960er Ur-Basic und Minicomputer Basics gar nicht, was die Basis ergab für die "Basic ist faschitoid" Bemerkungen von Assembler Hackern. Mikrocomputer Basics dagegen kennen PEEK() und IN() zum Speicherworte und Eingabegeräte auslesen, POKE und OUT zum Speicher und Ausgabegeräte beschreiben, SYS zum Maschinencode ausführen, der per DATA/FOR/READ/POKE/NEXT in den Speicher ge-poke-t worden ist, und USR() zum dies als Funktion machen. Damit vereinte Basic dann sowohl simplen Komfort wie auch schnelle und flexible Leistung je nach was man an einer Stelle lieber haben will.
Dieser Abschnitt ist recht kurz, weil Basic eben recht klein und kompakt ist. Das war auch schon ein Feature des Dartmouth Basic Manuals, das mehr Platz für Beispiele und Programmiertechniken brauchte als für Basic selber. Basic wurde schon damals als Mittel zum Zweck nebenbei gelehrt, in Kursen wo der Computer eingesetzt wurde. Es wurde genau desshalb schnell erlernt und effektiv eingesetzt, was seinen Ruf begründete.

Basic Rechner: Commodore 64 und Dragon 32

Nachdem wir jetzt wissen wie Basic als Sprache aussieht, schauen wir nun wie es im Inneren des dafür benutzten Interpreters zu und her geht. Wie man das doch recht stark von der Harddware abstrahiertes Verhalten von Basic implementiert. Dieser Teil des Vortrags setzt etwas Kenntnis voraus wie Computer funktionieren, und wie man maschinennah programmiert.

Als Beispiele dienen das vom Microsoft stammende spät-1970er Commodore CBM Basic V2.0 (das im 64er und davor im VC-20 unverändert seit dem CBM 3000 übernommen wurde), sowie das 1982er Microsoft Basic des Dragon 32 das der direkte Vorläufer vom MSX Basic ist. Diese aus genau einem Grund, weil der Schreiber beide benutzt hat, und von diesen beiden dissassemblierte ROM Listings hat, noch aus der Zeit als diese beiden Rechner im Gebrauch waren, und noch kein heutiger PC in Sicht war.

Die beiden Rechner sind sich recht ähnlich, und typisch für spät-1970er und früh-1980er Homecomputer:

Unterschiede sind nur der genaue Prozessortyp (aber beide halbwegs ähnlich, das 6809 Basic ist ein 6502 Basic Port), sowie die *sehr* verschiedenen Fähigkeiten von den Video und Sound Chips (C64 weitaus besser, aber nichts davon vom Basic ausgenutzt, letzteres ist neben mehr RAM auch einziger Unterschied vom VC-20, dem der Dragon 32 sehr ähnelt).

Adressaufteilung ist bei den beiden: C64 hat 2 8k ROMs A000..BFFF und E000..FFFF (mit einem Loch dazwischen(!)), D000..DFFF ist IO, C000..CFFF ist 4k RAM die das Basic nicht nutzen kann(!), 0000..9FFF ist 40k nutzbares RAM. Dragon hat 2 8k ROMs 8000..9FFF und A000..BFFF, und die letzten 32Bytes noch BFxx->FFxx gespiegelt. IO ist auch alles in FFxx drin. D000..FFDF ist ungenutzt. 0000..7FFF ist 32k RAM.

Basic ROMs: CBM Basic 2.0 und MS Basic 82

Beide Basics kommen in 16k ROM daher, aus je 2 8k Chips bestehend. Bei beiden fängt der eigentlich Basic Interpreter (der Teil von Microsoft) von zuvorderst an, und die Treiber (der Teil vom Hardware Hersteller) kommt von zuhinterst (weil es FFFx beinhalten muss). CBM Basic benutzt 8000..BFFF sowie E000..E4B6 (= 9k) und der "Kernel" (hauptsächlich Treiber) benutzt E4DA..FF80 (= 7k), FF81..FFF6 sind Sprungvektoren Basic->Treiber. MS Basic 82 benutzt 8033..BB34 (= 15k) und Treiber nur BB40..BE7E (= 1k), 8000..8032 sind die Sprungvektoren Basic->Treiber.

Man sieht schon mal 3 grosse Diferenzen:

Basic RAM Aufteilung

Dies ist bei den beiden Rechnern erstaunlich ähnlich aufgebaut. Man sieht die gemeinsame Herkunft der beiden Interpreter deutlich.

Bei beiden Prozessoren ist der RAM Bereich 0000..00FF besonders schnell zugreifbar, und daher für Basic-interne und Treiber-interne Steuerdaten benutzt. Da wären z.B.:

Der Platz reicht dafür aber nicht, daher werden weniger häufig benutzte interne Daten in 0100..03FF gespeichert. Da waren z.B.: Danach folgt der Videospeicher. Beim C64 sind diese stets 1000Bytes 0400..07FF (die letzten 24 werden nicht benutzt) für den Textmodus, für Graphikmodus hat der Benutzer irgendwie 8000 Bytes Platz zu finden, z.B. die letzten 8k der 40k RAM "abschneiden" (bzw beim Basic abmelden, durch einen der Speicher Endadressen verfälschen). Beim Dragon sind für den Textmodus 512Bytes 0400..05FF sowie für den Graphikmodus 2*6k 0600..35FF fest reserviert. Genauso muss der Benutzer auf dem C64 die Graphik "von Hand" generieren, während auf dem Dragon fixfertige Befehle dafür vorhanden sind.

Für Basic Programme und Variablen und Strings steht der restliche Speicher zur Verfügung. Beim C64 0800..BFFF 38k, die berühmten "38911 Basic Bytes Free", beim Dragon 3600..7FFF, ganze 18.5k, also nur halb soviel Platz. Dieser wird dynamisch verteilt. Von vorne wächst der Basic Code. Dahinter gleich anschliessen kommen die Variablen (die bei jedem Program Editieren gelöscht werden). Dann folgt der Stringspace bis zum offiziellen Speicherende. Dahinter können noch Videospeicher oder Maschinencode Blöcke folgen, wenn der Benutzer den Endwert fälscht. Letztere können beim C64 auch in die nicht vom Basic nutzbaren 4k Speicher von C000..CFFF abgelegt werden.

Basic compiliert im Speicher

Basic Code wird teil-compiliert, zu einem internen Code, der aber kein Maschinencode ist. Zur Laufzeit wird diese Zwischenform interpretiert. Die einzelnen Zeilen werden gespeichert als eine gelinke Liste. Pro Zeile hat es einen Zeiger auf die nächte Zeile ihren Anfang (zum mit GOTO schnell durchhangeln). Danach folgt die binär codierte Zeilennummer (kompakter und für GOTO Zeilennummern schneller zu vergleichen).

Die Basic Befehle (und Funktionen) werden als 1-Byte Tokens gespeichert (kompakter, und schneller zum in der Befehlstabelle nachschauen), mit Werten oberhalb von 128 (und so nicht mit 7bit ASCII verwechselbar), z.B. im C64: 128=END, 129=FOR, 130=NEXT, 131=DATA, ..., 162=NEW. Nur die Variablennamen (kurz und viele) und Konstanten (oft kürzer als in 5-Byte binär Form) werden als ASCII Text gespeichert. Der Leerschlag nach dem Befehlswort entfällt auch.

Jede Zeile wird direkt nach dem Eintippen derart teil-compiliert und dann an der richtigen Stelle in die Liste eingelinkt, und zwar in der richtigen Reihenfolge im Speicher liegend (braucht Kopiererei), nicht im Speicher herum springend (bräuchte Garbage Collection). Beim LIST Befehl wird wieder decompiliert und rekonstruiert, es ist kein "Rohtext" zum auslisten da. Es gibt keinerlei zeilenübergreifende Compilierungsvorgänge (FOR/NEXT ist eh das einzige mehrzeilige Konstrukt, da es kein blockorientiertes IF/THEN/ELIF/ELSE/ENDIF gibt). Auch auf Band wird der teil-compilierte Code gespeichert und wieder eingelesen (CP/M und MS-DOS Basic kann optional ASCII machen, C64 kann zu ein File "drucken").

Hinter dem Code folgen dann die Variablen. Genauer folgt hier ein Array von Name/Wert Paaren, ohne Platz für Links zu verbrauchen, 2 Bytes für den Namen, 5 Bytes für den Wert. Bei Zahlen ist dies direkt der Fliesskommawert, bei Strings sind dies 1 Byte Längenangabe (Strings haben max 255 Zeichen) und 2 Bytes Link in den Stringspace.

Dahinter folgt als letztes der Stringspace. Hier wird für jeden String der zusammengesetzt wird Platz vergeben (Stringkonstanten haben bereits ihren Platz im Code drin). Der Platz wird einfach vorzu abgeschnitten bei jedem Teilstring anhängen, bis der String fertig ist. Wenn der Platz ausgeht, wird per Garbage Collector der Leerplatz von nicht mehr existenten Strings "eingesammelt", indem alle Strings nach vorne kompaktiert werden, inklusive ihre Links anzupassen. Auf diese Art und Weise können Strings ohne anfällige malloc()/free() beliebig lang benutzt und erweitert werden, brauchen keine max-String grosse Platzreserve, und es gibt dank Längenangaben keine Bufferoverflows und ein schnelles Stringende finden. Aber bei Garbage Collection kann den Rechner minutenlang "einfrieren". Die Erfinder von C hätten hier einiges lernen können. Zitat von einem Kollegen: "Wenn man kapiert hat, dass C keine Strings hat, kann man dann damit Strings verarbeiten".

Basic ausführen im Interpreter

Eine Programmschleife (Eingabe Warteschleife) im ROM liest Eingabezeilen, schaut nach ob sie mit einer Zahl beginnen (= Program Edit) oder einem Befehl (= Befehl direkt ausführen). Auf jeden Fall wird die Zeile teil-compiliert. Das Befehlswort wird in einer ROM Tabelle von Strings nachgeschaut, wo für jeden Befehl das Bit 7 des letzten Zeichens gesetzt ist. Dabei werden, von 128 ausgehend, die Wörter gezählt, und damit der Tokenwert für diesen Befehl bestimmt.

War die Eingabe ein Edit wird nun das Programm modifiziert. Es wird durch umkopieren Platz geschaffen und die Zeile mit Link und Zeilennummer eingefügt. War es ein Kommando, wie z.B. RUN wird es sofort ausgeführt, wie wenn es Teil der Programmausführung wäre. Dazu wird der Token genommen, und die Zahl als Index in eine Tabelle von 2 Byte Werten benutzt, welche die für diesen Befehl zuständige Routine im Interpreter identifizieren, und diese angesprungen. Das ganze ist also ein "Case" Konstrukt.

Diese Routinen beinhalten nun die befehlstypische Logik. Im Fall von RUN werden die Variablen gelöscht (sofern nicht bereits durch Editieren) und die Basic-internen Angaben über wo man gerade ist werden auf die erste Programmzeile gestellt. Ausserdem wird von Tastatureingaben teil-compilieren und interpretieren auf Programmzeilen nur-interpreteren umgestellt. Einerseits ist die Quelle anders, anderseits entfällte der teil-compile Schritt, weil der ja beim editieren schon stattfand. Dadurch wird Basic einiges schneller. Dies ist analog zur "äuseren Interpreter" und "inneren Interpreter" Aufteilung von Forth, nur dass dort der Code weitaus weiter compiliert wird, und dementsprechend schwieriger bis unmöglich zum decompilieren ist.

Benötigt ein Befehl Argumente, kann dessen befehlstypische Logik dazu Hilfsroutinen im Interpreter aufrufen, welche diesen evaluiert. Im Fall von numerischen Ausdrücken wird dazu etwas Speicher namens Fliesskomma Akkumulator (FAC) benutzt, in dem der aktuelle Zahlenwert aufgebaut wird. Für mehrere Operanden einer Funktion, sowie Addition/Multiplikation/Exponent gibt es dazu auch 3 Hilfs-FACs. Für Klammerausdrücke, die beliebig oft verschachtelt sein können, werden die Hilfs-FACs bei "(" auf einen Stack gespeichert und bei ")" wieder zurückgeholt.

Auf diese anwendbar gibt es Routinen für Addition, Subtraktion (A-B wird als A+(-B) gerechnet), Multiplikation, Division (A/B wird erstaunlich nicht als A*(1/B) gerechnet), Polynomberechnung mit x hoch 0,1,2,3,... bzw x hoch 1,3,5,7,... Serien (letzteres für McLaurin und Taylor Reihen berechnen), sowie transzendente und logarithmische Funktionen via eben diese Reihen.

Selbst diese detailierte Logik ist bei beiden Rechnern identisch. Sogar die Zerlegung auf Subroutinen ist identisch. Das geht soweit, dass im Dragon, trotz des 6809 Prozessors der einen in Hardware implementierten 8bit*8bit Multiplikations Befehl hat, die nötige 32bit*32bit Mantissen Multiplikation mit genau der selbigen Shift-Logik berechnet wird wie auf dem 6502! Der MUL Befehl wird einfach ignoriert, was Multiplikation und damit auch Polynome und Transzendentale um ein Mehrfaches langsamer als nötig macht.

Werden als Teil eines Ausdruckes Variablen verwendet müssen deren Werte geholt werden. Dazu wird mit dem Variablenamen eine lineare Suche(!) des Variablenspeichers durchgeführt. Die Variablen sind nicht alphabetisch geordnet, es ist daher keine binäre Suche möglich, trotz konstanter Grösse. Da wurde ebenfalls viel Geschwindigkeit verschenkt.

Ist ein Befehl eines Programmes fertig, wird zur nächsten Zeile übergegangen und diese ausgeführt. Dies geht solange bis beim Programende angekommen wird, oder ein Programmablauf steuernder Befehl ausgeführt wird (GOTO/IF/GOSUB/RETURN/FOR/NEXT).

Die Sprünge GOTO, IF und GOSUB suchen einfach der gelinkten Liste der Zeilen nach, solange bis die richtige Zeilenummer auftaucht. Für Zielen mit Zeilennummer kleiner als der aktuellen wird von vorne gesucht. Für solche mit Nummer grösser wird ab der jetztigen Position weitergesucht, damit werden die zumeist kurze Distanz vorwärts laufenden IF und die den Else-Teil überspringenden GOTO einiges schneller. Die relativ simple Technik von den letzten paar GOTO, IF und GOSUB das Nummer->Zielort Resultat in einem Cache zu speichern wurde nicht verwendet.

GOSUB merkt sich die aktuelle Position (und nicht nur Zeilennummer) jedes Aufrufes auf einen Stack (den selbigen auf den Klammerausdrücke die Hilfs-FACs speichern) damit verschachtelte Subroutinen möglich sind, von dem aus dann RETURN diese ohne Zeilensuche schnell nehmen kann. Das GOSUB selber ist wegen der üblichen Anordnung der Subroutinen am Programmende relativ langsam zu benutzen.

Besonders aufwendig ist FOR, welcher zusammen mit NEXT auch der einzige mehrteilige Befehl ist. Nicht nur merkt es sich den Ort des FOR, und vermeidet damit eine Zeilensuche von vorne, es muss seine Indexvariable auch nur einmal suchen. Alle Zuweisungen und Tests auf diese laufen damit einiges schneller ab. Und da die Zuweisung für nächsten Wert berechnen und der Test auf Ende beides fixe Operationen sind, mit nur 2 Zahlenwerte als Parameter, werden auch diese nur einmal bestimmt, und dann mit abgespeichert und direkt benutzt. Auch dazu dient, damit verschachtelte Schleifen möglich sind, der selbige Stack wie bei GOSUB und Klammern. Daher sind FOR/NEXT weitaus schneller als die genau identisch wirkende mit normaler Arithmetik und IF/GOTO ausgeführte Variante.

Umgebung um Basic Darumherum

Basic entstand in einer Welt von Fernschreibern. Es erwartet daher nicht mehr als eine Bytestrom Ein-/Ausgabe über RS232 oder Vergleichbarem. Genau das wurde im Dragon in den 1k Treibern minimalst implementiert, auf einem Text Framebuffer aufsetzend. Beim C64 dagegen sind dort 7k an "Kernel", zum grösseren Teil Treiber, aber auch einiges an anderen Sachen. Und manche von denen haben den Umgang mit dem eigentlich recht schwachen alten Basic besser und komfortabler gemacht als das neuere Basic von Dragon ist.

Als wichtigstes ist hier das implementierte Terminal zu nennen. Während im Dragon einfach ein Glass TTY simuliert wird, ist der C64 sein Terminal direkt komfortabel. Dabei geht es gar nicht einmal um Escape Sequenzen, welche bei beiden fehlen, sondern darum, dass das C64 Terminal die Ausgabe editieren und wieder eingeben kann!

Alle Basics können ihr Programm editieren indem man per Kommandozeile Zeilen addiert, löscht oder ersetzt, was aber auf neu eintippen von zu ändernden Zeilen rausläuft, und recht mühsam ist.

Auf dem Dragon ist ein EDIT Zeilennummer Befehl vorhanden, der mit in etwa mit dem MS-DOS EDLIN vergleichbaren "Komfort" eine neue Variante einer Zeile produzieren kann. So mühsam, dass ich mir es nie angewöhnt habe. Neu eintippen weiss man schon wie es geht, und es ist genauso schnell, und pure Tipperei ohne lesen/planen/befehl/tippen Zyklus.

Auf dem C64 kann dagegen eine Zeile (oder mehrere Zeilen) mit LIST ausgelistet werden, dann im Bildschirmspeicher editiert werden, und die geänderten Zeilen als neue Kommandos abgeschickt werden, wie wenn voll getippt, womit sie neu eingefügt/ersetzt werden. Dabei können Befehle auch nur unverändert wiederholt werden, wie bei einer Shell History, wobei nicht nur Befehle, sondern auch INPUT Eingaben wiederholbar sind. Man kann auch ähnliche Zeilen durch mit-editieren der Zeilennummer von vorherigen ableiten. All das ohne ein einziges Feature im Basic drin, Basic sieht nur traditionelle neue Zeilen, aber der User hat editiert, und das im Vollbildschirm Modus, mit mehreren ausgelisteten Zeilen im Sichtfeld!

Dazu brauchte das Terminal nur den Cursortasten zu folgen (Basic weiss nix von denen), direkt die Zeichen im Videospeicher zu ändern (es ist kein separater History Speicher vorhanden), und von jeder Cursorposition wissen, zu welcher Eingabe oder Ausgabe Zeilengruppe (umgebrochene Einzelzeile!) sie gehört, und damit welcher Zeilenblock als neue Eingabe dem Basic zu schicken sein wird, wenn Return gedrückt wird. Der Cursor ist nach Return stets auf dem ersten Zeichen der nächsten Zeilengruppe. Dazu wird neben dem Videospeicher nur eine Liste von Koordinaten der Zeilengruppenenden der max 25 sichtbaren Zeilen benötigt. Einzige Limite ist, dass mangels Scrollback Speicher max 25 Zeilen an gemischter Ein- und Ausgabe so editierbar sind.

Das Resultat ist weitaus besser als beim Dragon. Vergleicht man das mit dessen "nur Zeile ändern und ersetzen" Editor, der weniger kann und schwieriger ist, und Basic Erweiterung brauchte, ist der Unterschied wie Tag und Nacht. Das generische "Aufsetzfeature" ist dem spezifischen eingebauten weit überlegen.

Der C64 Terminal Editor wurde dann auch logischerweise von anderen Programmen benutzt. Sowoh der typische "Monitor" Debugger, wie auch ein Assembler wurden beide als pure TTY Kommandozeilen geschrieben, die einen LIST-artigen Befehl hatten, dort wo editieren erwünscht ist.

Die Firma HP hat überigens, als Teil ihrer HP2000 Minicomputer, RS232 Terminals eingeführt die genauso arbeiten. Ich hab diese aber erst kennengelernt, als ich Unix (und moderne Pfeil-aufwärts Shell History) kannte, und diese an einem HP-UX Rechner angeschlossen waren. Jedesmal als ich wie gewohnt History holen wollte lief der Cursor herum, statt dass die Shell mit History reagierte. Ich fand dies frustrierend, und habe erst viel später kapiert, dass da die C64 Erfahrungen angebracht gewesen wären. Dabei fiel aber auch die Limite auf, dass History auch durch Ausgaben längst weggescrolle Kommandos kennt, während diese Terminals kein Scrollback kannten, oder diese zumindest nicht sichtbar war. Alles in allem genau ein "früher gab es total anderes" Feature, genau passend zum Thema dieses Jahr.

Literaturquellen

    [Wexelblat] Richard L Wexelblat, History of Programming Languages
      Academic Press, 1978, ISBN 0-12-745040-8 (Englisch)
        beinhaltet [Baker] und [Kurtz] und einiges anderes
    [Baker] Charles L Baker, JOSS - JOHNNIAC Open-Shop System
      = [Wexelblat] Seiten 495..513 (Englisch)
        Beschreibung von JOSS und seiner Entstehung
    [Kurtz] Thomas E Kurtz, Basic
      = [Wexelblat] Seiten 515..549 (Englisch)
        Beschreibung von Ur-Basic und seiner Entstehung
    [Levy] Steven Levy, Hackers - Heroes of the Computer Revolution
      Dell Publishing, 1984, ISBN 0-440-13405-6 (Englisch)
        (im 2. Abschnitt) Hacker und Basic, von Albrecht bis Wozniac
    [Janneck] Jörn W. Janneck & Till F. Mossakowski,
      Das Dragon 32/64 Lexikon
      Röckrath Mikrocomputer, 1984 (Deutsch)
        Hardwareaufbau und Dissassmbliertes ROM Listing vom Dragon 32 und 64
    [Angerhausen] Angerhausen & Brückmann & Englisch & Gerits, 64 intern
      Data Becker GmbH, 1983, ISBN 3-89011-000-2 (Deutsch)
        Hardwareaufbau und Dissassmbliertes ROM Listing vom Commodore C64
    

Home | Artikel | VCFe Basic Interpreter

Diese Seite ist von Neil Franklin, letzte Änderung 2007.04.27