jens.ebinger Geschrieben 5. Juni 2007 Geschrieben 5. Juni 2007 Hallo. Vorgeschichte: Ich habe mal in alten Zeitschriften geblättert, u.a. aus den 80ern. Da gibt es für einen "nicht unbekannten" 8-Bit-Computer (der über 17 Mio. Mal verkauft wurde) einen Compiler für BASIC, der den mitgelieferten Befehlssatz um weitere erweitert / vorhandene ergänzt. Z.B. bessere Garbage-collection bei Variablen etc. Da stand dabei, dass der Compiler (der wohl keinen Assemblercode erzeugt hat, sondern sog. "P-Code", d.h. ein Runtimemodul braucht) mit sich selbst kompiliert wurde? Wie geht denn das? Kann man sich doch an den eigenen Haaren aus dem Sumpf ziehen? Ich verstehs halt nicht Mit in diesem Zusammenhang fällt ein anderer Artikel, deutlich neuer (dennoch alt), in dem steht "Es hilft nichts, den Quellcode eines Compilers zu haben, zu lesen und zu prüfen, wenn alle Binaries des Compilers verseucht sind (d.h. Schadcode mutwillig einbauen". Schließlich braucht man ja (z.B.) einen GCC um einen GCC (neuerer Version) zu erzeugen? Wie schützt man sich vor so etwas (im Zeitalter von Tausenden Befehlen, die ein Prozessor heute versteht und Millionen ausgeführten Befehlen pro Sekunde)? Ciao. Zitieren
Klotzkopp Geschrieben 5. Juni 2007 Geschrieben 5. Juni 2007 Da stand dabei, dass der Compiler (der wohl keinen Assemblercode erzeugt hat, sondern sog. "P-Code", d.h. ein Runtimemodul braucht) mit sich selbst kompiliert wurde? Wie geht denn das? Kann man sich doch an den eigenen Haaren aus dem Sumpf ziehen?Man kann einen Compiler nur dann mit sich selbst kompilieren, wenn man ihn vorher mit einem anderen Compiler kompiliert hat. Wenn man beispielsweise neue Optimierungen zu einem Compiler hinzugefügt hat, muss man ihn zweimal kompilieren (einmal mit der alten, dann nochmal mit der dabei gebauten neuen Version), um eine optimierte Version des neuen Compilers zu erhalten. Vielleicht ist das damit gemeint. "Es hilft nichts, den Quellcode eines Compilers zu haben, zu lesen und zu prüfen, wenn alle Binaries des Compilers verseucht sind (d.h. Schadcode mutwillig einbauen". Schließlich braucht man ja (z.B.) einen GCC um einen GCC (neuerer Version) zu erzeugen? Wie schützt man sich vor so etwas (im Zeitalter von Tausenden Befehlen, die ein Prozessor heute versteht und Millionen ausgeführten Befehlen pro Sekunde)?Ich sehe nicht, was das mit der Rechenleistung zu tun hat. Üblicherweise schütz man sich vor Manipulation, indem man den Compiler als signiertes Binärpaket von einer vertrauenswürdigen Quelle bezieht. Zitieren
jens.ebinger Geschrieben 7. Juni 2007 Autor Geschrieben 7. Juni 2007 Ich sehe nicht, was das mit der Rechenleistung zu tun hat. Beim Commodore 64 gab es weniger als 60 Assemblerbefehle, die kannte man recht schnell. Disketten waren überschaubar gross, und Compiler gab es nur wenige verschiedene in überschaubar viel Versionen. Zitieren
Klotzkopp Geschrieben 7. Juni 2007 Geschrieben 7. Juni 2007 Beim Commodore 64 gab es weniger als 60 Assemblerbefehle, die kannte man recht schnell. Dass man den Befehlssatz kennt, bedeutet aber nicht, dass man den Schadcode in einem Compiler entdecken kann, indem man den Assemblercode prüft. Dazu gehört nun doch etwas mehr. Und die Größe des Befehlssatzes hat nichts mit der Rechenleistung zu tun. Was den Schutz vor einem "verseuchten" Compiler angeht, ist da IMHO weder die Größe des Befehlssatzes noch die Rechenleistung relevant. Man schützt sich, indem man Programme nur aus zuverlässigen Quellen bezieht. Zitieren
nic_power Geschrieben 8. Juni 2007 Geschrieben 8. Juni 2007 Hallo, Wie geht denn das? Kann man sich doch an den eigenen Haaren aus dem Sumpf ziehen? Zumindest für den ersten Compilerdurchlauf (stage0) benötigst Du einen externen/anderen Compiler. Das sich Compiler selbst übersetzen ist eine recht verbreitete Vorgehensweise. Wenn Du beispielsweise den gcc übersetzt wird im ersten Schritt ein sogenannte "stage0" compiler erzeugt. Mit diesem stage0 Compiler übersetzt man dann den Quellcode erneut. Das macht man aus mehreren Gründen: Es gibt/gab Hersteller, die nur sehr einfache Compiler mit dem Betriebssystem ausliefern (beispielsweise ohne jegliche Optimierungsmöglichkeiten). Da der Code (und damit der übersetzte stage1 Compiler) langsam ist, übersetzt man mit dem stage1 Compiler erneut und erhält somit eine optimierte Version. Viele Compiler unterstützen spezielle Features. Diese lassen sich jedoch nur nutzen, wenn sie auch im Compiler "eingeschaltet" wurden (d.h. der stage1 Compiler kann Spezialfeatures nur dann nutzen, wenn er mit der stage0 übersetzt wurde, nicht jedoch, wenn er mit dem Standard-Compiler übersetzt wurde) Compilerschreiber halten ihren Compiler immer für den besten. Von daher sollte man zum Übersetzen auch den eigenen Compiler verwenden und nicht einen beliebigen Fremd-Compiler. Beim Commodore 64 gab es weniger als 60 Assemblerbefehle, die kannte man recht schnell. Disketten waren überschaubar gross, und Compiler gab es nur wenige verschiedene in überschaubar viel Versionen. Die Anzahl der Assemblerbefehle hat nichts damit zu tun, wie sicher ein Compiler ist. Schadcode erzeugt man durch die geschickte Kombination von Assemblercode, welcher Sicherheitslücken im System ausnutzt. Ob man dafür nun drei Befehle verwendet oder 300 spielt keine Rolle. Komplexe Befehle haben den Nachteil dass ein Compiler erstmal erkennen muss, dass er sie einsetzen kann. Und das ist alles andere als trivial! Nic Zitieren
jens.ebinger Geschrieben 9. Juni 2007 Autor Geschrieben 9. Juni 2007 Zumindest für den ersten Compilerdurchlauf (stage0) benötigst Du einen externen/anderen Compiler. Das sich Compiler selbst übersetzen ist eine recht verbreitete Vorgehensweise. Wenn Du beispielsweise den gcc übersetzt wird im ersten Schritt ein sogenannte "stage0" compiler erzeugt. Mit diesem stage0 Compiler übersetzt man dann den Quellcode erneut. Ah jetzt, danke für die ausführliche Erklärung. Um auf mein Beispiel (Basic-erweiterung via Pseudo-code) zurückzukommen, wie geht denn das nun genau? Auf dem C64 lief der (mitgelieferte) Basic-Editor (programm im Hauptspeicher). Wenn man "run" gesagt, hat wurde eine Betriebssystem-routine aufgerufen, die Zeile für Zeile den "Quelltext" geholt, ausgewertet und ausgeführt hat. Das ist (soweit ichs verstehe) der normale Weg für Interpretierte Sprachen, wie es Basic oft ist. Mit dem basic-erweiterung via Compiler nun werden statt 50 Befehle statt 40 verstanden. So weit, so gut. Einfach die Kernelroutine, die die Zeile holt umbiegen, im falle der Befehle Nr. 41-50 eigene Routine ausführen, sonst normale BS-Routine. Kein Problem soweit. (denke ich) Ein Compiler, der ein vorhandenes basic-Programm (mit oder ohne erweitereten befehlssatz) in ein Assemblerprogramm umsetzt, ist auch vorstellbar, nichts anderes macht das Betriebssystem-Interpreter dauernd. Wie programmiere ich jedoch einen Basic-Compiler in Basic? Andere Programmiersprachen gab es auch dem C64 auch, aber 98% waren Basic oder Assembler. Nicht dass ich heute vorhätte, einen Basic-Compiler zu schreiben, ich will nur die Verfahrensweise verstehen. Danke Zitieren
Klotzkopp Geschrieben 9. Juni 2007 Geschrieben 9. Juni 2007 Ein Compiler, der ein vorhandenes basic-Programm (mit oder ohne erweitereten befehlssatz) in ein Assemblerprogramm umsetzt, ist auch vorstellbar, nichts anderes macht das Betriebssystem-Interpreter dauernd.Naja, ganz so trivial ist der Unterschied nicht. Der Interpreter muss nur den gerade aktuellen Code ausführen und den Status vorhalten, der Compiler muss etwas erstellen, das später auch ohne ihn selbst läuft. Wie programmiere ich jedoch einen Basic-Compiler in Basic?Du schreibst den Compiler, führst ihn mit dem Interpreter aus und lässt ihn seinen eigenen Quellcode verarbeiten. Ein Compiler kann sich nicht aus dem eigenen Quellcode selbst erzeugen. Dazu brauchst du immer ein anderes Programm, sei es eine ältere Version oder ein Übersetzungsprogramm für eine andere Sprache - in deinem Basic-Compiler-Beispiel eben einen Basic-Interpreter. Am Anfang steht immer ein in Maschinensprache geschriebenes Programm, vermutlich ein Assembler. Und darauf wird dann aufgebaut. Zitieren
jens.ebinger Geschrieben 9. Juni 2007 Autor Geschrieben 9. Juni 2007 Am Anfang steht immer ein in Maschinensprache geschriebenes Programm, vermutlich ein Assembler. Und darauf wird dann aufgebaut. Tja, aber was ist dann in dem "in Maschinensprache geschriebenes Programm" Wie "mitgelieferte" Befehle in Assembler umgesetzt werden kann man (durch beim C64 im ROM integrierten) Basic-Interpreter nachlesen/nachbauen. Die erweiterten Basic-befehle könnens auch nicht sein, denn die sind ja (beim fertigen Compiler) über P-Code gemacht, weil "assembler bringt kaum geschwindigkeitsvorteile, braucht aber mehr platz". Zitieren
Guybrush Threepwood Geschrieben 9. Juni 2007 Geschrieben 9. Juni 2007 Also ich versteh irgendwie die Problematik nicht :confused: Vereinfacht gesagt: Ein Compiler wandelt eine Programm einer bestimmten Syntax in Assemblercode um (meistens) und ein Linker den Assemblercode in Maschinencode. Fertig Es wird also "einfach" nur etwas immer weiter eine Ebene tiefer übersetzt bis der Computer was damit anfangen kann. Zitieren
Klotzkopp Geschrieben 9. Juni 2007 Geschrieben 9. Juni 2007 Tja, aber was ist dann in dem "in Maschinensprache geschriebenes Programm" Könntest du bitte mal klarstellen, ob es hier um ein allgemeines Verständnisproblem geht, oder um einen konkreten Basic-Compiler auf einer spezifischen Plattform? Irgendwie verstehe ich weder deine Fragen noch dein Problem. Ich habe das Gefühl, du fragst immer wieder dasselbe. Zitieren
jens.ebinger Geschrieben 9. Juni 2007 Autor Geschrieben 9. Juni 2007 Frage ist: wie schreibe ich eine Compiler in Sprache X, der sich selbst compilieren kann? Aktueller Stand der Antwort: gar nicht, man braucht einen "Hilfs-Programm" oder "stage0"-Compiler oder ähnliches. Was macht das "Hilfs-Programm", z.b. in Falles eine Basic-Compilers (auf beliebiger Plattform). Direkt einen Basic-compiler in Assembler (ohne die Selbstkompilierungseigenschaft) schreiben ist ja machbar, teilweise aufwendig aber machbar. Wie ist das nun im Falle eines (Basic- oder Pascal)-compilers, der sich (irgendwann, im Schritt 17) selbt kompilieren soll? Was steht da im Hilfsprogramm? Ich rede hier von Basic, mit dem Befehlssatz vom 197x, also IF/THEN/PRINT/GOTO/INPUT, nicht viel mehr. Pascal ist vermutlich komplizierter. Die Sinnhaftigkeit eines solchen Programms heute mal aussen vor. Zitieren
Guybrush Threepwood Geschrieben 9. Juni 2007 Geschrieben 9. Juni 2007 Es ist für den Compiler doch vollkommen egal was da am Ende für ein Programm rauskommt. Das einzige was er macht ist Stück für Stück den Code zu übersetzen. Ob da am Ende jetzt eine neuere Version des Compilers, ein Hallo Welt Programm oder sonst was rauskommt ist doch unwichtig. Zitieren
Klotzkopp Geschrieben 9. Juni 2007 Geschrieben 9. Juni 2007 Wie ist das nun im Falle eines (Basic- oder Pascal)-compilers, der sich (irgendwann, im Schritt 17) selbt kompilieren soll? Was steht da im Hilfsprogramm?Im "Hilfsprogramm" steht, wie man ein Basic-Programm übersetzt oder ausführt. Das "Hilfsprogramm" muss ja nicht derselbe Compiler sein, der da gebaut werden soll. Es muss überhaupt kein Compiler sein, ein Interpreter tut's ja auch. Und das Hilfsprogramm muss auch nicht in Basic geschrieben worden sein. Wie ich bereits (mehrfach?) sagte, am Anfang dieser Kette steht ein von Hand in Maschinensprache geschriebenes Programm, das in einer höheren Sprache geschriebenes Programm ausführen kann. Und wenn man irgendwann mal ein Programm hat, das Basicprogramme ausführen kann, kann man auch einen Basic-Compiler in Basic schreiben, wenn man denn möchte. Du kannst aber keinen Basic-Compiler in Basic schreiben, ohne ein anderes Programm, das Basic ausführen kann. Ich verstehe immer noch nicht, wo du da ein Problem siehst. Zitieren
nic_power Geschrieben 9. Juni 2007 Geschrieben 9. Juni 2007 Hallo, Vereinfacht gesagt: Ein Compiler wandelt eine Programm einer bestimmten Syntax in Assemblercode um (meistens) und ein Linker den Assemblercode in Maschinencode. Fertig Der Linker erzeugt aus mehreren Objekt- und ggf. Bibliotheksdateien das ausführbare Programm, für das Übersetzen des Assembercodes ist der Assembler zuständig. Frage ist: wie schreibe ich eine Compiler in Sprache X, der sich selbst compilieren kann? Aktueller Stand der Antwort: gar nicht, man braucht einen "Hilfs-Programm" oder "stage0"-Compiler oder ähnliches. Um ein Programm in einer bestimmten Sprache (also beispielsweise C) übersetzen zu können, benötigst Du einen Compiler. In welcher Sprache dieser geschrieben ist, spielt im Prinzip keine Rolle. Wenn Du mit einer Architektur arbeiten musst, für die keinerlei Compiler existieren, musst Du diesen in Handarbeit und im Extremfall in Assembler-Code selbst erstellen (in der Praxis sieht es anders aus, da man dort mit Cross-Compilern arbeitet). Nic Zitieren
jens.ebinger Geschrieben 9. Juni 2007 Autor Geschrieben 9. Juni 2007 Im "Hilfsprogramm" steht, wie man ein Basic-Programm übersetzt oder ausführt. Das "Hilfsprogramm" muss ja nicht derselbe Compiler sein, der da gebaut werden soll. Es muss überhaupt kein Compiler sein, ein Interpreter tut's ja auch. Und das Hilfsprogramm muss auch nicht in Basic geschrieben worden sein.... am Anfang dieser Kette steht ein von Hand in Maschinensprache geschriebenes Programm, das in einer höheren Sprache geschriebenes Programm ausführen kann. Okay, d.h. doppelte Entwicklungsarbeit: Einmal das Assemblerprogramm, dass die Basic-Befehle (plus evtl. Erweiterungen) interpretieren und ausführen und in eine neue Datei speichern kann. Dann der finale Compiler (der in meinem Beispiel P-Code erzeugt, also kein reines Assembler) Ich verstehe immer noch nicht, wo du da ein Problem siehst. Leistungsumfang und Struktur des Hilfsprogramms --> Ich denk mir das nochmal mit ner guten Zigarre durch, und melde mich dann mal, wenn da noch fragen sind. Irgendwie drücke ich mich unklar aus. Ma guggn, einstweilen danke Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.