it-swarm.com.de

Wie hilft das Lernen der Versammlung beim Programmieren?

Ich programmiere seit ungefähr 10 Jahren in höheren Sprachen (Python, C #, VBA, VB.NET) und habe keinerlei Verständnis dafür, was "unter der Haube" vor sich geht.

Ich frage mich, was die Vorteile des Lernens von Assembly sind und wie es mir als Programmierer helfen wird. Können Sie mir bitte eine Ressource zur Verfügung stellen, die mir genau den Zusammenhang zwischen dem, was ich in höherwertigem Code schreibe, und dem, was in der Assembly geschieht, zeigt?

Weil du verstehen wirst, wie es wirklich funktioniert.

  • Sie werden verstehen, dass Funktionsaufrufe nicht kostenlos sind und warum der Aufrufstapel überlaufen kann (z. B. in rekursiven Funktionen). Sie werden verstehen, wie Argumente an Funktionsparameter übergeben werden und wie dies möglich ist (Kopieren des Speichers, Zeigen auf den Speicher).
  • Sie werden verstehen, dass Speicher nicht kostenlos ist und wie wertvoll die automatische Speicherverwaltung ist. Gedächtnis ist nicht etwas, das Sie "nur haben", in Wirklichkeit muss es verwaltet, gepflegt und vor allem nicht vergessen werden (weil Sie es selbst befreien müssen).
  • Sie werden verstehen, wie der Kontrollfluss auf einer grundlegendsten Ebene funktioniert.
  • Sie werden die Konstrukte in höheren Programmiersprachen mehr zu schätzen wissen.

Es läuft darauf hinaus, dass alle Dinge, die wir in C # oder Python schreiben), in eine Folge grundlegender Aktionen übersetzt werden müssen, die ein Computer ausführen kann. Es ist einfach, sich einen Computer in Begriffen vorzustellen von Klassen, Generika und Listenverständnissen, aber diese existieren nur in unseren höheren Programmiersprachen.

Wir können uns Sprachkonstrukte vorstellen, die wirklich gut aussehen, sich aber nicht sehr gut auf eine einfache Art und Weise übersetzen lassen. Wenn Sie wissen, wie es wirklich funktioniert, werden Sie besser verstehen, warum die Dinge so funktionieren, wie sie funktionieren.

188
Simeon Visser

Sie erhalten ein besseres Verständnis dafür, was "unter der Haube passiert" und wie Zeiger funktionieren und welche Bedeutung Registervariablen und -architekturen (Speicherzuweisung und -verwaltung, Parameterübergabe (nach Wert/Referenz) usw.) im Allgemeinen haben.

Für einen kurzen Blick mit C wie ist das?

#include <stdio.h>

main()
{
  puts("Hello World.");
  return(0);
}

kompilieren mit gcc -S so.c und werfen Sie einen Blick auf die Assembly-Ausgabe in so.s:

 $ cat so.s

    .file   "so.c"
    .section    .rodata
.LC0:
    .string "Hello World."
    .text
.globl main
    .type   main, @function
main:
    pushl   %ebp
    movl    %esp, %ebp
    andl    $-16, %esp
    subl    $16, %esp
    movl    $.LC0, (%esp)
    call    puts
    movl    $0, %eax
    leave
    ret
    .size   main, .-main
    .ident  "GCC: (Ubuntu 4.4.3-4ubuntu5.1) 4.4.3"
    .section    .note.GNU-stack,"",@progbits
33
Levon

Ich denke, die Antwort, die Sie suchen, ist hier: http://www.codeproject.com/Articles/89460/Why-Learn-Assembly-Language

Ein Zitat aus dem Artikel:

Obwohl es stimmt, werden Sie wahrscheinlich nicht feststellen, dass Sie die App Ihres nächsten Kunden in Assembly schreiben. Es gibt jedoch noch viel zu gewinnen, wenn Sie Assembly lernen. Heutzutage wird die Assemblersprache hauptsächlich zur direkten Manipulation der Hardware, zum Zugriff auf spezielle Prozessoranweisungen oder zur Behebung kritischer Leistungsprobleme verwendet. Typische Anwendungen sind Gerätetreiber, eingebettete Systeme auf niedriger Ebene und Echtzeitsysteme.

Tatsache ist, je komplexer Hochsprachen werden und je mehr ADT (abstrakte Datentypen) geschrieben werden, desto mehr Aufwand entsteht, um diese Optionen zu unterstützen. In den Fällen von .NET möglicherweise aufgeblähtes MSIL. Stellen Sie sich vor, Sie kennen MSIL. Hier leuchtet die Assemblersprache.

Die Assemblersprache kommt dem Prozessor so nahe wie möglich als Programmierer, sodass ein gut konzipierter Algorithmus auf dem Vormarsch ist. Die Assemblersprache eignet sich hervorragend zur Geschwindigkeitsoptimierung. Es geht um Leistung und Effizienz. Mit der Assemblersprache haben Sie die vollständige Kontrolle über die Ressourcen des Systems. Ähnlich wie bei einer Fertigungslinie schreiben Sie Code, um einzelne Werte in Register zu übertragen, Speicheradressen direkt zu verarbeiten, um Werte oder Zeiger abzurufen.

In Assembly zu schreiben bedeutet, genau zu verstehen, wie Prozessor und Speicher zusammenarbeiten, um "Dinge geschehen zu lassen". Seien Sie gewarnt, die Assemblersprache ist kryptisch und der Quellcode der Anwendung ist viel größer als die einer Hochsprache. Aber machen Sie keinen Fehler, wenn Sie bereit sind, Zeit und Mühe zu investieren, um die Versammlung zu meistern, werden Sie besser und Sie werden ein herausragender Spieler auf dem Gebiet.

Darüber hinaus würde ich dieses Buch empfehlen, da es eine vereinfachte Version der Computerarchitektur enthält: Einführung in Computersysteme: Von Bits und Gates bis C und darüber hinaus, 2/e Yale N. Patt, Universität von Texas, Austin Sanjay J. Patel, Universität von Illinois in Urbana/Champaign

30
Brynne

Meiner bescheidenen Meinung nach es hilft nicht viel.

Ich kannte x86 Assembly sehr gut. Es hat ein wenig geholfen, als Assembly in meinen Kursen auftauchte, es kam einmal während eines Interviews und es hat mir geholfen zu beweisen, dass ein Compiler (Metrowerks) schlechten Code generiert. Es ist faszinierend, wie der Computer tatsächlich funktioniert, und ich fühle mich intellektuell reicher, wenn ich ihn gelernt habe. Es hat damals auch sehr viel Spaß gemacht, damit zu spielen.

Die heutigen Compiler können Assembly jedoch besser generieren als fast jeder andere auf fast jedem Code. Wenn Sie keinen Compiler schreiben oder überprüfen, ob Ihr Compiler das Richtige tut, verschwenden Sie wahrscheinlich Ihre Zeit, indem Sie ihn lernen.

Ich gebe zu, dass viele Fragen, die C++ - Programmierer immer noch sinnvoll stellen, durch das Wissen über Assembly informiert werden. Zum Beispiel: Soll ich Stapel- oder Heap-Variablen verwenden? soll ich nach Wert oder nach konstanter Referenz übergeben? In fast allen Fällen denke ich jedoch, dass diese Entscheidungen eher auf der Lesbarkeit des Codes als auf der Einsparung von Rechenzeit beruhen sollten. (Verwenden Sie beispielsweise Stapelvariablen, wenn Sie eine Variable auf einen Bereich beschränken möchten.)

Mein bescheidener Vorschlag ist, mich auf Fähigkeiten zu konzentrieren, die wirklich wichtig sind: Software-Design, Algorithmus-Analyse und Problemlösung. Mit der Erfahrung bei der Entwicklung großer Projekte wird sich Ihre Intuition verbessern, was Ihren Wert viel mehr erhöht als das Wissen um die Versammlung (meiner Meinung nach).

22
Neil G

Sie sollten mit einer Ebene „tiefer“ in dem System vertraut sein, auf dem Sie arbeiten. Zu weit nach unten zu springen ist nicht schlecht, aber möglicherweise nicht so hilfreich, wie man es sich wünscht.

Ein Programmierer in einer höheren Sprache sollte eine niedrigere Sprache lernen (C ist eine ausgezeichnete Option). Sie müssen nicht bis zur Assembly gehen, um zu verstehen, was unter der Decke vor sich geht, wenn Sie den Computer anweisen, ein Objekt zu instanziieren oder eine Hash-Tabelle oder einen Satz zu erstellen - aber Sie sollten in der Lage sein, zu codieren Sie.

Für einen Java -Programmierer würde das Erlernen von C bei der Speicherverwaltung helfen und Argumente übergeben. Das Schreiben einiger der umfangreichen Java -Bibliothek in C würde einen Weg dahin gehen Wenn Sie wissen, wann welche Implementierung von Set verwendet werden soll (möchten Sie einen Hash oder Baum?), können Sie besser verstehen, warum String unveränderlich ist, wenn Sie mit char * in einer Thread-Umgebung umgehen.

Auf die nächste Ebene gebracht ... Ein C-Programmierer sollte mit Assembly vertraut sein, und Assembly-Typen (häufig in Shops für eingebettete Systeme zu finden) würden wahrscheinlich gut dazu beitragen, die Dinge auf der Ebene der Gates zu verstehen. Wer mit Toren arbeitet, sollte sich mit Quantenphysik auskennen. Und diese Quantenphysiker versuchen immer noch herauszufinden, was die nächste Abstraktion ist.

21
user40980

Da Sie C oder C++ in den Sprachen, die Sie kennen, nicht erwähnt haben. Ich würde DRINGEND empfehlen, sie gut zu lernen, bevor ich überhaupt an die Versammlung denke. C oder C++ bietet alle grundlegenden Konzepte, die in verwalteten Sprachen vollständig transparent sind, und Sie verstehen die meisten der auf dieser Seite erwähnten Konzepte mit einer der wichtigsten Sprachen, die Sie in realen Projekten verwenden können. Dies ist ein echter Mehrwert für Ihre Programmierkenntnisse. Bitte beachten Sie, dass Assembly in ganz bestimmten Bereichen verwendet wird und bei weitem nicht so nützlich ist wie C oder C++.

Ich würde sogar noch weiter gehen und sagen, dass Sie nicht zur Versammlung gehen sollten, bevor Sie verstanden haben, wie nicht verwaltete Sprachen funktionieren. Es ist fast eine obligatorische Lektüre.

Sie sollten Assembly lernen, wenn Sie noch weiter nach unten gehen möchten. Sie möchten wissen, wie genau jedes einzelne Konstrukt der Sprache erstellt wird. Es ist informativ, aber es ist eine ganz andere Komplexität.

5
AhHatem

Wenn Sie eine Sprache gut beherrschen, sollten Sie mindestens eine Grundstufe der Abstraktion über Grundkenntnisse der Technologie verfügen.

Warum? Wenn etwas schief geht, erleichtert die Kenntnis der zugrunde liegenden Mechanik das Debuggen seltsamer Probleme und das Schreiben von effizienterem Code

Wenn Sie Python (/ CPython) als Beispiel verwenden und seltsame Abstürze oder schlechte Leistung feststellen, kann das Wissen über das Debuggen von C-Code sehr nützlich sein, ebenso wie das Wissen über die Ref-Counting-Speicherverwaltungsmethode. Dies würde Ihnen auch helfen zu wissen, wann/ob Sie etwas als C-Erweiterung schreiben müssen, und so weiter ...

Um Ihre Frage in diesem Fall zu beantworten, würde das Wissen über Assembly einem erfahrenen Python Entwickler) wirklich nicht helfen (es sind zu viele Schritte in der Abstraktion - alles, was in Python) getan wird = würde zu vielen, vielen Montageanweisungen führen)

