Ich lese gerade das Buch Die Elemente von Computersystemen: Aufbau eines modernen Computers aus ersten Prinzipien , das Projekte umfasst, die den Aufbau eines Computers von Booleschen Gattern bis hin zu Anwendungen auf hoher Ebene (in dieser Reihenfolge) umfassen. Das aktuelle Projekt, an dem ich arbeite, besteht darin, einen Assembler in einer Sprache meiner Wahl zu schreiben, der vom Hack-Assembly-Code in den Hack-Maschinencode übersetzt (Hack ist der Name der Hardware-Plattform, die in den vorherigen Kapiteln erstellt wurde). Obwohl die Hardware alle in einen Simulator eingebaut wurde, habe ich versucht vorzutäuschen, dass ich wirklich jede Ebene mit nur den Werkzeugen konstruiere, die mir zu diesem Zeitpunkt im realen Prozess zur Verfügung stehen.
Das heißt, es hat mich zum Nachdenken gebracht. Die Verwendung einer höheren Programmiersprache zum Schreiben meines Assemblers ist sicherlich praktisch, aber für den allerersten Assembler, der jemals geschrieben wurde (dh in der Geschichte), müsste er nicht in Maschinencode geschrieben werden, da dies alles war, was zu dieser Zeit existierte?
Und eine korrelierte Frage ... wie wäre es mit heute? Wie würde der Assembler aufgebaut sein, wenn eine brandneue CPU-Architektur mit einem brandneuen Befehlssatz und einer brandneuen Assemblersyntax herauskommen würde? Ich gehe davon aus, dass Sie weiterhin eine vorhandene Hochsprache verwenden könnten, um Binärdateien für das Assembler-Programm zu generieren. Wenn Sie die Syntax sowohl der Assembler- als auch der Maschinensprache für Ihre neue Plattform kennen, ist die Aufgabe, den Assembler zu schreiben, eigentlich nur eine Textanalyse-Aufgabe und ist nicht inhärent mit dieser Plattform verbunden (dh muss in der Maschinensprache dieser Plattform geschrieben sein). Dies ist der Grund, warum ich in der Lage bin, beim Schreiben meines Hack-Assemblers im Jahr 2012 zu "schummeln" und einige bereits vorhandene zu verwenden Hochsprache, um mir zu helfen.
Antworten:
Nicht unbedingt. Natürlich muss die allererste Version v0.00 des Assemblers in Maschinencode geschrieben worden sein, aber es wäre nicht leistungsfähig genug, um als Assembler bezeichnet zu werden. Es würde nicht einmal die Hälfte der Funktionen eines "echten" Assemblers unterstützen, aber es würde ausreichen, die nächste Version von sich selbst zu schreiben. Anschließend können Sie v0.00 in die Teilmenge der Assemblersprache neu schreiben, v0.01 aufrufen, damit den nächsten Funktionssatz Ihres Assemblers v0.02 erstellen und dann v0.02 zum Erstellen von v0.03 verwenden so weiter, bis du zu v1.00 kommst. Infolgedessen befindet sich nur die erste Version im Maschinencode. Die erste veröffentlichte Version wird in der Assemblersprache sein.
Ich habe die Entwicklung eines Template-Sprach-Compilers mit diesem Trick gebootet. Meine ursprüngliche Version verwendete
printf
Anweisungen, aber die erste Version, die ich in meinem Unternehmen verwendete, verwendete genau den Vorlagenprozessor, den sie verarbeitete. Die Bootstrapping-Phase dauerte weniger als vier Stunden: Sobald mein Prozessor kaum brauchbare Ausgaben produzieren konnte, schrieb ich sie in seiner eigenen Sprache neu, kompilierte sie und warf die nicht vorlagenbasierte Version weg.quelle
diff
des aktuellen Codegenerators, um festzustellen, ob sich der generierte Codeabschnitt nicht unerwartet geändert hat, und dem Ersetzen des vorhandenen Codes Führen Sie es erneut aus, um den Zyklus zu beenden.Laut Wikipedia wurde von Nathaniel Rochester die erste Assembler- / Assemblersprache für den IBM 701 implementiert . (Die Daten sind ein wenig unsicher aus dem Wikipedia - Artikel. Darin heißt es , dass Rochester IBM im Jahr 1948 beigetreten sind , aber ein andere Wikipedia - Seite heißt es, dass die 701 öffentlich im Jahr 1952 angekündigt wurde und diese IBM - Seite heißt es, dass „[a] ctual Design am Februar gestartet 1, 1951 und wurde ein Jahr später abgeschlossen " .)
In "Assemblers and Loaders" von David Salomon heißt es jedoch (auf Seite 7), dass EDSAC auch einen Assembler hatte:
Unter der Annahme , wir , dass „Erstbestellungen“ akzeptieren haben Vorrang, haben wir klare Hinweise darauf , dass der erste Assembler wurde in Maschinencode umgesetzt.
Dieses Muster (Schreiben der ersten Assembler in Maschinencode) wäre bis weit in die 1950er Jahre hinein die Norm gewesen. Laut Wikipedia waren "[a] ssembler die ersten Sprachwerkzeuge, die sich selbst booteten". Siehe auch diesen Abschnitt, in dem erläutert wird, wie ein von einem ursprünglichen Assembler geschriebener Maschinencode verwendet wurde, um einen fortgeschritteneren Assembler zu booten, der in Assemblersprache codiert wurde.
Heutzutage sind Assembler und Compiler in höheren Sprachen geschrieben, und ein Assembler oder Compiler für eine neue Maschinenarchitektur wird in der Regel auf einer anderen Architektur entwickelt und kreuzkompiliert.
(FWIW - Das Schreiben und Debuggen von nicht trivialen Programmen in Maschinencode ist ein äußerst mühsamer Prozess. Jemand, der einen Assembler in Maschinencode entwickelt, würde höchstwahrscheinlich so schnell wie möglich einen Assembler booten, der in Assembler geschrieben ist.)
Diese Wikipedia-Seite zum Thema Bootstrapping von Compilern und Assemblern ist eine Lektüre wert ... wenn Ihnen das alles rätselhaft erscheint.
quelle
Ich gehe davon aus, dass die ersten Assembler in Maschinencode geschrieben wurden, weil, wie Sie sagen, damals nichts anderes verfügbar war.
Wenn heute jedoch eine brandneue CPU-Architektur herauskommt, verwenden wir einen sogenannten Cross-Compiler , einen Compiler, der Maschinencode nicht für die Architektur erzeugt, auf der er ausgeführt wird, sondern für eine andere Architektur.
(Tatsächlich gibt es, wie Sie sicher später in dem Buch, das Sie lesen, herausfinden werden, absolut nichts, was einen Compiler von Natur aus besser für die Erstellung von Maschinencode für die Architektur geeignet macht, auf der er ausgeführt wird, als auf jeder anderen andere Architektur: Es ist nur eine Frage der Architektur, auf die Sie als Schöpfer des Compilers abzielen.)
So ist es heutzutage (zumindest theoretisch) sogar möglich, eine brandneue Architektur zu erstellen und Hochsprachen-Compiler (die auf anderen Architekturen mithilfe von Cross-Compilern kompiliert wurden) laufen zu lassen, bevor Sie überhaupt einen Assembler für diese Architektur haben.
quelle
Zuerst wurde "Assembly" auf Papier geschrieben und dann manuell auf Lochkarten "kompiliert".
Mein Großvater hat mit einem ZRA1 gearbeitet (sorry, Seite existiert nur in Deutsch, aber die Google-Übersetzung ist soweit in Ordnung , dass Sie die wichtigsten Fakten tatsächlich erfassen können: D).
Der Modus Operandi bestand darin, Ihren Code in einer Art Assemblersprache auf Papier zu schreiben, und die Sekretärin führte die Transkription auf Lochkarten durch, gab sie dann an den Operator weiter und das Ergebnis wurde am nächsten Morgen zurückgegeben.
All dies geschah im Wesentlichen, bevor Programmierer den Luxus hatten, Daten über eine Tastatur einzugeben und auf einem Bildschirm anzuzeigen.
quelle
Es ist schwer, sich über den allerersten Assembler im Klaren zu sein (es ist schwer zu definieren, was das war). Als ich vor Jahren einige Assembler für Computer schrieb, auf denen Assembler fehlten, schrieb ich den Code immer noch in Assemblersprache. Nachdem ich einen Abschnitt des Codes einigermaßen vollständig hatte, übersetzte ich ihn von Hand in Maschinencode. Dies waren jedoch immer noch zwei völlig getrennte Phasen - als ich den Code schrieb, arbeitete oder dachte ich überhaupt nicht auf Maschinencode-Ebene.
Ich sollte hinzufügen, dass ich in einigen Fällen noch einen Schritt weiter gegangen bin: Ich habe den größten Teil des Codes in einer Assemblersprache geschrieben, die ich für einfacher gehalten habe, und dann einen winzigen Kernel geschrieben (mehr oder weniger das, was wir jetzt als virtuelle Maschine bezeichnen würden). das auf dem Zielprozessor zu interpretieren. Das war tödlich langsam (besonders auf einem 1-MHz-8-Bit-Prozessor), aber das machte nicht viel aus, da es normalerweise nur einmal (oder höchstens ein paar Mal) lief.
quelle
Sie brauchen keinen Assembler, der Assemblersprachencode in Maschinencode umwandelt. Genauso wie Sie keinen Editor benötigen, um Assembler-Code zu schreiben.
Eine historische Perspektive
Die ersten Assembler wurden wahrscheinlich in Assemblersprache geschrieben und dann von Hand zu Maschinencode zusammengesetzt. Selbst wenn der Prozessor keine offizielle "Assemblersprache" hatte, haben die Programmierer wahrscheinlich den größten Teil der Programmierarbeit mit einer Art Pseudocode ausgeführt, bevor sie diesen Code in Maschinenanweisungen übersetzten.
Schon in den frühesten Tagen des Rechnens haben Programmierer Programme in einer Art symbolischer Notation geschrieben und sie in Maschinencode übersetzt, bevor sie in ihren Computer eingespeist wurden. In Augusta Ada Kings Fall hätte sie benötigt , um sie in den übersetzten Lochkarten für Babbage ‚s Analytical Engine , aber leider wurde nie gebaut.
Persönliche Erfahrung
Der erste Computer, den ich besaß, war ein Sinclair ZX81 (Timex 1000 in den USA). Die Rückseite des Handbuchs enthielt alle Informationen, die Sie zur Übersetzung der Assemblersprache Z80 in Maschinencode benötigten (einschließlich aller seltsamen Indexmodus- Opcodes, die der Z80 hatte).
Ich würde ein Programm (auf Papier) in Assemblersprache schreiben und den Code trocken durcharbeiten. Wenn ich froh war, dass mein Programm fehlerfrei war, schlug ich jede Anweisung am Ende des Handbuchs nach, übersetzte sie in Maschinencode und schrieb den Maschinencode ebenfalls auf das Papier. Schließlich würde ich alle Maschinencode-Anweisungen in mein ZX81 eingeben, bevor ich es auf Band speichere und versuche, es auszuführen.
Wenn es nicht funktionierte, überprüfte ich meine Hand-Assembly noch einmal und wenn eine Übersetzung falsch war, korrigierte ich die von Band geladenen Bytes, bevor ich sie erneut speicherte und versuchte, das Programm erneut auszuführen.
Aus Erfahrung kann ich Ihnen sagen, dass es viel einfacher ist, Ihren Code zu debuggen, wenn er in Assemblersprache als in Maschinencode geschrieben ist - daher die Beliebtheit von Disassemblern. Selbst wenn Sie keinen Assembler haben, ist die manuelle Assemblierung weniger fehleranfällig als der Versuch, Maschinencode direkt zu schreiben, obwohl ein echter Programmierer wie Mel möglicherweise anderer Meinung ist. * 8 ')
quelle
Damals und heute gibt es keinen Unterschied. Wenn Sie eine neue Programmiersprache erfinden möchten, wählen Sie eine der Sprachen aus, die Ihnen heute zur Verfügung stehen, um den ersten Compiler zu erstellen. Wenn es ein Ziel des Projekts ist, erstellen Sie über einen gewissen Zeitraum einen Compiler in dieser Sprache, der sich dann selbst hosten kann.
Wenn Sie lediglich Bleistift und Papier und einige Schalter oder Lochkarten als Benutzeroberfläche für den ersten oder nächsten neuen Befehlssatz verwendet haben, haben Sie einen oder alle verfügbaren Elemente verwendet. Sie hätten durchaus eine Assemblersprache auf Papier schreiben und dann einen Assembler verwenden können, um sie in Maschinencode zu konvertieren, vielleicht in Oktalform, und dann irgendwann in die Schnittstelle zur Maschine.
Wenn heute ein brandneuer Befehlssatz erfunden wird, der nicht anders ist, je nach Unternehmen / Personen, Praktiken usw. Es ist sehr wahrscheinlich, dass der Hardwaretechniker, der wahrscheinlich in Verilog oder VHDL programmiert, die ersten Testprogramme von Hand in Maschinencode schreibt (wahrscheinlich in hex oder binär). Je nach Fortschritt des Softwareteams können sie sehr schnell oder nicht sehr lange auf Assembler und dann auf Compiler umstellen.
Die ersten Computer waren keine Universalcomputer, auf denen Sie Assembler und Compiler erstellen konnten. Sie haben sie programmiert, indem Sie einige Drähte zwischen dem Ausgang des vorherigen Alus und dem Eingang des nächsten Alus verschoben haben. Schließlich hatten Sie einen Allzweckprozessor, mit dem Sie einen Assembler in der Baugruppe schreiben, von Hand zusammenbauen, als Maschinencode eingeben, das dann zum Parsen von ebcdic, ascii usw. und zum Selbsthosten verwenden konnten. Bewahren Sie die Binärdatei auf einem Medium auf, das Sie später lesen / laden können, ohne ständig die Schalter umlegen zu müssen, um den Maschinencode von Hand einzugeben.
Denken Sie an Lochkarten und Lochstreifen. Anstatt Schalter umzudrehen, könnten Sie definitiv eine komplett mechanische Maschine herstellen, ein arbeitssparendes Gerät, das die Medien erstellt, die der Computer lesen würde. Anstatt die Maschinencode-Bits mit Schaltern wie bei einem Altair eingeben zu müssen, könnten Sie stattdessen Papierstreifen oder Lochkarten zuführen (mit etwas Mechanischem, nicht prozessorgesteuertem, das den Speicher oder Prozessor speist, ODER mit einem kleinen, mit Maschinencode geschriebenen Bootloader). Dies war keine schlechte Idee, da Sie etwas herstellen konnten, das von dem Computer angetrieben wurde, der auch die Papierbänder oder Lochkarten mechanisch produzieren und diese dann wieder einspeisen konnte. Zwei Quellen für Lochkarten, das nicht computergestützte mechanische Arbeitsersparnisgerät und die computergesteuerte Maschine. beide erzeugen die "Binaries" für den Computer.
quelle
Es gibt ein oder zwei Fälle in Brooks Computerzoo, in denen er sagte, dass "die Mnemonics unsere Erfindung sind, der Designer einfach numerischen Opcode oder das Zeichen, dessen Code der Opcode war", also dort, wo Maschinen, für die es nicht einmal einen gab Assemblersprache.
Bei der Eingabe von Programmen wird das Debugging über das Bedienfeld beendet (für diejenigen, die dies nicht getan haben, war dies eine Möglichkeit, den Speicher einzurichten. Sie haben einige Schalter auf die Adresse und andere auf den Wert eingestellt und eine Taste oder eine andere Taste auf gedrückt Lesen Sie den Wert) war weit später üblich. Einige Oldtimer geben an, dass sie den Startcode für Maschinen, die sie häufig verwendeten, immer noch eingeben können.
Die Schwierigkeit, Maschinencode direkt zu schreiben und Programme aus dem Speicherauszug zu lesen, hängt stark von der Maschinensprache ab. Einige von ihnen sind relativ einfach (der schwierigste Teil ist das Verfolgen der Adressen), x86 ist einer der schlechteren.
quelle
Ich habe 1975 einen Computer gebaut. Er war im Vergleich zu seinem Zeitgenossen Altair sehr fortschrittlich, da er ein 'Monitor-ROM' besaß, mit dem ich Programme eingeben konnte, indem ich den Maschinencode in hexadezimaler Schrift eintippte und diesen Code auf einem Videomonitor anzeigte, wo wie beim Altair musste jeder Maschinenbefehl mit einer Reihe von Schaltern etwas zu einem Zeitpunkt eingegeben werden.
Also ja, in den frühen Tagen von Computern und dann wieder in den frühen Tagen von Personal Computern haben die Leute Anwendungen in Maschinencode geschrieben.
quelle
Eine Anekdote:
Als ich Assembler lernte, befand sich auf dem Apple ein Programm namens Micro-Assembler im ROM. Die Montageanweisung wurde sofort in Bytes übersetzt, sobald Sie sie eingegeben haben. Das heißt, es gab keine Etiketten - wenn Sie springen oder laden wollten, mussten Sie die Offsets selbst berechnen. Es war jedoch viel einfacher, als die Anweisungslayouts nachzuschlagen und Hex-Werte einzugeben.
Ohne Zweifel wurden echte Assembler zuerst mit dem Micro-Assembler oder einer anderen nicht ganz vollständigen Umgebung geschrieben.
quelle