Bits, Bytes und BASIC


BASIC

Wir haben nun eine ganze Menge Befehle und Funktionen des C16 für die Programmierung kennengelernt. So eine Menge an Befehlen und Funktionen und die Regeln, wie daraus ein Programm wird, nennt man eine Programmiersprache. Wir haben also gerade unsere erste Programmiersprache erlernt. Die C16-Programmiersprache? Nicht nur. In der Zeit, in der es den C16 gab, war die eingebaute Programmiersprache praktisch immer diesselbe, bis auf kleinere Abweichungen im Bereich der Ein- und Ausgabebefehle, die ja stark von der Technik des Computers abhängen. Diese Programmiersprache war BASIC (Beginners All Symbolic Instruction Code). Sie haben also gerade BASIC gelernt. BASIC ist heute noch eine sehr beliebte Programmiersprache auf Computern.

Bits und Bytes

Wir haben ganz am Anfang gelernt, wie man Zahlen speichert. Später, dass man auch Programme in den Speicher schreiben kann. Jetzt gehen wir etwas in die Tiefe und fragen: Wie funktioniert das eigentlich, dass so unterschiedliche Dinge gespeichert werden können?

Die elektronischen Speicher eines Computers sind s.g. bistabile Transistoren oder Flipflops. Sie müssen sich drunter irgendetwas Elektronisches vorstellen. Diese "Dinger" können eine 0 oder eine 1 speichern. Man nennt das 1 Bit. Zur Speicherung von Zahlen oder Buchstaben ist das natürlich zu wenig. Also bündelt man die Bits zu Bit-Gruppen, s.g. "Worten". In der Frühzeit der Computer war die Anzahl der Bits pro Wort von Maschine zu Maschine verschieden. Je nachdem, was der Computerbauer hauptsächlich zu Speicherung gedacht hatte: Ganzzahlen, Gleitkommazahlen oder Buchstaben. Von 12 Bits pro Wort bis 50 Bits pro Wort kam alles vor. Anfang der 60er-Jahre führte IBM ein grosses Computersystem ein, das System /360. Und da dieses System sehr universell gedacht war, wurden hier die Bits zu Standardworten gebündelt. Diese nannte man und nennt man heute noch Bytes. Jedes Byte hat 8 Bit. Warum acht? Ein Byte kann damit 256 verschiedene Zustände annehmen, also eine Ganzzahl zwischen 0 und 255 speichern. Damit können Bytes schon mal ganz gut dazu genutzt werden, Ziffern und Buchstaben zu speichern - mittels ASCII-Codierung, die wir schon kennengelernt haben. Womit das Geheimnis gelüftet wäre, wie ein Computer ein Programm speichert. Schliesslich können mehrere Bytes wiederum gebündelt werden, z.B. 4. Das sind dann 32 Bits. Diese können eine Ganzzahl zwischen -2 Milliarden und +2 Milliarden aufnehmen. (Oder zwischen 0 und 4 Milliarden). Das reicht auch für eine Zahl. Bei Gleitkommazahlen ist es etwas komplizierter, hier werden 4, 5 oder sogar 8 Bytes dazu benutzt, die Zahl in s.g. Exponentialdarstellung zu speichern, bei der Mantisse und Exponent unterzubringen sind.

Kilo, Mega und jenseits

Mein allererster programmierbarer Taschenrechner hatte 38 Bytes Programmspeicher. Das war übersichtlich. Aber damit kann man natürlich nicht viel anfangen. Daher spricht man oft über Tausende oder Millionen von Bytes. 1024 Bytes sind 1 Kilobyte, abgekürzt 1 K. 1024, richtig, nicht 1000. Denn 1024 sind 2^10 Bytes. Da der Computer alles binär (im 0/1-System) darstellt, ist das praktischer: Damit 1024 Bytes angesprochen werden können, braucht man eine Nummer mit genau 10 Bits.

1024 K sind 1 Megabyte, abgekürzt 1 MB. Also 2^20 Bytes.

1024 MB sind 1 Gigabyte, abgekürzt 1 GB. also 2^30 Bytes.

1024 GB sind 1 Terabyte, abgekürzt 1 TB. Also 2^40 Bytes.

1024 TB sind 1 Petabyte, abgekürzt 1 PB. Also 2^50 Bytes.

Grössere Einheiten werden Sie wahrscheinlich nicht brauchen - jedenfalls nicht in den nächsten 2 Jahren ....;-).