..aber wenn Sie Erfahrung mit C haben, dann wäre es in der Tat nützlich, "die nächste Stufe nach unten" (Versammlung) zu kennen.

Wenn Sie CoffeScript verwenden, ist es (sehr) nützlich, Javascript zu kennen. Wenn Sie Clojure verwenden, sind Kenntnisse in Java/JVM hilfreich.

Diese Idee funktioniert auch außerhalb von Programmiersprachen. Wenn Sie Assembly verwenden, sollten Sie sich mit der Funktionsweise der zugrunde liegenden Hardware vertraut machen. Wenn Sie ein Webdesigner sind, ist es eine gute Idee zu wissen, wie die Webanwendung implementiert ist. Wenn Sie ein Automechaniker sind, ist es eine gute Idee, einige Kenntnisse der Physik zu haben

5
dbr

Schreiben Sie ein kleines c-Programm und zerlegen Sie die Ausgabe. Das ist alles. Seien Sie jedoch auf einen mehr oder weniger hohen Grad an "Housekeeping" -Code vorbereitet, der zum Nutzen des Betriebssystems hinzugefügt wird.

Assembly hilft Ihnen zu verstehen, was unter der Haube vor sich geht, da es sich direkt um Speicher, Prozessorregister und dergleichen handelt.

Wenn Sie wirklich Bare-Metal-fähig sein möchten, ohne dass die Komplexität eines Betriebssystems die Dinge kompliziert, versuchen Sie, ein Arduino in Assembler-Sprache. zu programmieren

