Warum programmieren Sie in der Montage? [geschlossen]


85

Ich habe eine Frage an alle Hardcore-Low-Level-Hacker da draußen. Ich bin auf diesen Satz in einem Blog gestoßen. Ich denke nicht wirklich, dass die Quelle wichtig ist (es ist Haack, wenn es dich wirklich interessiert), weil es eine verbreitete Aussage zu sein scheint.

Beispielsweise ist bei vielen modernen 3D-Spielen die Hochleistungs-Core-Engine in C ++ und Assembly geschrieben.

Was die Assembly angeht - ist der in Assembly geschriebene Code, weil Sie nicht möchten, dass ein Compiler zusätzliche Anweisungen ausgibt oder übermäßige Bytes verwendet, oder wenn Sie bessere Algorithmen verwenden, die Sie nicht in C ausdrücken können (oder ohne die Sie nicht ausdrücken können) der Compiler muss sie durcheinander bringen)?

Ich verstehe vollkommen, dass es wichtig ist, das Low-Level-Zeug zu verstehen. Ich möchte nur das Warum- Programm in der Assembly verstehen, nachdem Sie es verstanden haben.


1
Ähnliche Fragen gibt es schon, denke ich ...
Mehrdad Afshari

8
Eeeeehh .. technisch ist das eine andere Frage. Diese Fragen sind beide, warum Montage lernen, deshalb Programm darin programmieren, was .. ich denke ist anders ....?
CGP

3
Warum programmieren Sie in der Montage? - Schauen wir uns einige UNMÖGLICHE Antworten auf diese Fragen an: 1) Um meinen Code wartbar zu machen, 2) flexibel, 3) um Portabilität zu erreichen, 4) Testbarkeit, 5) Lesbarkeit, ...;)
ivan_ivanovich_ivanoff

8
Arbeitsplatzsicherheit ........
San Jacinto

2
weil es Spaß macht .. :)
RainingComputers

Antworten:


168

Ich denke, Sie verstehen diese Aussage falsch:

Beispielsweise ist bei vielen modernen 3D-Spielen die Hochleistungs-Core-Engine in C ++ und Assembly geschrieben.

Spiele (und die meisten Programme heutzutage) sind nicht "in Assembly geschrieben", wie sie "in C ++ geschrieben" sind. In diesem Blog heißt es nicht, dass ein erheblicher Teil des Spiels in Assembler entworfen wurde oder dass ein Team von Programmierern herumsteht und sich in Assembler als ihre Hauptsprache entwickelt.

Was dies wirklich bedeutet, ist, dass Entwickler das Spiel zuerst schreiben und es in C ++ zum Laufen bringen. Dann profilieren sie es, finden heraus, was die Engpässe sind, und wenn es sich lohnt, optimieren sie das Problem bei der Montage. Oder wenn sie bereits Erfahrung haben, wissen sie, welche Teile Engpässe sein werden, und sie haben optimierte Teile aus anderen Spielen, die sie gebaut haben.

Der Punkt der Programmierung in ist die Montage so , wie es immer war: Geschwindigkeit . Es wäre lächerlich, viel Code in Assembler zu schreiben , aber es gibt einige Optimierungen, die dem Compiler nicht bekannt sind, und für ein ausreichend kleines Codefenster wird ein Mensch es besser machen.

Zum Beispiel sind Compiler für Gleitkommazahlen eher konservativ und kennen möglicherweise einige der erweiterten Funktionen Ihrer Architektur nicht. Wenn Sie bereit sind, Fehler zu akzeptieren, können Sie dies normalerweise besser als der Compiler tun, und es lohnt sich, ein wenig Code in Assembly zu schreiben, wenn Sie feststellen, dass viel Zeit dafür aufgewendet wird.

Hier sind einige relevantere Beispiele:

Beispiele aus Spielen

  • Artikel von Intel über die Optimierung einer Game Engine mithilfe von SSE Intrinsics. Der endgültige Code verwendet Intrinsics (kein Inline-Assembler), daher ist die Menge der reinen Assemblierung sehr gering. Sie sehen sich jedoch die Assembler-Ausgabe des Compilers an, um genau herauszufinden, was optimiert werden muss.

  • Quakes schnelle inverse Quadratwurzel . Auch hier enthält die Routine keinen Assembler, aber Sie müssen etwas über Architektur wissen, um diese Art der Optimierung durchführen zu können. Die Autoren wissen, welche Operationen schnell sind (multiplizieren, verschieben) und welche langsam sind (dividieren, sqrt). Sie haben also eine sehr knifflige Implementierung der Quadratwurzel entwickelt, die die langsamen Operationen vollständig vermeidet.