Jetzt können Sie die Meldung, die beim Starten des C16 kommt, verstehen: "12277 Bytes free". Der C16 hat nämlich 16 K Hauptspeicher. 16385 Bytes. Davon braucht er für das BASIC-System und den Bildschirm (siehe Kapitel "Grafik") etwas. Und es bleiben dann ca. 12K für den Programmierer übrig. Wieviel ist das? Nun, da diese Bytes sowohl für Daten als auch für das Programm herhalten muss und da Daten (Strings oder Zahlen) unterschiedlich viele Bytes brauchen und jede Programmzeile wieder unterschiedlich lang ist, kann man das schwer griffig sagen. Was die Programmlänge betrifft, kann man die Faustformel bilden: Ca. 20 Bytes pro Zeile. Bei 1K Zahlenspeicher (ca. 250 Zahlen) bleiben dann noch ca. 11000 Bytes und das sind dann ca. 550 Zeilen. Soviel haben wir bisher nicht gebraucht. Aber das kann schnell kommen, wenn man an einem Programm längere Zeit arbeitet, es pflegt und erweitert.

Wie kann ich beim C16 herausbekommen, wieviel Bytes ich schon verbraucht habe? Nun, geben Sie einmal folgendes Programm ein und starten es:

10 DIM A(4000)

Das ist alles. Anscheinend passiert hier noch gar nichts. Tatsächlich versucht Ihr PC in Zeile 10 Speicher für 4000 Zahlen zu reservieren. Jede Zahl braucht 4 Bytes. Er benötigt also 16000 Bytes. Das C16-System hat aber nur 12277 Byte frei. Folglich klappt das nicht:

?Out of memory error in 10

Diese Fehlermeldung werden Sie immer bekommen, wenn Sie entweder zuviel Speicher verbrauchen wollen oder ein zu langes Programm eingetippt haben (oder beides).

Natürlich können Sie sich auch schon vorher bei Gelegenheit informieren, wieviel Speicher noch frei ist. Das geht über die Funktion fre(0). (Man kann auch noch andere Argumente als die Null übergeben, um weitere Speicherdetails zu erfahren, aber das soll uns hier nicht interessieren.). Laden wir z.B. unser Millionärsprogramm aus dem letzten Kapitel und geben FRE(0) ein, erhalten wir "9706". Das heisst, wir haben noch 9706 Bytes Speicher frei. Unser Programm ist also "? 12277 - FRE(0)", 2578 Bytes lang, rund 2,5K.

Wenn wir nun das Programm laufen lassen und es mitten im Betrieb mit der Tab-Taste unterbrechen, können wir das gleiche Kommando nochmal abschicken. Dieses Mal sind alle Speicher, die das Programm benötigt, schon reserviert und belegt. Nun müsste mehr Speicher verbraucht sein. Tatsächlich: Nun meldet der C16: "2958". Das heisst, es sind nun 2958 Bytes verbraucht. 380 Bytes werden durch Variablenspeicher belegt.

Speicher und ihre Grösse

3K Speicher, den wir für unser Millionärsprogramm brauchten: Ist das viel oder ist das wenig? Es ist nicht unwichtig als Programmierer, ein bisschen ein Gefühl für Speicherbedarf und Speichergrössen zu entwickeln. Theoretisch wird das immer weniger wichtig, weil die Computerspeicher immer grösser werden. Aber an irgendwelchen Stellen ist immer ein Flaschenhals, der es nahelegt, einen Blick auf den Speicherbedarf zu werfen. Sei es die zur Verfügung stehende Modem-Übertragungsrate, sei es, dass der Computer, für den man gerade programmiert, ein Mobiltelefon ist, sei es, dass man ein Programm geschrieben hat, dass, je länger es läuft, je mehr Speicher braucht.

Aus der Sicht des Taschenrechners, mit der wir unser Tutorial gestartet haben, sind 3K viel. Wir sehen ja, dass wir rund 200 Programmzeilen darin untergebracht haben und dazu noch rund 100 Zahlenvariablen. Aus der Sicht heute üblicher Hauptspeichergrössen in PC's - 256 MB sind eher wenig - sind 3K ein Brösel, den man dort kaum noch wiederfinden wird. Deshalb ist es vielleicht nicht ganz unwichtig, sich einmal eine Übersicht über Speichergrössen zu verschaffen.




Hauptspeichergrössen