3
Robert Harvey

Es gibt keine endgültige Antwort, da Programmierer nicht alle von einem Typ sind. MÜSSEN Sie wissen, was darunter lauert? Wenn ja, dann lerne es. willst du es nur aus Neugier lernen? Wenn ja, dann lerne es. Wenn es für Sie keinen praktischen Nutzen hat, warum dann? Benötigt man das Wissen eines Mechanikers, um ein Auto zu fahren? Benötigt ein Mechaniker das Wissen eines Ingenieurs, um an einem Auto arbeiten zu können? Dies ist eine ernsthafte Analogie. Ein Mechaniker kann ein sehr guter, produktiver Mechaniker sein, ohne zu tauchen, um die Fahrzeuge, die er wartet, gründlich zu verstehen. Gleiches gilt für Musik. Möchten Sie wirklich die Komplexität von Melodie, Harmonie und Rhythmus ausloten, um ein guter Sänger oder Spieler zu sein? Nein. Einige außergewöhnlich talentierte Musiker können keine Noten lesen, geschweige denn den Unterschied zwischen dem dorischen und dem lydischen Modus erklären. Wenn Sie wollen, gut, aber nein, müssen Sie nicht. Wenn Sie ein Webentwickler sind, hat Assembly keinen praktischen Nutzen, den ich mir vorstellen kann. Wenn Sie sich in eingebetteten Systemen oder etwas ganz Besonderem befinden, ist dies möglicherweise erforderlich, aber wenn dies der Fall wäre, würden Sie es wissen.

