Sollte ich versuchen, Übungsprobleme bei der Montage zu lösen? [geschlossen]


9

Ich habe mir Project Euler Problem 48 angesehen :

Die Reihe 1 1 + 2 2 + 3 3 + ... + 10 10 = 10405071317.

Finden Sie die letzten zehn Ziffern der Reihe, 1 1 + 2 2 + 3 3 + ... + 1000 1000 .

In Python kann ich dies mit einer einzigen Zeile tun:

sum((x**x for x in xrange(1,1001))

Das Montageäquivalent dazu wäre jedoch 100 Zeilen und eine echte Herausforderung.

Sollte ich einige dieser Rätsel in der Montage lösen, um einen Einblick in die Programmierung auf niedriger Ebene zu erhalten und zu verstehen, wie der Computer tatsächlich funktioniert?


2
Wenn Sie nicht wissen, wie Speicher funktioniert, wie können Sie dann mit Themen wie Zeigern umgehen? Wenn Sie nicht verstehen, wie ein Computer und ein Betriebssystem funktionieren, wie können Sie eine Anwendung programmieren?
Ramhound

Ich kann viele Abstraktionen machen, Ramhound, deshalb habe ich dich das gefragt. Ich bekomme möglicherweise nicht den vollen Überblick über Zeiger, die noch in der Lage sind, Zeiger wie das Austauschen auszuführen, was logisch sinnvoll ist, wenn Sie davon ausgehen, dass Zeiger den Speicherort eines anderen Datentyps speichern Themen, die ich lesen sollte? Assemblersprache und ein bisschen COA wären gut?
Nishant

Wenn Sie nicht alle Zeiger in den Griff bekommen, werden Sie feststellen, dass dies an einigen Stellen ein schwerwiegender Nachteil ist.
David Thornley

3
Entweder berechnet Ihre Python-Zeile x ^ 2 für x in 1..1000 (anstelle von x ^ x für x in 1..1000) oder Python ist noch magischer als ich dachte. :)
Ingo

Ist die Funktion "Erhöhen auf die Macht von" *in Python?

Antworten:


1

Über das Lernen von Assembler hinaus glaube ich, dass das Lernen, wie eine einfache Sprache wie C kompiliert wird, sehr wertvoll ist. Meine Antwort lautet also ja, aber andererseits bin ich wahrscheinlich voreingenommen, weil ich gerne auf niedriger Ebene programmiere.

Zum Beispiel nur verstehen, wie einfache Anweisungen kompiliert werden. Die folgende Funktion:

int func(int val)
{
  int num = val * 5;
  return num;
}

... wird (zumindest das interessante Stück):

movl    %edi, -20(%rbp)
movl    -20(%rbp), %edx
movl    %edx, %eax
sall    $2, %eax
addl    %edx, %eax

Dieser Code nimmt das Argument aus dem Stapel (val, der Parameter zu func), verschiebt es um die linken 2 Stellen (multipliziert mit 2 ^ 2 oder 4) und addiert dann den ursprünglichen Wert zum Ergebnis. Das Endergebnis ist eine Multiplikation mit 5. Ein Beispiel wie dieses zeigt eine Reihe von Dingen, die Sie beachten sollten, z. B. Compiler-Optimierungen. Anstatt eine Anweisung zum direkten Multiplizieren mit 5 aufzurufen, werden zwei Stellen zum Multiplizieren mit 4 verschoben und dann der ursprüngliche Wert addiert. Ich habe Beispiele wie dieses gefunden, um mein Verständnis der Dinge auf einer niedrigeren Ebene erheblich zu verbessern.

Generieren Sie mit der -SOption eine Assembler-Ausgabe von gcc . Beachten Sie jedoch, dass die Ergebnisse je nach Compiler und Optimierungsstufe variieren.

Wie auch immer, ich denke nicht, dass es dasselbe ist, Assembler-Programmierer zu sein, wie Assembler zu verstehen . Auch hier halte ich das Programmieren in einer Sprache wie C und das Wissen, wie es in Maschinencode eingefügt wird, für eine wertvolle Praxis.


11

Wahrscheinlich nicht notwendig, um tatsächlich Assembler schreiben zu können (die meisten davon sind Details der Initialisierungs- und Aufrufkonvention für Ihr System).

Es lohnt sich, einige zu verstehen, falls Sie versuchen, etwas ohne Quelle zu debuggen.