High Performance Computing

  • Außerhalb des Bereichs der Spiele optimieren Leute im wissenschaftlichen Rechnen häufig den Mist aus den Dingen, um sie dazu zu bringen, schnell auf der neuesten Hardware zu laufen. Stellen Sie sich das als Spiele vor, bei denen Sie die Physik nicht betrügen können.

    Ein gutes aktuelles Beispiel hierfür ist die Lattice Quantum Chromodynamics (Lattice QCD) . In diesem Artikel wird beschrieben, wie sich das Problem auf einen sehr kleinen Rechenkern beschränkt, der stark für PowerPC 440 auf einem IBM Blue Gene / L optimiert wurde . Jeder 440 verfügt über zwei FPUs und unterstützt einige spezielle ternäre Operationen, die für Compiler schwierig auszunutzen sind. Ohne diese Optimierungen wäre Lattice QCD viel langsamer gelaufen, was kostspielig ist, wenn Ihr Problem Millionen von CPU-Stunden auf teuren Computern erfordert.

    Wenn Sie sich fragen, warum dies wichtig ist, lesen Sie den Artikel in Science , der aus dieser Arbeit hervorgegangen ist. Mit Lattice QCD berechneten diese Leute die Masse eines Protons nach ersten Prinzipien und zeigten letztes Jahr, dass 90% der Masse aus starker Kraftbindungsenergie und der Rest aus Quarks stammen. Das ist E = mc 2 in Aktion. Hier ist eine Zusammenfassung .

Für all das oben Genannte sind die Anwendungen nicht zu 100% in der Montage entworfen oder geschrieben - nicht einmal in der Nähe. Aber wenn Menschen wirklich Geschwindigkeit brauchen, konzentrieren sie sich darauf, die wichtigsten Teile ihres Codes zu schreiben, um auf bestimmter Hardware zu fliegen.


11
erstaunliche Antwort. Ich wünschte, wir könnten dies in ein Wiki stellen!
Bdd

5
@Paperino ... du kannst. Fragen und Antworten zu StackOverflow sind lizenzierte Creative Commons-Zuschreibungen.
Aaron Maenpaa

Weitere Informationen zum Verständnis von asm zum besseren Schreiben von C / C ++ finden Sie unter Warum ist dieser C ++ - Code schneller als meine handgeschriebene Assembly zum Testen der Collatz-Vermutung? . Meine Antwort dort weist darauf hin, dass das Lesen der ASM-Ausgabe des Compilers und das Optimieren der Quelle hilfreich sein kann, wenn der Compiler keine nützliche Optimierung bemerkt. Sie schreiben also mental (oder tatsächlich) in asm und halten dann den Compiler in der Hand, um das zu tun, was Sie wollen, aber jetzt haben Sie zukunftssicheres tragbares C.
Peter Cordes

42

Ich habe seit vielen Jahren nicht mehr in Assemblersprache codiert, kann aber mehrere Gründe angeben, die ich häufig gesehen habe:

  • Nicht alle Compiler können bestimmte CPU-Optimierungen und Befehlssätze verwenden (z. B. die neuen Befehlssätze, die Intel gelegentlich hinzufügt). Wenn Sie darauf warten, dass Compiler-Autoren aufholen, verlieren Sie einen Wettbewerbsvorteil.

  • Einfachere Anpassung des tatsächlichen Codes an die bekannte CPU-Architektur und -Optimierung. Zum Beispiel Dinge, die Sie über den Abrufmechanismus, das Caching usw. wissen. Dies soll für den Entwickler transparent sein, aber Tatsache ist, dass dies nicht der Fall ist. Deshalb können Compiler-Autoren optimieren.

  • Bestimmte Zugriffe auf Hardwareebene sind nur über die Assemblersprache möglich / praktisch (z. B. beim Schreiben eines Gerätetreibers).

  • Das formale Denken ist für die Assemblersprache manchmal tatsächlich einfacher als für die Hochsprache, da Sie bereits wissen, wie das endgültige oder fast endgültige Layout des Codes lautet.

  • Das Programmieren bestimmter 3D-Grafikkarten (ca. Ende der 90er Jahre) ohne APIs war in Assemblersprache oft praktischer und effizienter und in anderen Sprachen manchmal nicht möglich. Aber auch dies beinhaltete Spiele auf Expertenebene, die auf der Beschleunigerarchitektur basierten, wie das manuelle Verschieben von Daten in einer bestimmten Reihenfolge.