Hier ist Joels Auffassung, wie wichtig es ist, eine Sprache auf hohem Niveau zu lernen: http://www.joelonsoftware.com/articles/ThePerilsofJavaSchools.html

3
GrayFox374

Was für Sie wahrscheinlich am besten wäre, wäre eine Klasse, die meines Wissens nirgendwo existiert: Es wäre eine Klasse, die einen kurzen Überblick über Maschinen-/Assembler-Sprache und Speicheradressierungskonzepte mit einem Rundgang durch die Compilerkonstruktion kombiniert , Codegenerierung und Laufzeitumgebungen.

Das Problem ist, dass Sie mit einer Hochsprache, die weit von der Hardware entfernt ist, wie C # oder Python], die Tatsache nicht wirklich zu schätzen wissen, dass jede Bewegung, die Sie machen, zu Hunderten wird, wenn Nicht Tausende von Maschinenanweisungen, und Sie neigen nicht dazu zu verstehen, wie ein paar Zeilen einer Hochsprache dazu führen können, dass auf große Mengen an Speicher zugegriffen und Änderungen vorgenommen werden. Es ist nicht so sehr, dass Sie genau wissen müssen, was vor sich geht "under the cover", aber Sie müssen ein Verständnis für den Umfang des Geschehens und eine allgemeine Vorstellung von den Arten von Dingen haben, die auftreten.

2
Daniel R Hicks

Meine Antwort auf diese Frage hat sich vor relativ kurzer Zeit weiterentwickelt. Die vorhandenen Antworten decken das ab, was ich in der Vergangenheit gesagt hätte. Eigentlich wird dies immer noch durch den Punkt Top-Antwort - "Schätzen Sie die Konstrukte in der übergeordneten Programmierung" abgedeckt, aber es ist ein Sonderfall, den ich für erwähnenswert halte ...

Laut diesem Jeff Atwood-Blogbeitrag , der auf eine Studie verweist, ist das Verständnis der Zuordnung ein zentrales Thema für das Verständnis der Programmierung. Lernende Programmierer verstehen entweder, dass die Notation nur Schritte darstellt, denen der Computer folgt, und begründet sie durch die Schritte, oder sie werden durch irreführende Analogien zu mathematischen Gleichungen usw. ständig verwirrt.

Nun, wenn Sie das Folgende von 6502 Assembler verstehen ...

LDA variable
CLC
ADC #1
STA variable

Das sind wirklich nur die Schritte. Wenn Sie dann lernen, das in eine Zuweisungsanweisung zu übersetzen ...

variable = variable + 1;

Sie brauchen keine irreführende Analogie zu einer mathematischen Gleichung - Sie haben bereits ein korrektes mentales Modell, auf das Sie es abbilden können.

