Wir werden oft darauf hingewiesen, dass es der Hardware egal ist, in welcher Sprache ein Programm geschrieben ist, da nur der kompilierte Binärcode angezeigt wird. Dies ist jedoch nicht die ganze Wahrheit. Betrachten Sie zum Beispiel den bescheidenen Z80; Zu den Erweiterungen des 8080-Befehlssatzes gehören Befehle wie CPIR, die zum Scannen von C-Zeichenfolgen (mit NULL-Abschluss) nützlich sind, z strlen()
. B. zum Ausführen . Die Designer müssen festgestellt haben, dass das Ausführen von C-Programmen (im Gegensatz zu Pascal, bei dem die Länge einer Zeichenfolge im Header enthalten ist) etwas war, wofür ihr Design wahrscheinlich verwendet wurde. Ein weiteres klassisches Beispiel ist die Lisp-Maschine .
Welche anderen Beispiele gibt es? ZB Befehle, Anzahl und Art der Register , Adressierungsmodi, die einen bestimmten Prozessor dazu bringen, die Konventionen einer bestimmten Sprache zu bevorzugen? Ich interessiere mich besonders für Revisionen derselben Familie.
sizeof(int)
1 muss der Typchar
signiert sein (daint
alle Werte des Typs enthalten sein müssenchar
). Ich habe für eine Maschine geschriebenen Code , wochar
undint
sind beide 16-Bit - Integer mit Vorzeichen; Die größten Schwierigkeiten bestehen darin, dass man keine Gewerkschaften für die Typkonvertierung verwenden kann und eine effiziente Speicherung einer großen Anzahl von Bytes manuelles Packen und Entpacken erfordert. Diese Probleme sind geringfügig im Vergleich zu der Möglichkeit in C, dass sizeof (int) == sizeof (long), da ...unsigned int
Werten hält. C99 verbesserte diese Situation, aber vor C99 gab es keine Möglichkeit, einen potenziell negativen Wert in einem einzigen Schritt mit einem Wert vom Typ zu vergleichenunsigned int
(man müsste testen, ob die Zahl negativ war, bevor der Vergleich durchgeführt wird).Antworten:
Die vorhandenen Antworten konzentrieren sich auf ISA- Änderungen. Es gibt auch andere Hardware-Änderungen. Beispielsweise verwendet C ++ üblicherweise vtables für virtuelle Aufrufe. Ab dem Pentium M verfügt Intel über eine "indirekte Verzweigungsvorhersage" -Komponente, die virtuelle Funktionsaufrufe beschleunigt.
quelle
Der Intel 8086-Befehlssatz enthält eine Variation von "ret", die dem Stapelzeiger einen Wert hinzufügt, nachdem die Rücksprungadresse abgesetzt wurde. Dies ist für viele Pascal-Implementierungen nützlich, bei denen der Aufrufer einer Funktion Argumente vor dem Aufrufen einer Funktion auf den Stapel schiebt und sie anschließend abruft. Wenn eine Routine beispielsweise Parameter im Wert von vier Bytes akzeptiert, könnte sie mit "RET 0004" enden, um den Stapel zu bereinigen. Ohne einen solchen Befehl hätte eine solche Aufrufkonvention wahrscheinlich erforderlich gemacht, dass der Code die Rücksprungadresse in ein Register eingibt, den Stapelzeiger aktualisiert und dann zu diesem Register springt.
Interessanterweise verwendete der größte Teil des Codes (einschließlich der OS-Routinen) auf dem ursprünglichen Macintosh die Pascal-Aufrufkonvention, obwohl es im 68000 keine Anweisungen zur Erleichterung gab. Die Verwendung dieser Aufrufkonvention sparte 2-4 Byte Code an einem typischen Aufrufstandort, erforderte jedoch zusätzliche 4-6 Byte Code an der Rückgabeseite jeder Funktion, die Parameter verwendet hat.
quelle
ENTER
Gegenstück dazuRET n
...ENTER
es im Original 8086 existiert hat; es kam mit späteren Prozessoren. Es bringt jedoch einen interessanten Punkt auf den Punkt: Die BP-basierten Adressierungsmodi sind klar auf die Verwendung von gestapelten Parametern und Lokalen ausgelegt, auf die über den Rahmenzeiger zugegriffen wird. Ich finde diese Konvention in vielerlei Hinsicht interessant, insbesondere angesichts der Tatsache, dass (1) reiner Assemblersprachencode eher Werte in Registern als im Stapel verwendet, aber (2) die Vorteile der [BP + nn] -Adressierung gegenüber [SP +] nn] Adressierung ist für Assembler-Programme, die auf den Stack zugreifen,Ein Beispiel hierfür ist MIPS, die beide aufweist
add
undaddu
zum Auffangen und Überlauf zu ignorieren ist. (Auchsub
undsubu
.) Es brauchte die erste Art von Anweisungen für Sprachen wie Ada (ich glaube - ich habe Ada allerdings noch nie benutzt), die sich explizit mit Überläufen befassen, und die zweite Art für Sprachen wie C, die Überläufe ignorieren.Wenn ich mich richtig erinnere, hat die eigentliche CPU einige zusätzliche Schaltkreise in der ALU, um Überläufe zu verfolgen. Wenn die einzige Sprache, um die sich die Leute kümmerten, C wäre, würde es das nicht brauchen.
quelle
nmemb*size+offset
Bytes zuweisen und sicherstellen müssen, dass kein Überlauf auftritt.addu
undsubu
(diejenigen, die nicht auf Überläufe prüfen) diejenigen sind, die hinzugefügt wurden, um C glücklich zu machen. Natürlich weiß ich es nicht genau - wir haben es nur vage in der Vorlesung behandelt und ich bin mit Sicherheit kein Experte für Architektur: P.Die Burroughs 5000-Serie wurde entwickelt, um ALGOL effizient zu unterstützen, und Intels iAPX-432 wurde entwickelt, um Ada effizient auszuführen. Der Inmos Transputer hatte eine eigene Sprache, Occam. Ich denke, der Parallax "Propeller" -Prozessor wurde so entworfen, dass er mit einer eigenen BASIC-Variante programmiert werden kann.
Es ist keine Sprache, aber der VAX-11-Befehlssatz enthält einen einzelnen Befehl zum Laden eines Prozesskontexts, der auf Anfrage des VMS-Designteams erstellt wurde. Ich erinnere mich nicht an die Details, aber ISTR brauchte so viele Anweisungen, um es zu implementieren, dass die Anzahl der Prozesse, die geplant werden konnten, ernsthaft begrenzt wurde.
quelle
Bisher scheint noch niemand etwas erwähnt zu haben: Fortschritte bei der Compileroptimierung (bei der die Basissprache weitgehend irrelevant ist) haben die Verschiebung von CISC-Befehlssätzen (die größtenteils für den menschlichen Gebrauch konzipiert wurden) zu RISC-Befehlssätzen (die größtenteils von Menschen erstellt wurden) ausgelöst entworfen, um von Compilern codiert zu werden.)
quelle
Die Motorola 68000-Familie hat einen automatischen Adressierungsmodus eingeführt , der das Kopieren von Daten über die CPU sehr effizient und kompakt macht.
[Aktualisiertes Beispiel]
Dies war ein C ++ - Code, der 68000 Assembler beeinflusste
implementiert in herkömmlichen Assembler (Pseudocode, ich habe die 68000 Assembler-Befehle vergessen)
mit dem neuen adressmodus wurde es zu etwas ähnlichem
nur zwei Anweisungen pro Schleife anstelle von 4.
quelle
Der IBM Mainframe der Z-Serie ist der Nachfolger des IBM 360 aus den 1960er-Jahren.
Es gab mehrere Anweisungen, die speziell für die Beschleunigung von COBOL- und Fortran-Programmen erstellt wurden. Das klassische Beispiel ist
BXLE
- "Branch on Index Low oder Equal", bei dem es sich zumeist um eine Fortran-for
Schleife oder ein COBOL handelt,PERFORM VARYING x from 1 by 1 until x > n
das in einem einzelnen Befehl verkapselt ist.Es gibt auch eine ganze Familie gepackter Dezimalbefehle zur Unterstützung von Festkomma-Dezimalarithmetik, wie sie in COBOL-Programmen üblich sind.
quelle
DO
Schleife erinnernd .Frühe Intel-CPUs hatten die folgenden Funktionen, von denen viele im 64-Bit-Modus veraltet waren:
Das Vorzeichen-Flag, das sich im Statusregister vieler CPUs befindet, dient zur einfachen Ausführung von Arithmetik mit und ohne Vorzeichen.
Der SSE 4.1-Befehlssatz enthält Anweisungen für die Zeichenfolgenverarbeitung, sowohl gezählt als auch nullterminiert (PCMPESTR usw.).
Ich könnte mir auch vorstellen, dass eine Reihe von Funktionen auf Systemebene entwickelt wurden, um die Sicherheit von kompiliertem Code zu unterstützen (Segmentlimitprüfung, Call-Gates beim Kopieren von Parametern usw.).
quelle
Einige ARM-Prozessoren, hauptsächlich solche in Mobilgeräten, umfassen (d) Jazelle-Erweiterung, bei der es sich um einen Hardware-JVM-Interpreter handelt; es interpretiert Java-Bytecode direkt. Jazelle-fähige JVM können die Hardware verwenden, um die Ausführung zu beschleunigen und einen Großteil von JIT zu eliminieren. Ein Rückgriff auf Software-VM ist jedoch weiterhin gewährleistet, wenn der Bytecode nicht auf dem Chip interpretiert werden kann.
Prozessoren mit einer solchen Einheit enthalten einen BXJ-Befehl, der den Prozessor in einen speziellen "Jazelle-Modus" versetzt, oder wenn die Aktivierung der Einheit fehlgeschlagen ist, wird sie nur als normaler Verzweigungsbefehl interpretiert. Das Gerät verwendet ARM-Register erneut, um den JVM-Status zu halten.
Der Nachfolger der Jazelle-Technologie ist ThumbEE
quelle
Soweit ich weiß, war dies in der Vergangenheit üblicher.
Es gibt eine Reihe von Fragen, in denen James Gosling sagte, dass es Leute gab, die versuchten, Hardware zu entwickeln, die besser mit JVM - Bytecode umgehen kann, aber dann würden diese Leute einen Weg finden, dies mit allgemeinem Intel x86 zu tun (möglicherweise beim Kompilieren des Bytecode auf eine clevere Art und Weise).
Er erwähnte, dass die Verwendung des beliebten generischen Chips (wie Intel) von Vorteil ist, da ein großes Unternehmen riesige Summen auf das Produkt wirft.
Das Video ist einen Blick wert. Er spricht in Minute 19 oder 20 darüber.
quelle
Ich habe eine schnelle Seitensuche durchgeführt und es scheint, dass niemand CPU's erwähnt hat, die speziell für die Ausführung von Forth entwickelt wurden . Die Programmiersprache Forth ist stapelbasiert, kompakt und wird in Steuerungssystemen verwendet.
quelle
Die Intel iAPX- CPU wurde speziell für OO-Sprachen entwickelt. Hat aber nicht ganz geklappt.
quelle
Der 68000 verfügte über MOVEM, das am besten geeignet war, mehrere Register in einem einzigen Befehl auf den Stapel zu schieben, was viele Sprachen erwarteten.
Wenn Sie im gesamten Code MOVEM (MOVE Multiple) vor JSR (Jump SubRoutine) sahen, wussten Sie im Allgemeinen, dass es sich um C-konformen Code handelte.
MOVEM ermöglichte das automatische Inkrementieren des Zielregisters, sodass jede Verwendung das Stapeln des Ziels fortsetzen oder im Fall eines automatischen Dekrements aus dem Stapel entfernen konnte.
http://68k.hax.com/MOVEM
quelle
Die AVR-Architektur von Atmel wurde von Grund auf so konzipiert, dass sie für die Programmierung in C geeignet ist. In diesem Anwendungsbericht wird beispielsweise näher darauf eingegangen.
IMO ist dies eng mit rockets4kids'es ausgezeichneter Zusammenhang Antwort , mit dem frühen PIC16-s für die direkten Assembler - Programmierung (40 Befehle insgesamt) entwickelt, mit späteren Familien C. Targeting
quelle
Bei der Entwicklung des numerischen 8087-Coprozessors war es für Sprachen üblich, alle Gleitkomma-Berechnungen mit dem Typ mit der höchsten Genauigkeit durchzuführen und das Ergebnis nur auf eine niedrigere Genauigkeit abzurunden, wenn es einer Variablen mit niedrigerer Genauigkeit zugewiesen wurde. In der ursprünglichen C-Norm ist zum Beispiel die Reihenfolge:
würde fördern
a
undb
zudouble
, sie hinzufügen, fördernc
zudouble
, es hinzufügen und dann das Ergebnis speichern, auf das gerundet wirdfloat
. Obwohl es in vielen Fällen für einen Compiler schneller gewesen wäre, Code zu generieren, der Operationen direkt auf dem Typ ausführtfloat
, war es einfacher, eine Reihe von Gleitkommaroutinen zu haben, die nur auf dem Typ funktionieren würdendouble
, zusammen mit Routinen zum Konvertieren in / vonfloat
, als separate Sätze von Routinen zu haben, um Operationen auffloat
und zu handhabendouble
. Der 8087 wurde um diesen Ansatz für die Arithmetik entwickelt und führt alle arithmetischen Operationen mit einem 80-Bit-Gleitkomma-Typ aus. [80 Bits wurden wahrscheinlich gewählt, weil:Auf vielen 16- und 32-Bit-Prozessoren ist es schneller, mit einer 64-Bit-Mantisse und einem separaten Exponenten zu arbeiten, als mit einem Wert, der ein Byte zwischen Mantisse und Exponenten teilt.
Es ist sehr schwierig, Berechnungen durchzuführen, die auf die volle Genauigkeit der verwendeten numerischen Typen genau sind. Wenn man zum Beispiel versucht, etwas wie log10 (x) zu berechnen, ist es einfacher und schneller, ein Ergebnis zu berechnen, das bis auf 100 μs eines 80-Bit-Typs genau ist, als ein Ergebnis, das bis auf 1 μs eines 64-Bit-Typs genau ist Wenn Sie das erstere Ergebnis auf 64-Bit-Genauigkeit runden, erhalten Sie einen 64-Bit-Wert, der genauer ist als der letztere.
Leider haben zukünftige Versionen der Sprache die Semantik der Funktionsweise von Gleitkommatypen geändert. Während die 8087-Semantik sehr schön gewesen wäre, wenn Sprachen sie konsistent unterstützt hätten, wenn die Funktionen f1 (), f2 () usw. den Typ zurückgegeben hätten
float
, würden viele Compiler-Autoren es auf sich nehmen,long double
einen Alias für den 64-Bit-Doppeltyp zu erstellen anstelle des 80-Bit-Typs des Compilers (und bieten keine andere Möglichkeit zum Erstellen von 80-Bit-Variablen) und zum willkürlichen Auswerten von:auf eine der folgenden Arten:
Beachten Sie, dass, wenn f3 und f4 dieselben Werte wie f1 bzw. f2 zurückgeben, der ursprüngliche Ausdruck eindeutig Null zurückgeben sollte, viele der letzteren Ausdrücke jedoch möglicherweise nicht. Dies führte dazu, dass die Leute die "zusätzliche Präzision" des 8087 verurteilten, obwohl die letzte Formulierung im Allgemeinen der dritten überlegen war und - mit Code, der den erweiterten Doppeltyp angemessen verwendete - selten minderwertig war.
In den vergangenen Jahren hat Intel auf den (unglücklichen) Trend der Sprache reagiert, Zwischenergebnisse auf die Genauigkeit der Operanden abzurunden, indem die späteren Prozessoren so entworfen wurden, dass sie dieses Verhalten begünstigen, was sich nachteilig auf den Code auswirkt, der von der Verwendung höherer Werte profitiert Präzision bei Zwischenberechnungen.
quelle
## How the stack changed the processor
und## How floating point changed the processor
), damit die Benutzer beim Lesen die richtige Einstellung erhalten und weniger wahrscheinlich glauben, dass Sie bei der Beantwortung oder Neuveröffentlichung der Fragen abwesend waren gleiche (r ähnliche) Antworten.