Ich bezweifle, dass viele Leute Assemblersprache verwenden, wenn eine höhere Sprache dies tun würde, insbesondere wenn diese Sprache C ist. Die Handoptimierung großer Mengen von Allzweckcode ist unpraktisch.


19

Es gibt einen Aspekt der Assembler-Programmierung, den andere nicht erwähnt haben - das Gefühl der Zufriedenheit, dass Sie wissen, dass jedes einzelne Byte in einer Anwendung das Ergebnis Ihrer eigenen Bemühungen ist, nicht das des Compilers. Ich würde nicht für eine Sekunde wieder ganze Apps in Assembler schreiben wollen, wie ich es in den frühen 80ern getan habe, aber ich vermisse dieses Gefühl manchmal ...


3
Heh, es ist das Ergebnis der Assembler-Arbeit! Normalerweise schreiben Sie viele Makros in asm.
Mehrdad Afshari

4
Nicht nur Zufriedenheit, sondern Wertschätzung für Präzision. Ein prägnanter Prozess, bei dem alles erklärt wird, ist eine Freude zu sehen.
Deau

17

Normalerweise ist die Versammlung eines Laien langsamer als die von C (aufgrund der Optimierung von C), aber viele Spiele (ich erinnere mich noch genau an Doom ) mussten bestimmte Abschnitte des Spiels in der Versammlung haben, damit es auf normalen Maschinen reibungslos lief.

Hier ist das Beispiel, auf das ich mich beziehe.


1
+1 Sehr wahr. Menschen sind sehr schlecht darin, langen Asm-Code zu schreiben.
Dead Account

Beachten Sie, dass diese Tools beim Schreiben des Assemblers nicht immer verfügbar waren.
Marco van de Voort

15

Ich habe in meinem ersten Job (80er Jahre) mit dem professionellen Programmieren in Assemblersprache begonnen. Für eingebettete Systeme war der Speicherbedarf - RAM und EPROM - gering. Sie könnten engen Code schreiben, der Ressourcen schont.

In den späten 80ern war ich zu C gewechselt. Der Code war einfacher zu schreiben, zu debuggen und zu warten. Sehr kleine Codeausschnitte wurden in Assembler geschrieben - für mich war es, als ich den Kontextwechsel in einem Roll-Your-Own-RTOS schrieb. (Etwas, das Sie nicht mehr tun sollten, es sei denn, es ist ein "wissenschaftliches Projekt".)

In einigen Linux-Kernel-Codes werden Assembler-Snippets angezeigt. Zuletzt habe ich es in Spinlocks und anderem Synchronisationscode durchsucht. Diese Codeteile müssen Zugriff auf atomare Test- und Set-Operationen, das Manipulieren von Caches usw. erhalten.

Ich denke, es wird Ihnen schwer fallen, moderne C-Compiler für die meisten allgemeinen Programmierungen zu optimieren.

Ich stimme @altCognito zu, dass Ihre Zeit wahrscheinlich besser damit verbracht wird, über das Problem nachzudenken und die Dinge besser zu machen. Aus irgendeinem Grund konzentrieren sich Programmierer häufig auf Mikroeffizienzen und vernachlässigen die Makroeffizienzen. Assemblersprache zur Verbesserung der Leistung ist eine Mikroeffizienz. Ein Schritt zurück für eine breitere Ansicht des Systems kann die Makroprobleme in einem System aufdecken. Das Lösen der Makroprobleme kann häufig zu besseren Leistungssteigerungen führen. Sobald die Makroprobleme gelöst sind, kollabieren Sie auf die Mikroebene.

Ich denke, Mikroprobleme liegen in der Kontrolle eines einzelnen Programmierers und in einem kleineren Bereich. Das Ändern des Verhaltens auf Makroebene erfordert die Kommunikation mit mehr Personen - eine Sache, die manche Programmierer vermeiden. Dieser ganze Cowboy gegen die Mannschaftssache.


10

"Ja". Verstehen Sie jedoch, dass sich die Vorteile des Schreibens von Code in Assembler größtenteils nicht lohnen. Die Rendite, die Sie für das Schreiben in der Baugruppe erhalten, ist in der Regel geringer als die bloße Konzentration darauf, sich eingehender mit dem Problem zu befassen und Ihre Zeit damit zu verbringen, über eine bessere Methode nachzudenken.