[~ # ~] edit [~ # ~] - natürlich, wenn die Erklärung von LDA variable ist im Grunde ACCUMULATOR = variable, genau das bekommen Sie aus einigen Tutorials und Referenzen. Sie landen wieder dort, wo Sie angefangen haben, und es ist überhaupt keine Hilfe.

Ich habe 6502 Assembler als meine zweite Sprache gelernt, die erste war Commodore Basic, und ich hatte damals nicht wirklich viel davon gelernt - teilweise, weil es so wenig zu lernen gab, aber auch, weil Assembler damals einfach so viel interessanter schien . Teilweise die Zeit, teils weil ich ein 14 Jahre alter Geek war.

Ich empfehle nicht, das zu tun, was ich getan habe, aber ich frage mich, ob das Lernen einiger sehr einfacher Beispiele in einer sehr einfachen Assembler-Sprache eine lohnende Vorbereitung für das Erlernen höherer Sprachen sein könnte.

1
Steve314

Das Schreiben in Assembly würde Ihnen keine magische Geschwindigkeitssteigerung bringen, da Sie aufgrund der Menge an Details (Registerzuordnung usw.) wahrscheinlich den trivialsten Algorithmus aller Zeiten schreiben werden.

Bei modernen (nach 70-80 Jahren entworfenen) Prozessoren liefert Assembly außerdem nicht genügend Details, um zu wissen, was vor sich geht (dh bei den meisten Prozessoren). Moderne PU (CPUs und GPUs) sind in Bezug auf Planungsanweisungen recht komplex. Wenn Sie die Grundlagen der Assembly (oder Pseudoassembly) kennen, können Sie Bücher/Kurse zur Computerarchitektur verstehen, die weitere Kenntnisse (Caches) liefern , Ausführung außerhalb der Reihenfolge, MMU usw.). Normalerweise müssen Sie nicht komplex sein ISA, um sie zu verstehen (MIPS 5 ist sehr beliebt) IIRC).

Warum Prozessor verstehen? Es könnte Ihnen viel mehr Verständnis geben, was los ist. Angenommen, Sie schreiben die Matrixmultiplikation auf naive Weise:

for i from 0 to N
    for j from 0 to N
        for k from 0 to N
            A[i][j] += B[i][k] + C[k][j]

Es kann für Ihren Zweck "gut genug" sein (wenn es sich um eine 4x4-Matrix handelt, kann es ohnehin zu Vektoranweisungen kompiliert werden). Es gibt jedoch ziemlich wichtige Programme, wenn Sie massive Arrays kompilieren - wie können Sie diese optimieren? Wenn Sie den Code in Assembly schreiben, können Sie einige Prozent der Verbesserungen erzielen (es sei denn, Sie tun dies wie die meisten Leute - auch auf naive Weise, indem Sie die Register nicht ausreichend nutzen, ständig in den Speicher laden/speichern und tatsächlich ein langsameres Programm als in HL-Sprache haben). .

Sie können jedoch die Linien umkehren und auf magische Weise an Leistung gewinnen (warum? Ich lasse es als 'Hausaufgabe') - IIRC kann in Abhängigkeit von verschiedenen Faktoren für große Matrizen sogar 10x sein.

for i from 0 to N
    for k from 0 to N
        for j from 0 to N
            A[i][j] += B[i][k] + C[k][j]

Das heißt - es wird daran gearbeitet, dass Compiler dies tun können ( Graphit für gcc und Polly für alles, was LLVM verwendet). Sie sind sogar in der Lage, es in etwas umzuwandeln (sorry - ich schreibe Blocking from Memory):

for i from 0 to N
    for K from 0 to N/n
        for J from 0 to N/n
            for kk from 0 to n
                for jj from 0 to n
                    k = K*n + kk
                    j = J*n + jj
                    A[i][j] += B[i][k] + C[k][j]

Zusammenfassend lässt sich sagen, dass Sie mit den Grundlagen einer Assembly verschiedene Details des Prozessordesigns kennenlernen können, mit denen Sie schnellere Programme schreiben können. Es kann gut sein, Unterschiede zwischen RISC/CISC- oder VLIW/Vektorprozessor/SIMD/... -Architekturen zu kennen. Ich würde jedoch nicht mit x86 beginnen, da diese eher kompliziert sind (möglicherweise ARM auch) - zu wissen, was ein Register usw. ist, ist meiner Meinung nach ausreichend für den Start.

0

Wenn Sie kein Compiler-Writer sind oder etwas hochoptimiertes benötigen (wie einen Datenverarbeitungsalgorithmus), bietet Ihnen das Erlernen der Assembly-Codierung keine Vorteile.

Das Schreiben und Verwalten von in Assembly geschriebenem Code ist sehr schwierig. Selbst wenn Sie die Assembler-Sprache sehr gut kennen, sollten Sie sie nicht verwenden, es sei denn, es gibt keine anderen Möglichkeiten.

Der Artikel " Optimierung für SSE: Eine Fallstudie " zeigt, was möglich ist, wenn Sie zur Assembly gehen. Dem Autor ist es gelungen, den Algorithmus von 100 Zyklen/Vektor auf 17 Zyklen/Vektor zu optimieren.

0
BЈовић