Zum Inhalt springen

Verständnisfrage: Compiler mit sich selbst kompiliert?


Empfohlene Beiträge

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.

Link zu diesem Kommentar
Auf anderen Seiten teilen

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.
Link zu diesem Kommentar
Auf anderen Seiten teilen

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.

Link zu diesem Kommentar
Auf anderen Seiten teilen

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

Link zu diesem Kommentar
Auf anderen Seiten teilen

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

Link zu diesem Kommentar
Auf anderen Seiten teilen

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.

Link zu diesem Kommentar
Auf anderen Seiten teilen

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".

Link zu diesem Kommentar
Auf anderen Seiten teilen

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.

Link zu diesem Kommentar
Auf anderen Seiten teilen

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.

Link zu diesem Kommentar
Auf anderen Seiten teilen

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.

Link zu diesem Kommentar
Auf anderen Seiten teilen

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.

Link zu diesem Kommentar
Auf anderen Seiten teilen

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

Link zu diesem Kommentar
Auf anderen Seiten teilen

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

Link zu diesem Kommentar
Auf anderen Seiten teilen

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.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...