John Carmack und Michael Abrash, die maßgeblich für das Schreiben von Quake verantwortlich waren, und der gesamte Hochleistungscode, der in IDs-Gaming-Engines enthalten war, gehen in diesem Buch ausführlich darauf ein .

Ich würde auch Ólafur Waage zustimmen, dass Compiler heutzutage ziemlich schlau sind und oft viele Techniken anwenden, die versteckte architektonische Verbesserungen nutzen.


9

Heutzutage schlägt ein anständiger Compiler, zumindest für sequentielle Codes, fast immer sogar einen erfahrenen Assembler-Programmierer. Aber für Vektorcodes ist es eine andere Geschichte. Weit verbreitete Compiler leisten keine so gute Arbeit, indem sie beispielsweise die vektorparallelen Funktionen der x86-SSE-Einheit nutzen. Ich bin ein Compiler-Autor, und das Ausnutzen von SSE steht ganz oben auf meiner Liste der Gründe, sich selbstständig zu machen, anstatt dem Compiler zu vertrauen.


In diesem Fall würde ich einen intrinsischen Compiler verwenden.
Mehrdad Afshari

Immer noch nicht dasselbe. Es ist wie ein Compiler ohne Registeroptimierer
Marco van de Voort

Es hängt davon ab, welche Art von Gewürzen Ihr Asm-Programmierer hat. Wenn Sie agner.org/optimize gelesen und durchsucht haben , um mehr über die Mikroarchitektur zu erfahren, auf die Sie sich einstellen , ist es oft einfach , den Compiler nur für kurze Sequenzen zu schlagen . Mindestens die Hälfte der Zeit habe ich kleinere Optimierungen verpasst, wenn ich die Compilerausgabe für kleine Funktionen betrachte. Wo Compiler großartig sind, ist die Optimierung über große Codebasen mit Inlining und konstanter Weitergabe.
Peter Cordes

8

SSE-Code funktioniert in Assembly besser als Compiler-Intrinsics, zumindest in MSVC. (dh es werden keine zusätzlichen Kopien von Daten erstellt)


Guter Punkt, Sie brauchen einen Compiler, der gute Arbeit mit Intrinsics leistet. Die Intel- und Gnu-Compiler sind ziemlich gut. Ich weiß nicht, ob die neuesten von PGI und PathScale noch wettbewerbsfähig sind. Früher waren sie es nicht.
Jed

5

Einige Anweisungen / Flags / Steuerelemente sind auf C-Ebene einfach nicht vorhanden.

Das Überprüfen auf x86 auf Überlauf ist beispielsweise das einfache Überlaufflag. Diese Option ist in C nicht verfügbar.


Sie können Überlaufflags in C mit Bitoperationen berechnen.
Swegi

@swegi: Ich wette, das ist unbedeutend langsamer.
Brian

Wie oft ist das nützlich? und wenn es so ist, kann es unmöglich der einzige Grund sein, in Assembler zu fallen.

5

Fehler werden in der Regel zeilenweise ausgeführt (Anweisung, Codepunkt usw.). Während es wahr ist, dass Assembly für die meisten Probleme weit mehr Zeilen als Sprachen höherer Ebenen verwendet, gibt es gelegentlich Fälle, in denen es die beste (prägnanteste, wenigste) Zuordnung zum vorliegenden Problem ist. Die meisten dieser Fälle betreffen die üblichen Verdächtigen wie Treiber und Bitbangen in eingebetteten Systemen.


5

Ich habe drei oder vier Assembler-Routinen (in einer Quelle von ca. 20 MB) in meinen Quellen bei der Arbeit. Alle von ihnen sind SSE (2) und beziehen sich auf Operationen an Bildern (ziemlich groß - denken Sie an 2400 x 2048 und größer).

Für das Hobby arbeite ich an einem Compiler, und dort haben Sie mehr Assembler. Laufzeitbibliotheken sind oft voll davon, die meisten haben mit Dingen zu tun, die dem normalen Verfahrensregime widersprechen (wie Helfer für Ausnahmen usw.).

Ich habe keinen Assembler für meinen Mikrocontroller. Die meisten modernen Mikrocontroller verfügen über so viel periphere Hardware (Interrupt-gesteuerte Zähler, sogar ganze Quadraturcodierer und serielle Bausteine), dass die Verwendung eines Assemblers zur Optimierung der Schleifen häufig nicht mehr erforderlich ist. Bei den aktuellen Flash-Preisen gilt das Gleiche für den Codespeicher. Außerdem gibt es häufig eine Reihe von Pin-kompatiblen Geräten, sodass das Hochskalieren, wenn Ihnen systematisch die CPU-Leistung oder der Flash-Speicherplatz ausgeht, oft kein Problem darstellt

