Compiler
Ein Compiler (in deutsch auch Kompilierer) dient dazu, eine Quellsprache in eine Zielsprache zu übersetzen. In den meisten Fällen wird Quelltext einer höheren Programmiersprache in Maschinensprache übersetzt. Ein kompiliertes Computerprogramm kann nicht mehr ohne Weiteres manipuliert und bearbeitet werden.
Ein Compiler arbeitet normalerweise auf dem System, auf dem auch das zur übersetzende Programm laufen soll. Läuft er auf einem anderen System (übersetzt man z.B. einen Assembler-Quelltext mit einem auf einem PC laufenden Compiler in ein PRG, das für einen C64 gedacht ist), spricht man von einem Cross-Compiler.
Es gibt auch Decompiler, die aus einem Kompilat wieder Quelltext gewinnen sollen, allerdings ist deren Erfolg und die Qualität des rückgewonnenen Codes stark von den Informationen abhängig, die noch im Kompilat stecken. Zum Beispiel gehen beim Kompilieren oft die Bezeichner "verloren" und der Dekompiler muss sich dann irgendwelche eigenen Namen "ausdenken". Außerdem kann die Lizenz einer zu bearbeitenden Software verbieten, sie zu dekompilieren. So ein Verbot kann unter bestimmten Umständen allerdings auch unwirksam sein. Das deutsche Urheberrecht kennt beispielsweise Ausnahmen in §69e, wenn es um die Interoperabilität mit anderen Programmen geht.
BASIC-Compiler[Bearbeiten | Quelltext bearbeiten]
Das im C64 eingebaute BASIC V2 lässt in vielerlei Hinsicht Optimierungspotenzial offen.
- Das Programm wird interpretiert. Das heißt, dass letztendlich gar nicht das BASIC-Programm selbst direkt auf der CPU läuft, sondern eine Art "Mittelmann" - der Interpreter - jeweils den nächsten BASIC-Befehl und seine Operanden liest, alle nötigen Daten zur Ausführung zusammensammelt und den Befehl dann ausführt. Das alles braucht Zeit und hat Effekte wie z.B. dass lange Variablennamen die Ausführung des Programms verlangsamen, da der Interpreter sie komplett lesen muss.
- Selbst Zahlenkonstanten werden im Speicher nicht in direkt verwertbarer Form, sondern PETSCII-kodiert abgelegt. Das führt dazu, dass z.B.
A=A+9999
etwas langsamer ist alsA=A+1
. - Variablen werden jeweils bei Bedarf gesucht. D.h. wird im Programm fünfmal direkt nacheinander
A=A+1
ausgeführt, sucht der Interpreter insgesamt zehnmal in seinem Variablenindex (siehe Artikel Speicherbelegung) nach Variable A. Bei kompilierten Programmen taucht der Variablenname dagegen typischerweise gar nicht mehr auf, stattdessen wird im Code immer direkt auf einen Speicherbereich verwiesen: ausA=A+1
wird sinngemäßspeicherzelle4711=speicherzelle4711+1
. - Programmzeilen müssen ebenso bei Bedarf gesucht werden: Wird z.B. per
GOTO 10000
zu Zeile 10000 gesprungen, geht der Interpreter das Programm im Speicher von vorne bis hinten durch, bis er Zeile 10000 findet. - IF springt in BASIC V2 bei nicht erfüllter Bedingung nicht etwa einfach zur nächsten Zeile, sondern überliest die nachfolgenden Befehle, was Zeit kostet. Das Gleiche gilt für REM. Kompilate überspringen den jeweilige Code einfach (oder lassen die Daten im Fall von REM einfach ganz weg).
- Das Programm muss während der Ausführung auf Syntaxfehler geprüft werden. Kompilierter Code wurde bereits beim Kompilieren auf Syntaxfehler geprüft, entsprechend sind weitere Prüfungen während des Programmablaufs nicht nötig.
- Selbst Zahlenkonstanten werden im Speicher nicht in direkt verwertbarer Form, sondern PETSCII-kodiert abgelegt. Das führt dazu, dass z.B.
- Die CPU 6510 des C64 ist eine 8-Bit-CPU, aber BASIC kennt den einzigen "natürlichen" Datentypen der CPU - das Byte, also eine Ganzzahl zwischen 0 und 255 - nicht. Alle Operationen mit Zahlen werden per langsamen Fließkommaoperationen abgebildet, selbst wenn z.B. im ganzen BASIC-Programm ausschließlich Ganzzahlen von 0 bis 255 benutzt werden.
- Es gibt Ganzzahlvariablen, die per
%
(wieA%
) gekennzeichnet werden, aber arithmetische Operationen mit ihnen werden trotzdem mit den langsamen Fließkommaoperationen ausgeführt. - Auch der Platzbedarf ist dadurch größer als meist nötig: Jede Zahlenvariable braucht fünf Bytes (außer in Feldern), obwohl Ganzzahlen sich meist platzsparender speichern lassen.
- Ein Beispiel:
FOR I=0 TO 255:NEXT
, also das ganzzahlige Durchzählen von 0 bis 255, braucht in BASIC etwa 0,4 Sekunden und 10 Bytes Platz für das Programm. Das vergleichbare Assembler (LDX #$00, loop: INX, BNE loop
, 5 Bytes) braucht rund 1,3 Millisekunden, ist also rund 300mal so schnell. Der Fairness halber muss erwähnt werden, dass der Geschwindigkeitsvorteil abseits vom Datentyp Byte deutlich geringer ausfällt und compiler-generierter Maschinencode bei weitem nicht so optimiert wie handgeschriebener Code ist, sowohl was Geschwindigkeit als auch Platzbedarf angeht.
- Es gibt Ganzzahlvariablen, die per
- Die Verwaltung von Strings ist nicht sonderlich geschickt umgesetzt. Werden Strings intensiv genutzt, wird u.U. eine langsame Garbage Collection durch den BASIC-Interpreter nötig.
- Der für Programm und Variablen nutzbare Bereich ist auf 38 kBytes begrenzt, obwohl eigentlich mehr RAM zur Verfügung steht.
BASIC-Compiler können ein BASIC-Programm in eine schnellere Form überführen, unter Umständen benötigt das Programm dann aber auch mehr Speicherplatz. Grundsätzlich kann das Programm dabei in eine Zwischensprache überführt werden (häufig P-Code genannt), die von einem weiteren Interpreter abgearbeitet wird, den der Compiler automatisch dem Ergebnisprogramm hinzufügt (passiert z.B. beim Blitz! Compiler). Alternativ kann das BASIC-Programm direkt in Maschinensprache (im Kontext auch M-Code genannt) überführt werden (z.B. BASIC-BOSS und MOSpeed). Einige Compiler wie z.B. der BASIC 64 Compiler unterstützen beide Varianten und können im Programm sogar umschalten. Typischerweise ist M-Code schneller und P-Code platzsparender: M-Code ist meist (deutlich) größer als das Ursprungsprogramm, P-Code unter Umständen sogar kleiner.
Das nach einer gewissen Menge von String-Operationen auftretende Problem der Garbage-Collection wird nach bisherigen Erkenntnissen nur durch den Basic-Boss und durch MOSpeed wirklich effektiv gelöst. Es können also durchaus auch im Kompilat früher oder später ähnlich gravierende Verzögerungen auftreten wie im BASIC-Sourcecode.
Weitere Einschränkungen finden sich in der nachfolgenden Übersicht.
Compiler | Compilierbare Dialekte | Besonderheiten |
Basic 64 Compiler |
|
|
Basic 128 Compiler |
||
Blitz! Compiler (Skyles Electrical Works) |
BASIC V2, ? | Unterstützt mehrere Laufwerke. Erzeugt ein Protokoll-File "Z/...", das nach dem Laden und LIST-Befehl aufschlüsselt, welche neuen Pseudozeilennummern welchen alten Zeilennummern entsprechen, hilfreich für Fehlersuche, falls trotz erfolgreichem Kompilieren das Kompilat abstürzt. Kompilat ist relativ klein (nutzt P-Code). Der Compiler unterstützt Integer-Optimierungen. Es existiert eine Anleitung, die zwar recht oberflächlich ist, aber die Bedienung ist sehr unkompliziert. Der Compiler kann mehrere Dateien in einem Rutsch übersetzen, die dann zusammen als Overlays agieren und Variablen teilen können. Es existieren mit blitz 0.1 und Reblitz64 von PC-Kommandozeile nutzbare Versionen (Cross-Development). |
Speedcompiler |
BASIC V2, ? | |
Basic-Boss |
BASIC V2, ? | Es existiert eine umfangreiche und detaillierte Anleitung. Vielfältige Befehle bieten enorm viele Einsatzmöglichkeiten, unter anderem flexible Speicherverwaltung, günstig für die Einbindung des Kompilats in ein Assembler-Programm. Der Compiler unterstützt Integer-Optimierungen. Beschleunigte Garbage-Collection. Bedingt durch die Komplexität müssen einige Restriktionen beim Erstellen des Ursprungscodes beachtet werden. Erzeugt ein relativ großes Kompilat. Sollte das Kompilieren ohne Fehlermeldung gelingen und das Kompilat dennoch abstürzen, lässt sich nicht ohne Weiteres zurückverfolgen, welche Zeile des Ursprungscodes Probleme bereitet. |
Austro-Speed |
BASIC V2, ? | Identisch mit Blitz!, Nachfolger von Austro-Comp. |
Simon's |
||
Laser BASIC Compiler |
|
Ein Kompilat mit Laser BASIC-Befehlen ist ohne Laden der Erweiterung lauffähig. Kompiliert trotz 3-Pass recht flott. Spezieller Integer-Modus, mit dem Programme ohne Fließkommazahlen schneller und kleiner werden. Unterstützt erweiterte Kontrollflussbefehle (ELSE, mehrzeilige Blöcke). LOAD aus dem Programm ist nicht möglich. |
Diabolo |
BASIC V2 (nur Integer-Arithmetik) | |
PETSPEED 64 |
BASIC V2 | |
PETSPEED 128 |
BASIC 7.0 | |
MOSpeed |
BASIC V2 | Cross-Compiler, läuft nativ auf dem PC, erzeugt Code für den C64, den VC20, den X16, Javascript oder Powershell. Open Source Optimierender Compiler. Startadresse des Kompilats frei wählbar. Erzeugt echten Maschinencode. Schreibt auf Wunsch den erzeugten Assemblerquelltext mit raus. Erzeugt systembedingt ein relativ großes Kompilat (das aber über eine Compiler-Option zu Lasten der Geschwindigkeit verkleinert werden kann). Der Compiler kennt keinen expliziten Integer-Typ. Integer-Berechnungen lassen sich also nur sehr eingeschränkt beschleunigen. |
DTL-Basic 64 Drive Technology Ltd.[1] |
BASIC V2 | Auch als Kassettenversion verfügbar. Limitierung auf 12 KByte Sourcecode (zumindest bei der Kassettenversion). |
super limited basic compiler (sl-basic)[2] | Untermenge von BASIC V2 (nur Integer, nur eindimensionale Arrays etc.) |
schnell (M-Code) Bringt eigene schnelle Version von PRINT Compiler startet komfortabel aus Steckmodul Kann BASIC- und KERNAL-ROM ausblenden Inkl. Quelltexten Sehr eingeschränkter Befehlssatz |
Micro Compiler[3] | Untermenge von BASIC V2 | schnell (M-Code) sehr eingeschränkter Befehlssatz scheint häufig fehlerhaften Code zu erzeugen |
Benchmarks[Bearbeiten | Quelltext bearbeiten]
Aus u.a. einem Forum64-Beitrag von muffi.
Zeiten in 60tel Sekunden, Benchmark-PRG siehe Link.
R: (Schleifen) mit Real-Variablen, I: (Schleifen) mit Integer-Variablen (%
).
Die Größe des kompilierten Programms bezieht sich auf den gesamten Benchmark, differenziert also nicht zwischen Real und Integer.
Compiler | FOR/NEXT | Init IntArr | Init StrArr | Append StrArr | Cosinus | Init RealArr | Arr-Zugriff/IFs | DEF FN | GOSUB | SYS49152,X,Y | Code-Größe (Blöcke) | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
(BASIC V2) | 7452 | 305 | 274 | 485 | 1792 | 309 | 8475 | 4800 | 5776 | 2993 | 6147 | 13 |
Basic Boss (R) | 6499 | 100 | 138 | 233 | 1682 | 127 | 3002 | 1426 | 1366 | 2585 | 2936 | 33 |
Basic Boss (I) | 1645 | 18 | 62 | 108 | 1676 | 45 | 611 | 1465 | 1468 | 2548 | 3225 | 33 |
BASIC64 (P-Code, R) | 7047 | 115 | 123 | 193 | 1691 | 124 | 2365 | 1513 | 1408 | 2723 | 5731 | 32 |
BASIC64 (P-Code, I) | 1767 | 54 | 64 | 114 | 1657 | 63 | 1377 | 1814 | 1827 | 2680 | 5296 | 32 |
BASIC64 (M-Code, R) | 6946 | 97 | 109 | 168 | 1677 | 107 | 1718 | 1416 | 1325 | 2702 | 5365 | 45 |
BASIC64 (M-Code, I) | 1665 | 36 | 51 | 90 | 1642 | 47 | 723 | 1712 | 1739 | 2661 | 4953 | 45 |
Austro-Comp (R) | 6472 | 114 | 125 | 213 | 1700 | 122 | 1642 | 1675 | 1647 | 2496 | 3395 | 24 |
Austro-Comp (I) | 1911 | 64 | 76 | 150 | 1609 | 73 | 1761 | 1676 | 1518 | 2461 | 3849 | 24 |
Austro-Speed/Blitz (R) | 6027 | 89 | 97 | 155 | 1680 | 96 | 1753 | 1539 | 1535 | 2464 | 3263 *1 | 32 |
Austro-Speed/Blitz (I) | 1272 | 39 | 48 | 95 | 1647 | 47 | 1151 | 1532 | 1412 | 2428 | 3706 *1 | 32 |
SC (R) | 6472 | 114 | 125 | 214 | 1699 | 122 | 2710 | 1675 | 1647 | 2495 | 3395 | 24 |
SC (I) | 1911 | 64 | 76 | 150 | 1669 | 73 | 1761 | 1679 | 1521 | 2461 | 3837 | 24 |
Sauron (R) | 6027 | 89 | 97 | 156 | 1680 | 97 | 1732 | 1538 | 1533 | 2465 | 3271 | 32 |
Sauron (I) | 1271 | 40 | 48 | 95 | 1647 | 47 | 1141 | 1532 | 1412 | 2427 | 3713 | 32 |
Petspeed (R) | 1580 | 38 | 44 | 76 | 1654 | 40 | 1149 | 1401 | 1333 | 2671 | x | (90) |
Petspeed (I) | 1494 | 37 | 46 | 75 | 1654 | 39 | 1140 | 1477 | 1421 | 2668 | x | (90) |
Laser BASIC Compiler (R) | 6448 | 161 | 154 | 287 | 1703 | 151 | 4626 | 1666 | 1620 | 2620 | x | 37 |
Laser BASIC Compiler (I) | 1925 | 69 | 79 | 173 | / *2 | 68 | 1760 | / *2 | / *2 | 2586 | x | 29 |
DTL (R) | 6355 | 124 | 128 | 225 | 1694 | 148 | 2893 | 1619 | 1592 | 2998 | 3560 | 11 |
DTL (I) | 1666 | 52 | 57 | 123 | 1671 | 77 | 1434 | 1687 | 1551 | 2963 | 3968 | 11 |
MOSpeed (R) | 6213 | 99 | 110 | 205 | 1667 | 108 | 2522 | 911 | 816 | 2687 | x | 78 |
*1: Inkorrekte Ausgabe (Leerzeichen fehlen). Reblitz64 hat dieses Problem nicht.
*2: Im Integer-Modus unterstützt der Laser BASIC Compiler keinerlei Fließkommaberechnungen.
Beobachtungen
- Praktisch alle Benchmarks profitieren stark von Integer-Optimierungen.
- M-Code ist insbesondere im Zusammenhang mit Integer-Operationen und Array-Zugriffen deutlich schneller als P-Code, bringt ansonsten aber wenig Gewinn.
- Auch kompilierter Code ruft z.B. für Cosinus und PRINT typischerweise die Originalroutinen des BASIC bzw. KERNALs auf. Als Vergleich: Wird der PRINT-Benchmark mit Crank the PRINT! optimiert, braucht er statt rund 42 Sekunden (2500 Sechzigstelsekunden) nur ca. 5,5 Sekunden, weil das langsame KERNAL-PRINT umgangen wird.
Übersicht zu Einschränkungen[Bearbeiten | Quelltext bearbeiten]
Compiler | Explizite Integer-Unterstützung | P-Code/M-Code | DIM für einfache Variablen[4] | Implizites DIM[4] | alternative Garbage-Collection |
Basic 64 Compiler | beides | Nachfrage | |||
Basic 128 Compiler | beides | Nachfrage | |||
Blitz! Compiler | P-Code | Nachfrage | |||
Speedcompiler | ? | ? | Nachfrage | ||
Basic-Boss | M-Code | implizit immer 11 (0-10) | |||
Austro Speed | P-Code | Nachfrage | |||
Simon's Austro Speed | P-Code | Nachfrage | |||
Laser BASIC Compiler | ? | ? | Nachfrage | ||
Diabolo | ? | ? | Nachfrage | ||
PETSPEED 64 | ? | ? | Nachfrage | ||
PETSPEED 128 | ? | ? | Nachfrage | ||
MOSpeed | M-Code | (in Verwendung als Konstante[5]) |
|||
DTL-Basic 64 | ? | ? | Nachfrage |
Quellen[Bearbeiten | Quelltext bearbeiten]
- ↑ DTL-Basic 64 Compiler angekündigt in Personal Computer News: Go Faster With DTL, David Janda looks at a cassette-based C64 Basic compiler
- ↑ Thema: Super limited basic compiler for Commodore 64 auf Forum64.de
- ↑ Micro Compiler aus der RUN 07/1986 S. 83, siehe Thema: Heute so compiliert... auf Forum64.de (D64), Anleitung siehe Posting #371
- ↑ 4,0 4,1 Behandlung von DIM in BASIC-Compilern: Thema: BASIC V2 Interpreter/Compiler in/für Java auf Forum64.de
- ↑ Behandlung von DIM bei MOSpeed: Thema: BASIC V2 Interpreter/Compiler in/für Java auf Forum64.de
Weblinks[Bearbeiten | Quelltext bearbeiten]
Wikipedia: Compiler |
- Commodore Programmiersprachenliste
- Programmieren (C64-Online)
- commodore.software / Category: BASIC-Compilers
- 64'er 1994/8 S. 26: Konkurrenz für den Boss - Compiler-Vergleichstest (Scan auf archive.org)
Auswahl ursprünglich in BASIC geschriebener kompilierter Programme
- CSDb- Release Nr. 23516 Mafia (Spiel), austro-compiled
- CSDb- Release Nr. 95669 Mafia 1.31 (Spiel), blitz-compiled
- CSDb- Release Nr. 100821 Murder V1.2 (Spiel), blitz-compiled
- CSDb- Release Nr. 102382 Snake on a Plane V1.1 (Spiel), boss-compiled
- CSDb- Release Nr. 170070 Brush up your English, austro-compiled