ABER es lohnt sich auf jeden Fall, die Maschine zumindest auf der Ebene von 'C' und Zeigern (im Wesentlichen ein Assembler auf hoher Ebene) zu verstehen, damit Sie wissen, warum es schlecht ist, eine Zeichenfolge millionenfach in einer Schleife zu verknüpfen.


Tatsächlich können einige relativ clevere Implementierungen for i in range(1000000): s = s + '.'nicht (nicht viel) schlechter machen als die "optimierten" Versionen, die ich wieder verwende s. In ähnlicher Weise machen mehrere andere Entwicklungen eine vernünftige Annahme mit C-Wissen und eine naive Implementierung ungültig. Aber im Allgemeinen ist es eher nützlich als schädlich. Denken Sie daran, dass

2
@delnan -Ich brauchte nur ein kurzes Beispiel dafür, wo etwas, das in Java / C # harmlos aussieht, auf Silizium sehr teuer sein könnte. Ich bin besonders auf viele Leute gestoßen, die denken, dass eine große Speicherzuweisung und Kopie sofort erfolgt.
Martin Beckett

Ich hasse es zu glauben, dass Delnan :-)
Nishant

5

Gute Frage. Assembly lernen ist auf jeden Fall gut und die Mühe wert.

  1. Ein derart geringes Verständnis wird bei der Entwicklung eingebetteter Software von Nutzen sein
  2. Refactoring auf niedrigem Niveau
  3. Es wird Ihnen helfen, den Debugger effektiv zu nutzen
  4. Geben Sie Ihnen ein Verständnis für zerlegten Code, um in Sachen Code-Höhlen zu helfen

2
Ich musste Codecaves nachschlagen. Ich benutze diese oft, aber wir nennen sie jetzt "Umwege". research.microsoft.com/en-us/projects/detours
ProdigySim

1

Ja und nein.

Es ist zwar richtig, dass Sie dadurch besser verstehen, was Ihr Code tut und warum manche Dinge nur eine schlechte Idee sind, aber Sie müssen über den Aufwand nachdenken.

Das Erlernen von Assembler ist kein Wochenendprojekt, es wird viel Zeit in Anspruch nehmen und Sie müssen sich überlegen, ob diese Zeit besser genutzt werden könnte oder nicht.

Wenn Sie sich nicht für optimierten Code interessieren, werden Sie wahrscheinlich nie Vorteile sehen, die dem Aufwand entsprechen, den Sie investieren.


1

Ich habe viel Assembler gemacht, als ich jünger war, und ich glaube nicht, dass es geholfen hat, etwas außerhalb des Assemblers zu verstehen. Wenn Sie sich einen modernen Assembler ansehen, ist das sowieso alles in Makrosprache. Normalerweise hasse ich Analogien, aber hier ist es trotzdem: Macht es Sie zu einem besseren Fahrer, wenn Sie wissen, wie der Motor eines Autos funktioniert?


Macht es Sie zu einem besseren Fahrer, zu wissen, wie der Motor eines Autos funktioniert? Nein, aber es macht Sie zu einem besseren Autobesitzer, denn wenn der Motor ausfällt, können Sie ihn reparieren.
Cameron Martin

Einverstanden, aber es macht Sie nicht zu einem besseren Fahrer, was die Analogie ist, die ich verwendet habe. Indem Sie den Motor selbst reparieren, unterstützen Sie die allgemeine Wirtschaft nicht durch den Einsatz von Mechanikern. Analogien haben Grenzen. Im Allgemeinen würde ich niemals jemanden davon abhalten, etwas zu lernen, wenn er interessiert ist, aber ich denke, Sie müssen ziemlich tief in das Kaninchenloch vordringen, um es sinnvoll auf höhere Sprachen anwenden zu können. Zunächst müssen Sie die Kompilierungsoptimierungen verstehen, die von der jeweiligen Sprache verwendet werden, wenn sie kompiliert ist, oder den Interpreter oder den Jitter. Es ist ein riesiges Gebiet.
Ian

1

Ich habe daran gearbeitet, Assembler zu verstehen, indem ich Programme in höheren Sprachen geschrieben und dann Teile durch (zumindest hoffentlich) funktional äquivalente Teile des zusammengesetzten Codes ersetzt habe. Dies bedeutet, dass ich HLLs verwenden kann, um Probleme auf hoher Ebene zu organisieren und zu lösen, und ich verwende asm, um das Metall zu schlagen.

(Wenn ich über das Host-Programm spreche, das in einer HLL geschrieben wird, meine ich C oder ObjC, wenn ich versuche, x86_64 asm zu lernen, und BASIC, wenn ich an Z80, 6502 und 6809 asm arbeite).

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.