Wenn Sie nicht wirklich 100000 Geräte ausliefern und der Assembler programmiert, können Sie wirklich große Einsparungen erzielen, indem Sie einfach einen Flash-Chip einbauen, der eine Kategorie kleiner ist. Aber ich bin nicht in dieser Kategorie.

Viele Leute denken, dass Embedded eine Ausrede für Assembler ist, aber ihre Controller haben mehr CPU-Leistung als die Maschinen, auf denen Unix entwickelt wurde. (Mikrochip mit 40 und 60 MIPS- Mikrocontrollern für unter 10 USD ).

Viele Menschen stecken jedoch im Erbe fest, da es nicht einfach ist, die Mikrochip-Architektur zu ändern. Außerdem ist der HLL-Code sehr architekturabhängig (da er die Hardware-Peripherie, Register zur Steuerung von E / A usw. verwendet). Es gibt also manchmal gute Gründe, ein Projekt weiterhin in Assembler zu verwalten (ich hatte das Glück, Angelegenheiten auf einer neuen Architektur von Grund auf neu einrichten zu können). Aber oft täuschen sich die Leute, dass sie den Monteur wirklich brauchen.

Ich mag immer noch die Antwort eines Professors, als wir fragten, ob wir GOTO verwenden könnten (aber Sie könnten das auch als ASSEMBLER lesen): "Wenn Sie der Meinung sind, dass es sich lohnt, einen dreiseitigen Aufsatz darüber zu schreiben, warum Sie die Funktion benötigen, können Sie sie verwenden Bitte reichen Sie den Aufsatz mit Ihren Ergebnissen ein. "

Ich habe das als Leitprinzip für Lowlevel-Funktionen verwendet. Seien Sie nicht zu eng, um es zu benutzen, aber stellen Sie sicher, dass Sie es richtig motivieren. Wirf sogar ein oder zwei künstliche Barrieren auf (wie den Aufsatz), um verschlungenes Denken als Rechtfertigung zu vermeiden.


Ich mag den Aufsatztest; Ich muss dies möglicherweise öfter verwenden;)
ex nihilo

3

Ein weiterer Grund könnte sein, dass der verfügbare Compiler für eine Architektur einfach nicht gut genug ist und die im Programm benötigte Codemenge nicht so lang oder komplex ist, wie dass der Programmierer sich darin verlieren könnte. Versuchen Sie, einen Mikrocontroller für ein eingebettetes System zu programmieren. In der Regel ist die Montage viel einfacher.


3

Neben anderen erwähnten Dingen haben alle höheren Sprachen bestimmte Einschränkungen. Aus diesem Grund programmieren manche Leute in ASM, um die volle Kontrolle über ihren Code zu haben.

Andere genießen sehr kleine ausführbare Dateien im Bereich von 20 bis 60 KB, z. B. HiEditor , das vom Autor des HiEdit-Steuerelements implementiert wurde, ein hervorragendes, leistungsstarkes Bearbeitungssteuerelement für Windows mit Syntaxhervorhebung und Registerkarten in nur ~ 50 KB. In meiner Sammlung habe ich mehr als 20 solcher Gold-Steuerelemente von Excell wie Ssheets bis hin zu HTML-Renderings.


3

Ich denke, viele Spieleentwickler wären von dieser Information überrascht.

Die meisten Spiele, von denen ich weiß, dass sie so wenig Montage wie möglich verwenden. In einigen Fällen überhaupt keine und im schlimmsten Fall eine oder zwei Schleifen oder Funktionen.

Dieses Zitat ist übertrieben verallgemeinert und bei weitem nicht so wahr wie vor einem Jahrzehnt.

Aber hey, bloße Tatsachen sollten den Kreuzzug eines echten Hackers zugunsten der Versammlung nicht behindern. ;)


3

Wenn Sie einen 8-Bit-Low-End-Mikrocontroller mit 128 Byte RAM und 4 KB Programmspeicher programmieren, haben Sie keine große Auswahl bei der Verwendung von Assembly. Manchmal muss jedoch bei Verwendung eines leistungsstärkeren Mikrocontrollers eine bestimmte Aktion genau zum richtigen Zeitpunkt ausgeführt werden. Die Assemblersprache ist dann nützlich, da Sie die Anweisungen zählen und so die von Ihrem Code verwendeten Taktzyklen messen können.


