Ich möchte ein paar Fragen zur Assemblersprache stellen. Ich verstehe, dass es der Maschinensprache sehr nahe kommt und sie schneller und effizienter macht.
Bedeutet das, dass wir unterschiedliche Computerarchitekturen haben, dass ich in Assembly für unterschiedliche Architekturen unterschiedlichen Code schreiben muss? Wenn ja, warum nicht Assembly, schreiben Sie einmal - lassen Sie jede Art von Sprache laufen? Wäre es nicht einfacher, es einfach universell zu machen, sodass Sie es nur einmal schreiben und auf praktisch jedem Computer mit unterschiedlichen Konfigurationen ausführen können? (Ich denke, dass es unmöglich wäre, aber ich hätte gerne konkrete, detaillierte Antworten.)
Manche Leute sagen vielleicht, C ist die Sprache, nach der ich suche. Ich habe C noch nie benutzt, aber ich denke, es ist immer noch eine Hochsprache, obwohl es wahrscheinlich schneller als Java ist. Ich könnte mich hier irren.
Antworten:
Assembler - Sprache ist eine Möglichkeit , um Schreibbefehle für den Computer - Befehlssatz , in einer Weise , die für die menschliche Programmierer leicht verständlicher ist.
Unterschiedliche Architekturen haben unterschiedliche Befehlssätze: Die zulässigen Befehlssätze sind für jede Architektur unterschiedlich. Aus diesem Grund können Sie nicht hoffen, dass Sie ein "Write-Once-Run-Anywhere" -Montageprogramm haben. Beispielsweise unterscheidet sich der Befehlssatz, der von x86-Prozessoren unterstützt wird, erheblich von dem Befehlssatz, der von ARM-Prozessoren unterstützt wird. Wenn Sie ein Assembly-Programm für einen x86-Prozessor geschrieben haben, enthält es viele Anweisungen, die vom ARM-Prozessor nicht unterstützt werden, und umgekehrt.
Der Hauptgrund für die Verwendung der Assemblersprache besteht darin, dass sie die Steuerung Ihres Programms auf sehr niedriger Ebene ermöglicht und alle Anweisungen des Prozessors ausnutzt: Passen Sie das Programm an, um Funktionen zu nutzen, die für den jeweiligen Prozessor einzigartig sind läuft weiter, manchmal kann man das Programm beschleunigen. Die Write-Once-Run-Anywhere-Philosophie widerspricht dem grundsätzlich.
quelle
Die DEFINITION der Assemblersprache ist, dass es sich um eine Sprache handelt, die direkt in Maschinencode übersetzt werden kann. Jeder Operationscode in Assemblersprache wird in genau eine Operation auf dem Zielcomputer übersetzt. (Nun, es ist etwas komplizierter: Einige Assembler bestimmen automatisch einen "Adressierungsmodus" basierend auf Argumenten für einen Op-Code. Das Prinzip ist jedoch, dass eine Assemblierungszeile in eine maschinensprachliche Anweisung übersetzt wird.)
Sie könnten zweifellos eine Sprache erfinden, die wie Assemblersprache aussieht, aber auf verschiedenen Computern in verschiedene Maschinencodes übersetzt wird. Aber per Definition wäre das keine Assemblersprache. Es wäre eine höhere Sprache, die der Assemblersprache ähnelt.
Ihre Frage ähnelt der Frage: "Ist es möglich, ein Boot zu bauen, das nicht schwimmt oder auf andere Weise über Wasser fährt, aber Räder und einen Motor hat und an Land fahren kann?" Die Antwort wäre, dass ein solches Fahrzeug per Definition kein Boot wäre. Es klingt eher wie ein Auto.
quelle
Es gibt keinen begrifflichen (I daresay, keine Computerwissenschaft ) Grund gegen eine Assemblersprache mit für alle Computer in der Welt. In der Tat würde das viele Dinge viel einfacher machen. Was die Theorie angeht, so sind sie alle gleich, bis auf ein bisschen Funky Bijection.
In der Praxis gibt es jedoch unterschiedliche Chips für unterschiedliche Zwecke mit unterschiedlichen Operationen und Konstruktionsprinzipien (z. B. RISC vs CISC), die unterschiedlichen Zielen dienen, und die Befehlssätze, die sie bedienen, und damit die Assemblersprachen unterscheiden sich. Letztendlich ist die Antwort dieselbe wie bei der Frage, warum es so viele verschiedene Programmiersprachen gibt : unterschiedliche Ziele, unterschiedliche Entwurfsentscheidungen.
Das heißt, Sie können natürlich Abstraktionsebenen einführen, um zu einer gemeinsamen Schnittstelle zu gelangen. x86 zum Beispiel wird seit geraumer Zeit auf Chip-Ebene abgeschafft. Es gibt ein kleines Stück Hardware, das x86-Anweisungen in das übersetzt, womit Ihr Prozessor wirklich arbeitet. Sprachen wie C wären ein weiterer Schritt von der Hardware entfernt (wenn auch nur ein winziger), bis hin zu Sprachen wie Haskell, Java oder Ruby. Ja, Compiler sind eine der wichtigsten Errungenschaften der Informatik, da sie es ermöglichen, Bedenken auf diese Weise zu trennen.
quelle
Sie erwähnen den Satz "einmal schreiben, irgendwo laufen", ohne seine Bedeutung zu bemerken. Das ist der Marketing - Slogan für Sun Microsystem , die im Handel das Konzept einer erfundenen „virtuellen Maschine“ und „Bytecode“ für Java, obwohl möglicherweise hat die Idee , in der Wissenschaft 1 entstanden sein st. Die Idee wurde später von Microsoft für .NET kopiert, nachdem Sun sie erfolgreich wegen Verstoßes gegen die Java-Lizenzierung verklagt hatte. Java-Bytecodes sind eine Implementierung der Idee einer maschinenübergreifenden Assemblierung oder Maschinensprache. Sie werden für mehrere andere Sprachen als Java verwendet und können theoretisch zum Kompilieren einer beliebigen Sprache verwendet werden. Nach vielen Jahren fortschrittlicher Optimierung kommt Java den kompilierten Sprachen sehr nahe und zeigt, dass das Ziel einer leistungsfähigen plattformunabhängigen virtuellen Maschinentechnologie im Allgemeinen erreichbar ist.
Eine weitere neue Idee, die in einem frühen Stadium Ihren Anforderungen entspricht, heißt Recomputation Project und dient der wissenschaftlichen Forschung, könnte aber auch für andere Zwecke verwendet werden. Die Idee ist, Computerexperimente über die Technologie virtueller Maschinen replizierbar zu machen. Dies ist hauptsächlich die Idee, verschiedene Maschinenarchitekturen auf beliebiger Hardware zu simulieren.
quelle
Gründe auf hohem Niveau
Wenn Sie darüber nachdenken, macht ein Mikroprozessor eine erstaunliche Sache: Mit ihm können Sie eine Maschine (wie eine Waschmaschine oder einen Aufzug) nehmen und einen ganzen Block von kundenspezifischen Mechanismen oder Schaltkreisen durch billiges, in Massenproduktion hergestelltes Silizium ersetzen Chip. Sie sparen viel Geld für Teile und viel Zeit für das Design.
Aber warten Sie, ein Standard- Chip, der unzählige Sonderanfertigungen ersetzt ? Es kann keinen einzigen perfekten Mikroprozessor geben, der für jede Anwendung perfekt ist. Einige Anwendungen müssen den Stromverbrauch minimieren, müssen jedoch nicht schnell sein. andere müssen schnell sein, müssen aber nicht einfach zu programmieren sein, andere müssen kostengünstig sein usw.
Wir haben also viele verschiedene "Geschmacksrichtungen" von Mikroprozessoren, jede mit ihren eigenen Stärken und Schwächen. Es ist wünschenswert, dass alle Benutzer einen kompatiblen Befehlssatz verwenden, da dies die Wiederverwendung von Code ermöglicht und es einfacher macht, Personen mit den richtigen Fähigkeiten zu finden. Der Befehlssatz wirkt sich jedoch auf die Kosten, die Komplexität, die Geschwindigkeit, die Benutzerfreundlichkeit und die physischen Einschränkungen des Prozessors aus. Daher haben wir einen Kompromiss: Es gibt einige "Mainstream" -Befehlssätze (und viele kleinere) und In jedem Befehlssatz gibt es viele Prozessoren mit unterschiedlichen Eigenschaften.
Oh, und wenn sich die Technologie ändert, ändern sich all diese Kompromisse, sodass sich Anweisungssätze entwickeln, neue entstehen und alte sterben. Selbst wenn es einen "besten" Befehlssatz von heute gäbe, könnte es nicht in 20 Jahren sein.
Hardware-Details
Die wahrscheinlich größte Entwurfsentscheidung in einem Befehlssatz ist die Wortgröße , dh wie groß eine Zahl ist, die der Prozessor "natürlich" manipulieren kann. 8-Bit-Prozessoren verarbeiten Zahlen von 0 bis 255, während 32-Bit-Prozessoren Zahlen von 0 bis 4.294.967.295 verarbeiten. Code, der für einen entwickelt wurde, muss für einen anderen komplett überarbeitet werden.
Es geht nicht nur darum, Anweisungen von einem Befehlssatz in einen anderen zu übersetzen. Ein völlig anderer Ansatz kann in einem anderen Befehlssatz vorzuziehen sein. Auf einem 8-Bit-Prozessor kann beispielsweise eine Nachschlagetabelle ideal sein, während auf einem 32-Bit-Prozessor eine arithmetische Operation für denselben Zweck besser wäre.
Es gibt andere Hauptunterschiede zwischen Befehlssätzen. Die meisten Anweisungen lassen sich in vier Kategorien einteilen:
Prozessoren unterscheiden sich darin, welche Art von Berechnungen sie ausführen können und wie sie sich dem Kontrollfluss, der Datenübertragung und der Prozessorkonfiguration nähern.
Beispielsweise können einige AVR-Prozessoren weder multiplizieren noch dividieren. Während alle x86-Prozessoren können. Wie Sie sich vielleicht vorstellen können, kann die Eliminierung der für Aufgaben wie Multiplikation und Division erforderlichen Schaltkreise einen Prozessor einfacher und billiger machen. Diese Vorgänge können weiterhin mithilfe von Softwareroutinen ausgeführt werden, wenn sie benötigt werden.
Mit x86 können arithmetische Anweisungen ihre Operanden aus dem Speicher laden und / oder ihre Ergebnisse im Speicher speichern. ARM ist eine Load-Store-Architektur und verfügt daher nur über wenige dedizierte Anweisungen für den Speicherzugriff. Mittlerweile verfügt x86 über dedizierte Anweisungen für bedingte Verzweigungen, während ARM die bedingte Ausführung praktisch aller Anweisungen ermöglicht . ARM ermöglicht auch das Durchführen von Bitverschiebungen als Teil der meisten arithmetischen Anweisungen. Diese Unterschiede führen zu unterschiedlichen Leistungsmerkmalen, Unterschieden im internen Design und den Kosten der Chips sowie Unterschieden in den Programmiertechniken auf Assemblersprachenebene.
Fazit
Der Grund, warum es unmöglich ist, eine universelle Assemblersprache zu haben, ist, dass man den Code neu entwerfen muss, um Assembler-Code von einem Befehlssatz in einen anderen zu konvertieren - etwas, das Computer noch nicht können.
quelle
Hinzu kommt die wunderbare Antwort von DW: Wenn Sie einen Assembler haben möchten, müssen Sie alle Architekturen beibehalten, einen perfekten Übersetzer unter sich haben und vollständig verstehen, was Sie tun.
Einige stark optimierte Codes für eine Architektur müssten deoptimiert, auf einer abstrakteren Ebene verstanden und für eine andere optimiert werden.
Wenn dies jedoch möglich wäre, hätten wir einen perfekten C-Compiler, und das Schreiben in reiner Assembly wäre überhaupt nicht vorteilhaft.
Der wichtigste Punkt bei der Verwendung von Assembler ist die Leistung, die von den neuesten Compilern nicht beeinträchtigt werden kann.
Das Schreiben eines solchen Programms wäre noch schwieriger als bei vorhandenen Compilern, und das Beibehalten aller neuen Architekturen, die erstellt werden, würde es noch schwieriger machen.
Und für "one only" -Programme würde dies auch vollständige Abwärtskompatibilität bedeuten.
quelle
Microsoft hat MSIL als Intermediate Assembler-Sprache erfunden . Programme würden von C # oder VB.Net nach MSIL kompiliert. Zur Laufzeit wurde die MSIL mit einem JIT- Compiler zu Maschinencode für die Maschine kompiliert, auf der sie ausgeführt wurde . Die Datei mit der MSIL war eine .EXE-Datei mit einigen Anweisungen zum Starten des Programms in X86. Auf einem ARM-Prozessor geben Sie das Wort mono vor dem Programmnamen ein, um es auszuführen.
quelle
Wie bereits erwähnt, ist LLVM dem bisher am nächsten. Ein großes Hindernis für eine wirklich universelle Sprache sind grundlegende Unterschiede in Bezug auf implizite Kompromisse: Parallelität, Speichernutzung, Durchsatz, Latenz und Stromverbrauch. Wenn Sie explizit im SIMD-Stil schreiben, wird möglicherweise zu viel Speicher verwendet. Wenn Sie explizit im SISD-Stil schreiben, erhalten Sie eine suboptimale Parallelisierung. Wenn Sie den Durchsatz optimieren, wird die Latenz beeinträchtigt. Wenn Sie den Single-Threaded-Durchsatz (dh die Taktrate) maximieren, wird die Akkulaufzeit beeinträchtigt.
Zumindest müsste der Code mit den Kompromissen versehen werden. Was am wichtigsten sein kann, ist, dass die Sprache gute algebraische / Typeneigenschaften hat, die dem Compiler viel Spielraum zum Optimieren und Erkennen logischer Inkonsistenzen geben.
Dann ist da die Frage nach undefiniertem Verhalten. Ein Großteil der Geschwindigkeit von C und Assemblersprachen beruht auf undefiniertem Verhalten. Wenn Sie undefiniertes Verhalten eingestehen, das tatsächlich vorkommt, werden Sie letztendlich als Sonderfälle behandelt (dh: architektur- und kontextspezifische Hacks).
quelle
Vielleicht suchen Sie eine Universal Turning Machine-Notation, in der sich alle auf die Symbole für die Befehle einigen. ( https://en.wikipedia.org/wiki/Universal_Turing_machine )
Ein Assembler, der eine Turning Acceptable-Sprache in den zugrunde liegenden herstellerspezifischen Maschinencode übersetzt und für all diese Dinge erstellt, die wir Computer nennen.
In der Kunst der Computerprogrammierung gibt es ein Beispiel dafür, wie dies aussehen könnte.
Aber stellen Sie sich die Frage "Warum ist ihre Sprache nicht eine im Handel erhältliche universelle Sprache, die mit allen Computern verwendet werden kann?" (2) Wirtschaftlichkeit, Bereitstellung von Inkompatibilität zwischen Maschinen verschiedener Marken und Anbietern ist eine Geschäftsstrategie sowie das Ergebnis begrenzter Ressourcen (Zeit / Geld) zum Entwerfen von Maschinen.
quelle
Annahme: Kompilieren und Optimieren einer Hochsprache L1 zu einer Niedrigsprache L0 ist einfacher als Kompilieren und Optimieren einer Hochsprache L2 (höher als L1) zu L0; einfacher in dem Sinne, dass Sie beim Kompilieren von L1 nach L0 angeblich optimierten Code generieren können als von L2 nach L0.
Ich denke, die Annahme ist wahrscheinlich richtig, deshalb verwenden wahrscheinlich die meisten Compiler eine einfache Zwischensprache (IR / LLVM).
Wenn dies zutrifft, verwenden Sie eine Low-Level-Sprache L0 und schreiben Sie Compiler, um L0 in andere Low-Level-Sprachen zu übersetzen. Verwenden Sie beispielsweise den MIPS-Befehlssatz und kompilieren Sie ihn zu x86, arm, power, ...
-Taoufik
quelle