Ich programmiere seit ungefähr 10 Jahren in höheren Programmiersprachen (Python, C #, VBA, VB.NET) und habe keinerlei Verständnis dafür, was "unter der Haube" vor sich geht.
Ich frage mich, welche Vorteile das Lernen von Assembler hat 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öherem Code schreibe, und dem, was in der Assembly passiert, zeigt?
for
Schleife zu optimieren, indem Sie Variablen außerhalb der Schleife deklarieren. BeispielAntworten:
Weil Sie verstehen werden, wie es wirklich funktioniert.
Alles, was wir in C # oder Python schreiben, muss in eine Folge grundlegender Aktionen übersetzt werden, die ein Computer ausführen kann. Es ist leicht, sich einen Computer in Bezug auf Klassen, Generika und Listenverständnisse vorzustellen, aber diese existieren nur in unseren höheren Programmiersprachen.
Wir können uns Sprachkonstrukte vorstellen, die wirklich gut aussehen, sich aber nicht 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.
quelle
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?
Kompilieren Sie mit
gcc -S so.c
und werfen Sie einen Blick auf die Assembly-Ausgabe inso.s
:quelle
so.c
für Stackoverflow-Fragen (wie ichso.py
,so.awk
etc.), um die Dinge schnell zu testen. So.S .. :)gcc -O -c -g -Wa,-ahl=so.s so.c
, sehen Sie die Assembly-Ausgabe für jede Zeile des C-Codes. Dies macht es ein wenig einfacher zu verstehen, was los ist.5:so.c
, um den Code für Zeile 5 von zu findenso.c
.Ich denke, die Antwort, die Sie suchen, ist hier: http://www.codeproject.com/Articles/89460/Why-Learn-Assembly-Language
Ein Zitat aus dem Artikel:
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 zu C und darüber hinaus, 2 / e Yale N. Patt, Universität Texas, Austin Sanjay J. Patel, Universität von Illinois in Urbana / Champaign
quelle
Meiner bescheidenen Meinung nach hilft es nicht viel.
Ich kannte x86-Assembly sehr gut. Es hat ein wenig geholfen, als in meinen Kursen Assembler auftauchte, es ist einmal während eines Interviews aufgetaucht, und es hat mir geholfen zu beweisen, dass ein Compiler (Metrowerks) schlechten Code generiert hat. Es ist faszinierend, wie der Computer tatsächlich funktioniert, und ich fühle mich geistig reicher, wenn ich ihn gelernt habe. Es hat damals auch sehr viel Spaß gemacht, damit zu spielen.
Die heutigen Compiler sind jedoch besser in der Lage, Assembler zu generieren als fast jeder andere, der mit fast jedem Code arbeitet. Wenn Sie keinen Compiler schreiben oder überprüfen, ob Ihr Compiler das Richtige tut, verschwenden Sie wahrscheinlich Ihre Zeit, indem Sie ihn erlernen.
Ich gebe zu, dass viele Fragen, die C ++ - Programmierer immer noch sinnvoll stellen, durch Assembler-Kenntnisse beantwortet werden. Beispiel: Soll ich Stack- oder Heap-Variablen verwenden? soll ich als Wert oder als konstante Referenz übergeben? In fast allen Fällen sollten diese Entscheidungen jedoch auf der Grundlage der Lesbarkeit des Codes getroffen werden, anstatt Rechenzeit zu sparen. (Verwenden Sie 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, große Projekte zu entwickeln, wird sich Ihre Intuition verbessern, was Ihren Wert viel mehr steigert als das Wissen um die Montage (meiner Meinung nach).
quelle
Sie sollten mit einer Ebene „tiefer“ in dem System vertraut sein, auf dem Sie arbeiten. In einem Rutsch 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 den ganzen Weg bis zum Zusammenbau zurücklegen, um eine Vorstellung davon zu bekommen, 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, Code zu erstellen Sie.
Für einen Java-Programmierer würde das Erlernen von C Ihnen bei der Speicherverwaltung helfen und Argumente übergeben. Wenn Sie einige der umfangreichen Java-Bibliotheken in C schreiben, können Sie nachvollziehen, wann Sie welche Implementierung von Set verwenden müssen (möchten Sie einen Hash oder einen Baum?). Der Umgang mit char * in einer Thread-Umgebung hilft zu verstehen, warum String unveränderlich ist.
Auf die nächste Ebene gebracht ... AC-Programmierer sollten mit Baugruppen vertraut sein, und Baugruppentypen (die häufig in eingebetteten Systemgeschäften zu finden sind) eignen sich wahrscheinlich gut für das Verständnis der Gatter. Wer mit Toren arbeitet, sollte sich mit Quantenphysik auskennen. Und diese Quantenphysiker versuchen immer noch herauszufinden, was die nächste Abstraktion ist.
quelle
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 Montage denke. C oder C ++ bietet alle grundlegenden Konzepte, die in verwalteten Sprachen vollständig transparent sind, und Sie werden die meisten der auf dieser Seite erwähnten Konzepte mit einer der wichtigsten Sprachen verstehen, die Sie in Projekten der realen Welt verwenden können. Es ist ein echter Mehrwert für Ihre Programmierkenntnisse. Bitte beachten Sie, dass Assembly in sehr spezifischen Bereichen verwendet wird und nicht annähernd so nützlich ist wie C oder C ++.
Ich würde sogar noch weiter gehen und sagen, dass Sie nicht in die Versammlung eintauchen sollten, bevor Sie nicht verstanden haben, wie nicht verwaltete Sprachen funktionieren. Es ist fast eine Pflichtlektüre.
Sie sollten die Montage lernen, wenn Sie noch weiter nach unten wollen. Sie möchten wissen, wie genau jedes Konstrukt der Sprache erstellt wird. Es ist informativ, aber es ist eine ganz andere Komplexität.
quelle
Wenn Sie eine Sprache gut beherrschen, sollten Sie mindestens Grundkenntnisse der Technologie auf einer niedrigeren Abstraktionsebene haben.
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 anfangen, seltsame Abstürze oder eine schlechte Leistung zu erzielen, kann das Wissen über das Debuggen von C-Code sehr hilfreich sein, ebenso wie das Wissen über die Speicherverwaltungsmethode für das erneute Zählen. 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 Assembler-Kenntnisse einem erfahrenen Python-Entwickler nicht wirklich weiterhelfen (die Abstraktion geht zu weit zurück - alles, was in Python getan wird, würde zu vielen, vielen Assembler-Anweisungen führen).
..aber, wenn Sie mit C erfahren sind, dann wäre es in der Tat nützlich, "die nächste Ebene nach unten" (Assembly) zu kennen.
Ebenso ist es (sehr) nützlich, Javascript zu kennen, wenn Sie CoffeScript verwenden. Wenn Sie Clojure verwenden, sind Kenntnisse in Java / JVM hilfreich.
Diese Idee funktioniert auch außerhalb von Programmiersprachen. Wenn Sie Assembly verwenden, sollten Sie mit der Funktionsweise der zugrunde liegenden Hardware vertraut sein. 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
quelle
Schreiben Sie ein kleines c-Programm und zerlegen Sie die Ausgabe. Das ist alles. Seien Sie jedoch auf einen größeren oder geringeren 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 wollen, ohne dass die Komplexität eines Betriebssystems die Dinge kompliziert, versuchen Sie, ein Arduino in Assembler-Sprache zu programmieren .
quelle
Es gibt keine definitive Antwort, da Programmierer nicht alle von einem Typ sind. MÜSSEN Sie wissen, was sich darunter verbirgt? Wenn ja, dann lerne es. Wollen Sie es nur aus Neugier lernen? Wenn ja, dann lerne es. Wenn es Ihnen keinen praktischen Nutzen bringt, warum dann die Mühe machen? Braucht man das Wissen eines Mechanikers, um Auto zu fahren? Benötigt ein Mechaniker Kenntnisse eines Ingenieurs, nur um an einem Auto zu arbeiten? Dies ist eine ernsthafte Analogie. Ein Mechaniker kann ein sehr guter, produktiver Mechaniker sein, ohne ein tiefes Verständnis für die von ihm gewarteten Fahrzeuge zu haben. Gleiches gilt für Musik. Wollen 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 Dorian- und dem Lydian-Modus. Wenn du willst, okay, aber nein, musst du nicht. Wenn Sie ein Webentwickler sind, hat Assembly keinen praktischen Nutzen, den ich mir vorstellen kann. Wenn Sie sich in eingebetteten Systemen oder etwas wirklich Besonderem befinden, ist dies möglicherweise erforderlich, aber wenn dies der Fall wäre, würden Sie es wissen.
Hier ist Joels Sicht auf diesen Wert des Lernens einer nicht-übergeordneten Sprache: http://www.joelonsoftware.com/articles/ThePerilsofJavaSchools.html
quelle
Eigentlich wäre das Beste für Sie eine Klasse, die (meines Wissens) nirgendwo existiert: Es wäre eine Klasse, die einen kurzen Überblick über die Maschinensprache / Assemblersprache und die Speicheradressierungskonzepte mit einer Tour durch die Compilerkonstruktion kombiniert , Codegenerierung und Laufzeitumgebungen.
Das Problem ist, dass Sie mit einer hochentwickelten, von der Hardware weit entfernten Sprache wie C # oder Python die Tatsache nicht wirklich zu schätzen wissen, dass jede Bewegung, die Sie ausführen, zu Hunderten oder gar Tausenden von Maschinenanweisungen wird, und dass Sie keine Anweisungen geben Es ist nicht so einfach zu verstehen, wie einige Zeilen einer Hochsprache dazu führen können, dass große Mengen an Speicherplatz abgerufen und geändert werden. Es geht nicht so sehr darum, genau zu wissen, was "unter der Decke" vor sich geht, sondern darum, den Umfang des Geschehens zu verstehen und eine allgemeine Vorstellung davon zu haben, welche Arten von Dingen auftreten.
quelle
Meine Antwort auf diese Frage hat sich vor relativ kurzer Zeit entwickelt. Die vorhandenen Antworten decken das ab, was ich in der Vergangenheit gesagt hätte. Eigentlich wird dies immer noch von der Top-Antwort abgedeckt - dem Punkt "Schätzen Sie die Konstrukte in der übergeordneten Programmierung", aber es ist ein Sonderfall, den ich für erwähnenswert halte ...
Laut diesem Jeff Atwood-Blogbeitrag , der sich auf eine Studie bezieht, ist das Verständnis von Aufgaben ein zentrales Thema für das Verständnis von Programmierung. Lernende Programmierer verstehen entweder, dass die Notation nur die Schritte darstellt, denen der Computer folgt, und die Gründe für die Schritte, oder sie werden immer wieder durch irreführende Analogien zu mathematischen Gleichungen usw. verwirrt.
Nun, wenn Sie folgendes von 6502 Assembler verstehen ...
Das sind wirklich nur die Schritte. Wenn Sie dann lernen, das in eine Zuweisungsanweisung zu übersetzen ...
Sie brauchen keine irreführende Analogie zu einer mathematischen Gleichung - Sie haben bereits ein korrektes mentales Modell, auf das Sie es abbilden können.
BEARBEITEN - natürlich, wenn die Erklärung, die Sie erhalten,
LDA variable
im Grunde genommenACCUMULATOR = variable
genau die ist, die Sie aus einigen Tutorials und Referenzen erhalten, landen Sie wieder dort, wo Sie begonnen haben, und es ist überhaupt keine Hilfe.Ich lernte 6502 Assembler als meine zweite Sprache, die erste war Commodore Basic, und ich hatte damals nicht wirklich viel davon gelernt - zum Teil, weil es so wenig zu lernen gab, aber auch, weil Assembler damals einfach so viel interessanter wirkte . Teilweise die Zeiten, teilweise, weil ich ein 14-jähriger Aussenseiter war.
Ich empfehle nicht, das zu tun, was ich getan habe, aber ich frage mich, ob das Studium einiger sehr einfacher Beispiele in einer sehr einfachen Assemblersprache eine lohnende Voraussetzung für das Erlernen von höheren Sprachen sein könnte.
quelle
Wenn Sie kein Compiler-Schreiber sind oder etwas hochoptimiertes (wie einen Datenverarbeitungsalgorithmus) benötigen, bietet das Erlernen der Assembly-Codierung keine Vorteile.
Das Schreiben und Verwalten von Code, der in Assembler geschrieben wurde, ist sehr schwierig. Daher sollten Sie ihn nicht verwenden, auch wenn Sie die Assemblersprache sehr gut beherrschen, 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 Baugruppe gehen. Dem Autor ist es gelungen, den Algorithmus von 100 Zyklen / Vektor auf 17 Zyklen / Vektor zu optimieren.
quelle
Das Schreiben in Assembler 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 den 70er und 80er Jahren ausgelesenen) Prozessoren liefert die Baugruppe nicht genügend Details, um zu wissen, was vor sich geht (das heißt, bei den meisten Prozessoren). Moderne PUs (CPUs und GPUs) sind in Bezug auf Terminierungsanweisungen recht komplex. Wenn Sie die Grundlagen der Assemblierung (oder Pseudoassemblierung) kennen, können Sie Bücher / Kurse zur Computerarchitektur verstehen, die weitere Kenntnisse vermitteln (Caches, nicht ordnungsgemäße Ausführung, MMU usw.). Normalerweise müssen Sie keine komplexen ISA-Kenntnisse haben, um sie zu verstehen (MIPS 5 ist ein sehr beliebtes IIRC).
Warum Prozessor verstehen? Es könnte Ihnen viel mehr Verständnis geben, was los ist. Angenommen, Sie schreiben die Matrixmultiplikation auf naive Weise:
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 einige wichtige Programme, mit denen Sie massive Arrays kompilieren - wie können Sie sie optimieren? Wenn Sie den Code in Assembler schreiben, können Sie einige Prozent der Verbesserungen erzielen (es sei denn, Sie würden wie die meisten anderen tun - auch auf naive Weise, wenn Sie die Register nicht ausnutzen, ständig in den Speicher laden / speichern und tatsächlich ein langsameres Programm als in HL-Sprache haben). .
Sie können jedoch die Zeilen umkehren und die Leistung auf magische Weise steigern (warum? Ich lasse es als "Hausaufgabe") - IIRC kann in Abhängigkeit von verschiedenen Faktoren für große Matrizen sogar das 10-fache betragen.
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 können es sogar in umwandeln (Entschuldigung - ich schreibe Blockieren aus dem Speicher):
Zusammenfassend lässt sich sagen, dass Sie mit den Grundlagen einer Baugruppe verschiedene Details aus dem Prozessordesign kennenlernen können, mit denen Sie schnellere Programme schreiben können. Es kann hilfreich sein, die Unterschiede zwischen den Architekturen RISC / CISC oder VLIW / Vektorprozessor / SIMD / ... zu kennen. Allerdings würde ich nicht mit x86 anfangen, da sie in der Regel recht kompliziert sind (möglicherweise auch ARM) - zu wissen, was ein Register usw. ist, reicht meiner Meinung nach für den Start aus.
quelle
Normalerweise ist es für das Debuggen SEHR wichtig. Was tun Sie, wenn das System mitten in einer Anweisung abbricht und der Fehler keinen Sinn ergibt? Bei .NET-Sprachen ist das weitaus weniger ein Problem, solange Sie nur sicheren Code verwenden - das System schützt Sie fast immer vor den Vorgängen unter der Haube.
quelle
Kurz gesagt, ich denke, die Antwort liegt darin, dass Sie mehr tun können, wenn Sie Montage lernen. Das Erlernen der Assemblierung ermöglicht den Zugriff auf die Bereiche Programmierung eingebetteter Geräte, Eindringen in die Sicherheit und Umgehung, Reverse Engineering und Systemprogrammierung, die nur schwer zu handhaben sind, wenn Sie keinen Assembler kennen.
Das Erlernen, um die Programmleistung zu verbessern, ist bei der Anwendungsprogrammierung zweifelhaft. Meistens gibt es so viele Dinge, auf die Sie sich konzentrieren müssen, bevor Sie diese Optimierungsstufe erreichen, wie beispielsweise die Optimierung Ihres E / A-Zugriffs auf Festplatte und Netzwerk, die Optimierung der GUI-Erstellung, die Auswahl der richtigen Algorithmen und die Maximierung aller Kerne Wenn Sie mit der besten Hardware arbeiten, die Sie für Geld kaufen können, wechseln Sie von interpretierten zu kompilierten Sprachen. Wenn Sie keine Software für andere Endbenutzer erstellen, ist die Hardware im Vergleich zum Stundenlohn eines Programmierers günstig, insbesondere bei Cloud-Verfügbarkeit.
Außerdem müssen Sie die Programmausführungsgeschwindigkeit mit der Lesbarkeit Ihres Codes abwägen, nachdem Sie von einem Bus angefahren wurden, beenden oder zur Codebasis zurückkehren, um sie ein Jahr nach dem Schreiben der letzten Version zu ändern.
quelle
Ich würde Lernalgorithmen empfehlen: Sortieren, verknüpfte Listen, binäre Bäume, Hashing usw.
Lernen Sie auch lisp, siehe Struktur und Interpretation von Computerprogrammen groups.csail.mit.edu/mac/classes/6.001/abelson-sussman-lectures. In diesem Videokurs lernen Sie alles, was Sie wissen müssen, einschließlich Algorithmen (wie man alles basierend auf ein paar primitive Befehle, ein lisp-Primitiv und einige Assembler-Provokationen).
Schließlich, wenn Sie Assembler lernen müssen, lernen Sie ein einfaches wie ARM (auch wird es in ungefähr 4-mal mehr Geräten als x86 verwendet).
quelle
Nun, die Antwort ist, dass nur, weil die Sprache, die Sie verwenden, am Ende interpretiert oder in Assembler kompiliert werden muss. Egal in welcher Sprache oder auf welcher Maschine.
Das Design der Sprachen ergibt sich aus der Funktionsweise der CPU. Mehr bei Low-Level-Programmen, weniger bei High-Level-Programmen.
Abschließend möchte ich sagen, dass Sie nicht nur den kleinen Assembler kennen müssen, sondern auch die CPU-Architektur, die Sie durch das Erlernen des Assemblers erlernen.
Einige Beispiele: Es gibt viele Java-Programmierer, die nicht verstehen, warum dies nicht funktioniert, und noch weniger als wissen, was passiert, wenn Sie es ausführen.
Wenn Sie einen kleinen Assembler kennen würden, würden Sie immer wissen, dass der Inhalt eines Speicherorts nicht mit der Nummer in der Zeigervariablen übereinstimmt, die auf diesen Speicherort "verweist".
Schlimmer noch, selbst in veröffentlichten Büchern liest man so etwas wie in JAVA. Primitive werden nach Wert und Objekte nach Referenz übergeben, was völlig falsch ist. Alle Argumente in Java werden als Wert übergeben, und Java kann KEINE Objekte an Funktionen übergeben, nur Zeiger, die als Wert übergeben werden.
Wenn Sie jetzt wissen, was los ist, ist es so kompliziert zu erklären, dass die meisten Autoren Sie nur mit einer frommen Lüge belügen.
Die Konsequenzen sind natürlich subtil, können Sie aber später in echte Schwierigkeiten bringen. Wenn Sie wissen, dass Assembler kein Problem ist, steht Ihnen eine lange, lange Nacht des Debuggens bevor.
quelle
String a = "X"; String b = "X"; if( a==b) return true;
dem,== true
wasString interning
der Compiler tatsächlich tut, wegen etwas , das er nennt. Alle anderen Java-Anweisungen sind ebenfalls falsch. Java hat keine Zeiger, es hat Referenzen, die nicht dasselbe sind. Und nichts davon hat in irgendeiner Weise etwas mit Assembler zu tun. Java übergibt Primitive nach Wert sowie Referenzen nach Wert. Java hat keine Zeiger und kann sie daher nicht weitergeben. Wieder alles irrelevant, um ASM zu kennen.