2

Wenn Sie bei allen Sanierungsbemühungen im Jahr 2000 dabei gewesen wären, hätten Sie viel Geld verdienen können, wenn Sie die Versammlung gekannt hätten. Es gibt immer noch viel Legacy-Code, der darin geschrieben wurde, und dieser Code muss gelegentlich gewartet werden.


2

Abgesehen von sehr kleinen Projekten auf sehr kleinen CPUs würde ich nie ein ganzes Projekt in Assembly programmieren. Es ist jedoch üblich festzustellen, dass ein Leistungsengpass durch die strategische Handcodierung einiger innerer Schleifen behoben werden kann.

In einigen Fällen ist es lediglich erforderlich, ein Sprachkonstrukt durch eine Anweisung zu ersetzen, deren Verwendung vom Optimierer nicht erwartet werden kann. Ein typisches Beispiel sind DSP-Anwendungen, bei denen Vektoroperationen und Multiplikationsakkumulationsoperationen für einen Optimierer schwer zu erkennen sind, der Code jedoch leicht zu handhaben ist.

Beispielsweise enthalten bestimmte Modelle des SH4 4x4-Matrix- und 4 Vektoranweisungen. Ich sah eine enorme Leistungsverbesserung bei einem Farbkorrekturalgorithmus, indem äquivalente C-Operationen auf einer 3x3-Matrix durch die entsprechenden Anweisungen ersetzt wurden, und zwar zu den geringen Kosten der Vergrößerung der Korrekturmatrix auf 4x4, um der Hardwareannahme zu entsprechen. Dies wurde erreicht, indem nicht mehr als ein Dutzend Assemblierungszeilen geschrieben und passende Anpassungen an den zugehörigen Datentypen und der Speicherung an einer Handvoll Stellen im umgebenden C-Code vorgenommen wurden.


2

Es scheint nicht erwähnt zu werden, also dachte ich, ich würde es hinzufügen: In der modernen Spieleentwicklung denke ich, dass zumindest ein Teil der Assembly, die geschrieben wird, überhaupt nicht für die CPU ist. Es ist für die GPU in Form von Shader-Programmen .

Dies kann aus allen möglichen Gründen erforderlich sein, manchmal einfach, weil unabhängig von der verwendeten höheren Schattierungssprache die exakte Operation nicht in der exakten Anzahl der gewünschten Anweisungen ausgedrückt werden kann, um einer Größenbeschränkung, Geschwindigkeit oder einer beliebigen Kombination zu entsprechen . Genau wie bei der Assembler-Programmierung üblich, denke ich.


2

Fast jede mittelgroße bis große Spiel-Engine oder Bibliothek, die ich bisher gesehen habe, verfügt über einige handoptimierte Assembly-Versionen, die für Matrixoperationen wie die 4x4-Matrixverkettung verfügbar sind. Es scheint, dass Compiler bei der Arbeit mit großen Matrizen unweigerlich einige der cleveren Optimierungen übersehen (Register wiederverwenden, Schleifen maximal effizient abrollen, maschinenspezifische Anweisungen nutzen usw.). Diese Matrixmanipulationsfunktionen sind fast immer auch "Hotspots" im Profil.

Ich habe auch gesehen, dass handcodierte Baugruppen häufig für den benutzerdefinierten Versand verwendet werden - Dinge wie FastDelegate, aber compiler- und maschinenspezifisch.

Wenn Sie über Interrupt-Serviceroutinen verfügen, kann asm den Unterschied in der Welt ausmachen. Es gibt bestimmte Vorgänge, die unter Interrupt einfach nicht ausgeführt werden sollen, und Sie möchten, dass Ihre Interrupt-Handler "schnell ein- und aussteigen". .. Sie wissen fast genau, was in Ihrem ISR passieren wird, wenn es in asm ist, und es ermutigt Sie, die blutigen Dinge kurz zu halten (was sowieso eine gute Praxis ist).


2

Spiele sind ziemlich leistungshungrig und obwohl die Optimierer in der Zwischenzeit ziemlich gut sind, kann ein "Master-Programmierer" immer noch etwas mehr Leistung herausholen, indem er die richtigen Teile in der Montage von Hand codiert.