Die folgende Tabelle ist auch als nette Übersicht für etwas fortgeschrittenere Programmierer gedacht, daher tauchen einige Fachbegriffe auf, die wir noch nicht kennengelernt haben, wie z.B. "Stackspeicher".

Art des Speichers Grösse Jahre, in denen er aktuell war
Univac, erster in Serie gebauter Grossrechner, Kosten in heutigen Preisen ca. 2 Mio. EUR 8 K 1952-1960
PDP8, beliebter Minicomputer, Kosten 100.000 US$ 4K 1965 bis 1975
Commodore C16, Kosten 150 US$ 16 K 1985
Professioneller Büro-Computer (CP/M oder Apple) 64 K 1982
Erster DOS-PC 16 bis 64 K 1981
Maximaler Stackspeicher unter DOS und 16-Bit-Windows 64 K 1981 bis 1990
Maximaler konventioneller Hauptspeicher unter DOS 640 K 1981 bis 1990
PC 8 bis 32 MB 1995
Maximaler Hauptspeicher unter Windows 9x/ME 512 MB 1995 bis 2002
PC 128 bis 512 MB 2003
Hauptspeicherbedarf von Windows XP min. 40 MB ab 2002
Hauptspeicherbedarf von Linux 6 MB bis 100 MB (je nach Ausbau) ab 1994
Maximaler konventioneller Hauptspeicher unter 32-Bit-Linux/Windows 4 GB 1995 bis ?
Maximaler ansteuerbarer Hauptspeicher eines Pentium 4-PC's 64 GB 2001 bis ?



Massenspeichergrössen

Massenspeicher sind die Datenträger, die die Programme und Daten permanent speichern, auch in der Zeit, in der der Computer ausgeschaltet ist, wie z.B. eine Diskette (nicht mehr ganz aktuell) oder eine DVD, aber auch USB-Sticks u.a.

Art des Speichers Grösse Jahre, in denen er aktuell war
Lochkarte 640 Bytes 1940 bis 1985
Audiocassette C60 80 K 1965 bis 1985
Floppy Disk 1,44 MB 1985 bis 2003
Zip-Disk 100 MB bis 250 MB 1992 bis 2001
CD-ROM/CD-RW 700 MB ab 1994
DVD 4,7 GB ab 2000
DVD2 (blauer Laser) 27 GB (?) ab 2006
Festplatte 10 MB 1982
Festplatte 100 MB 1990
Festplatte 1 GB 1995
Festplatte 10 GB 2000
Festplatte 100 GB 2003
Festplatte 1 TB (?) 2006

Hoch- und Niedrigsprachen

Es ist nicht notwendig für einen Programmierer, sehr viel über die innere Funktion eines Computers zu wissen, aber die wesentlichsten Grundsätze zu kennen, ist sehr wichtig. Dazu gehört es, ein Executable von einem Quellcode unterscheiden zu können.

Maschinensprache

Es ist nicht so, dass die Elektronik eines Computers in der Lage wäre, mit dem BASIC-Programm umzugehen, das wir ihr vorsetzen. Die Elektronik eines Computers ist eigentlich ziemlich einfach. Sie besteht im Wesentlichen aus zwei Bausteinen:

  1. Dem Prozessor (CPU)
  2. Dem Hauptspeicher

Nur beide zusammen machen einen Computer aus. Der Prozessor alleine ist eher so etwas wie die eigentliche Rechenmaschine im Computer. Es ist ein Chip, ein schwarzer Baustein, mit vielen Kontaktbeinchen. Je nachdem, welche Spannungen an diesen Beinchen anliegen, aktivieren wir an dieser CPU eine ihrer Funktionen. Die CPU hat auch einige eigene Speicher. Es sind allerdings wenige, höchstens ein Dutzend, und sie haben feste Namen, z.B. E1, E2 usw. oder a,b,c bis i. Man nennt sie "Register". (Das können Sie wieder vergessen.) Eine Funktion kann z.B. sein, den Inhalt eines Speicherbytes in ein Register zu verfrachten. "ld E1,(8000)" hiesse z.B., den Inhalt von Speicherzelle 8000 in das Register E1 zu laden. "ld E1,(8000)" ist dabei nur der Name, den wir dieser Funktion geben, die CPU kennt die Funktion nur unter einer bestimmten Bitkombination in Form von Spannungen an ihren Füsschen. "add E1,E2" wäre z.B. eine andere solche Funktion. Es ist eine Art Programmiersprache, aber es ist eine sehr einfach gebaute, bescheidene Programmiersprache, in der es nicht einfach ist, ein "richtiges" Programm zu schreiben. Man nennt so eine Sprache Maschinensprache. Ein Programm in Maschinensprache nennt man ein Executable, weil es durch die CPU direkt ausführbar ist. Sie liegen als Dateien auf Ihrer Festplatte. Executables auf Windows-PCs enden mit .exe oder .com, auf Linux-PCs meist mit .bin (für "binary"). Bausteine von Executables auf Windows-PCs enden in der Regel mit der Endung ".dll".