Beginnen Sie niemals mit der Optimierung Ihres Programms, ohne zuvor ein Profil erstellt zu haben. Nachdem die Profilerstellung in der Lage sein sollte, Engpässe zu identifizieren, und wenn Sie bessere Algorithmen und ähnliches finden, können Sie versuchen, einige Dinge in der Baugruppe von Hand zu codieren.


2

Ich habe nur persönlich mit einem Entwickler über seine Verwendung von Assembly gesprochen. Er arbeitete an der Firmware, die sich mit den Steuerelementen für einen tragbaren MP3-Player befasste. Die Arbeit in der Montage hatte zwei Zwecke:

  1. Geschwindigkeit: Verzögerungen mussten minimal sein.
  2. Kosten: Da der Code minimal ist, kann die zum Ausführen erforderliche Hardware etwas weniger leistungsfähig sein. Bei der Massenproduktion von Millionen von Einheiten kann sich dies summieren.

2

Die einzige Assembler-Codierung, die ich weiterhin mache, ist für eingebettete Hardware mit knappen Ressourcen. Wie Leander erwähnt, eignet sich Assembly immer noch gut für ISRs, bei denen der Code schnell und gut verstanden werden muss.

Ein zweiter Grund für mich ist, mein Wissen über die Montage funktionsfähig zu halten. Es fühlt sich einfach gut an, die Schritte zu untersuchen und zu verstehen, die die CPU unternimmt, um meine Gebote abzugeben.


2

Das letzte Mal, als ich in Assembler schrieb, konnte ich den Compiler nicht davon überzeugen, libc-freien, positionsunabhängigen Code zu generieren.

Das nächste Mal wird wahrscheinlich aus dem gleichen Grund sein.

Natürlich hatte ich früher andere Gründe .


2

Viele Leute lieben es, Assemblersprache zu verunglimpfen, weil sie nie gelernt haben, damit zu programmieren, und nur vage darauf gestoßen sind und sie entweder entsetzt oder etwas eingeschüchtert sind. Echte talentierte Programmierer werden verstehen, dass es sinnlos ist, C oder Assembly zu verprügeln, weil sie sich ergänzen. in der Tat ist der Vorteil des einen der Nachteil des anderen. Die organisierten syntaktischen Regeln von C verbessern die Klarheit, geben aber gleichzeitig alles auf, was die Power Assembly davon hat, frei von strukturellen Regeln zu sein! C-Code-Anweisungen werden erstellt, um nicht blockierenden Code zu erstellen, der die Klarheit der Programmierabsicht erzwingen könnte, aber dies ist ein Leistungsverlust. In C erlaubt der Compiler keinen Sprung innerhalb eines if / elseif / else / end. Oder Sie dürfen nicht zwei for / end-Schleifen für verschiedene Variablen schreiben, die sich überlappen. Sie können keinen selbstmodifizierenden Code schreiben (oder nicht auf nahtlose, einfache Weise) usw. Herkömmliche Programmierer sind von dem oben Gesagten erschreckt und hätten keine Ahnung, wie sie die Leistungsfähigkeit dieser Ansätze überhaupt nutzen können, da sie zur Befolgung herkömmlicher Regeln erhoben wurden . Hier ist die Wahrheit: Heute haben wir eine Maschine mit der Rechenleistung, die viel mehr kann als die Anwendung, für die wir sie verwenden, aber das menschliche Gehirn ist zu unfähig, sie in einer regelfreien Codierungsumgebung (= Assembly) zu codieren, und benötigt so restriktive Regeln Reduzieren Sie das Spektrum und vereinfachen Sie die Codierung. Ich habe selbst Code geschrieben, der nicht in C-Code geschrieben werden kann, ohne aufgrund der oben genannten Einschränkungen äußerst ineffizient zu werden. Und ich habe noch nicht über Geschwindigkeit gesprochen, von der die meisten Leute denken, dass sie der Hauptgrund für das Schreiben in der Versammlung ist. Nun, wenn es Ihnen etwas ausmacht, in C zu denken, dann sind Sie für immer der Sklave Ihres Compilers. Ich dachte immer, Schachspieler-Meister wären ideale Assembler-Programmierer, während die C-Programmierer nur "Dames" spielen.


1
Selbstmodifizierender Code ist für die Leistung auf den meisten modernen CPUs außerhalb von JIT-Once / Run-Many-Szenarien nicht hilfreich. Das sofortige Ausfüllen von Konstanten ist jedoch eine unterhaltsame Möglichkeit. C gotoerlaubt jedoch unstrukturierte Sprünge innerhalb einer Funktion. Einfügen in einen Block innerhalb einer if()oder-Schleife in derselben Funktion. zB godbolt.org/z/IINHTg . Siehe auch Duffs Gerät, bei dem Switch / Case in eine do{}while()Schleife verwendet wird, um einen Sprung in eine abgewickelte Schleife auszudrücken. Aber irgendwann kann es klarer werden, in asm zu schreiben, wenn Sie auf diese Ebene des Chaos kommen.
Peter Cordes

1
(Natürlich ist Duffs Gerät nur auf Maschinen mit Post-Inkrement-Adressierung nützlich, andernfalls verlieren diese Einstiegspunkte innerhalb der abgewickelten Schleife nur den größten Teil des Optimierungszwecks.)
Peter Cordes

1

Nicht mehr Geschwindigkeit, sondern Kontrolle . Geschwindigkeit wird manchmal von der Kontrolle kommen, aber es ist der einzige Grund , in der Baugruppe zu codieren. Jeder andere Grund läuft auf die Kontrolle hinaus (dh SSE- und andere Handoptimierung, Gerätetreiber und geräteabhängiger Code usw.).


1

Wenn ich in der Lage bin, GCC und Visual C ++ 2008 (auch als Visual C ++ 9.0 bekannt) zu übertreffen, sind die Leute daran interessiert, mich zu befragen, wie dies möglich ist.

Aus diesem Grund lese ich im Moment nur die Dinge in der Assembly und schreibe bei Bedarf __asm ​​int 3.

Ich hoffe diese Hilfe ...


1

Ich habe einige Jahre nicht in der Versammlung geschrieben, aber die zwei Gründe, die ich früher hatte, waren:

  • Die Herausforderung der Sache! Ich habe vor einigen Monaten einen Zeitraum durchlaufen, in dem ich alles in x86-Assembly geschrieben habe (die Tage von DOS und Windows 3.1). Es brachte mir im Grunde einen Teil von Low-Level-Operationen, Hardware- E / A usw. bei.
  • Für einige Dinge hielt es die Größe klein (wieder DOS und Windows 3.1 beim Schreiben von TSRs )

Ich schaue immer wieder auf die Codierung und es ist nichts weiter als die Herausforderung und Freude an der Sache. Ich habe keinen anderen Grund dazu :-)


1

Ich habe einmal ein DSP-Projekt übernommen, das der vorherige Programmierer hauptsächlich in Assembler-Code geschrieben hatte, mit Ausnahme der in C geschriebenen Tonerkennungslogik mit Gleitkomma (auf einem Festkomma-DSP!). Die Tonerkennungslogik lief ungefähr 1/20 der Echtzeit.

Am Ende habe ich fast alles von Grund auf neu geschrieben. Fast alles befand sich in C, mit Ausnahme einiger kleiner Interrupt-Handler und einiger Dutzend Codezeilen, die sich auf die Interrupt-Behandlung und die Frequenzerkennung auf niedriger Ebene beziehen und mehr als 100-mal so schnell wie der alte Code ausgeführt werden.

Ich denke, es ist wichtig zu bedenken, dass es in vielen Fällen viel größere Möglichkeiten zur Geschwindigkeitsverbesserung bei kleinen Routinen gibt als bei großen, insbesondere wenn handgeschriebene Assembler alles in Register einfügen können, ein Compiler jedoch nicht ganz verwalten. Wenn eine Schleife groß genug ist, um ohnehin nicht alles in Registern zu halten, gibt es weitaus weniger Verbesserungsmöglichkeiten.


0

Die Dalvik-VM, die den Bytecode für Java-Anwendungen auf Android-Telefonen interpretiert, verwendet Assembler für den Dispatcher. Dieser Film (ungefähr 31 Minuten, aber es lohnt sich, den ganzen Film anzuschauen!) Erklärt, wie

"Es gibt immer noch Fälle, in denen ein Mensch besser kann als ein Compiler".


0

Ich nicht, aber ich habe es mir zum Ziel gesetzt, es zumindest zu versuchen und es irgendwann in der Zukunft (hoffentlich bald) zu versuchen. Es kann keine schlechte Sache sein, mehr über das Low-Level-Zeug und die Funktionsweise hinter den Kulissen zu erfahren, wenn ich in einer High-Level-Sprache programmiere. Leider ist es schwierig, mit einem Vollzeitjob als Entwickler / Berater und Eltern Zeit zu finden. Aber ich werde zu gegebener Zeit geben, das ist sicher.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.