Jede CPU "spricht" also ihre eigene Maschinensprache. Die Prozessoren aus der Familie der s.g. x86-Prozessoren (8088 bis Pentium 4) beherrschen alle 8088-Maschinensprache, selbst ein Pentium 4 aus dem Jahr 2002. Unter Windows 9x/NT/2000/XP sind allerdings alle Binaries in der originären Maschinensprache des 80386 geschrieben, so dass die 8088-Fähigkeit (s.g. "Real Mode") meist nicht mehr benötigt wird - ausser beim Starten des PC's. Der C16 hat als CPU eine 7502, ein Abkömmling des in den 80er-Jahren weit verbreiteten 6502. Dessen Maschinensprache hat gar nichts mit der der x86-CPU's zu tun. Ein Executable für x86-PC's läuft auch nicht auf einem Apple-Computer oder auf einer Sun-Workstation, da diese jeweils andere Prozessoren haben. Wenn eine CPU auf ein Programm in einer ihr fremden Maschinensprache trifft, haben wir eine Inkompatibilität: Executable und CPU sind nicht kompatibel, passen nicht zueinander.

Ab dem Jahr 2004 wird es neben Apple- und x86-PCs noch zwei weitere Prozessorfamilien geben: Itanium und Opteron (Athlon64). Beide beherrschen zwar die Maschinensprache des 80386 (das meint man, wenn man auch von "32-Bit-Modus" spricht), nicht mehr jedoch die des 8088. Und beide haben ihre eigene originäre (und unterschiedliche) Maschinensprache: Opteron-Binaries sind zum Itanium inkompatibel und umgekehrt.

Interpreter und Compiler

Wie kommt es aber, dass wir den C16 in BASIC programmieren können? Nun, einfach dadurch, dass im C16 ein bestimmtes Executable eingebaut ist. Dieses Maschinenprogramm geht den eingetippten BASIC-Text Zeile für Zeile durch und übersetzt ihn in 7502-Maschinensprache. Das hat zwei Vorteile:
  1. Wir müssen uns nicht mit der primitiven und technischen Maschinensprache herumschlagen und können so schneller und besser unser Programm erstellen.
  2. Der BASIC-Text, der s.g. Sourcecode oder zu deutsch Quelltext (Gegensatz zum Executable) kann auch auf anderen Computern verwendet werden. Dann übersetzt ein entsprechendes BASIC-Übersetzungsprogramm den Text in die dortige Maschinensprache.

Solch ein Maschinenprogramm, das einen Quelltext Zeile für Zeile in Maschinensprache übersetzt, nennt man einen Interpreter. Der C16 hat also einen eingebauten BASIC-Interpreter. Natürlich kann man auch für andere Sprachen Interpreter programmieren, so gibt es auch LISP-Interpreter, LOGO-Interpreter, Javascript-Interpreter usw.

Zu Interpretern gibt es auch eine Alternative: Compiler. Compiler übersetzen den Quelltext nicht Zeile für Zeile, sondern "auf einen Rutsch". Das führt dazu, dass man in einem Interpreter ein Quelltext-Programm einfach starten kann, als wäre es ein Executable. Bei der Arbeit mit einem Compiler muss man immer vorher den Übersetzungsvorgang starten, man muss den ganzen Quelltext compilieren. Der Lohn der Mühe ist, dass man dann ein fertiges Maschinenprogramm hat, das in der Regel einen Faktor 5 bis 10 schneller läuft, als interpretierte Programme.

Für den C16 wird es früher wohl keinen BASIC-Compiler gegeben haben. Der Grund lag in seinem zu kleinen Hauptspeicher. Ein Compiler braucht viel Hauptspeicher: Der Compiler selbst (er ist ja nicht fest eingebaut, wie der BASIC-Interpreter, sondern wird von Cassette oder Diskette geladen) muss gespeichert werden, der Quelltext und das Compilat, das fertige Maschinenprogramm. Dafür sind selbst 64K sehr knapp.