web-dev-qa-db-fra.com

Comment l'apprentissage de l'assemblage aide-t-il à la programmation?

Je programme dans des langages de plus haut niveau (Python, C #, VBA, VB.NET) depuis environ 10 ans et je n'ai aucune compréhension de ce qui se passe "sous le capot".

Je me demande quels sont les avantages de l'apprentissage de l'assemblage et comment cela m'aidera-t-il en tant que programmeur? Pouvez-vous me fournir une ressource qui me montrera exactement le lien entre ce que j'écris dans un code de niveau supérieur et ce qui se passe dans l'assemblage?

Parce que vous comprendrez comment cela fonctionne vraiment.

  • Vous comprendrez que les appels de fonction ne sont pas gratuits et pourquoi la pile d'appels peut déborder (par exemple, dans les fonctions récursives). Vous comprendrez comment les arguments sont transmis aux paramètres de la fonction et comment les effectuer (copie de la mémoire, pointage vers la mémoire).
  • Vous comprendrez que la mémoire n'est pas gratuite et à quel point la gestion automatique de la mémoire est précieuse. La mémoire n'est pas quelque chose que vous "venez d'avoir", en réalité elle doit être gérée, prise en charge et surtout, pas oubliée (car vous devez la libérer vous-même).
  • Vous comprendrez comment fonctionne le flux de contrôle au niveau le plus fondamental.
  • Vous apprécierez davantage les constructions dans les langages de programmation de niveau supérieur.

Cela revient à dire que toutes les choses que nous écrivons en C # ou Python doivent être traduites en une séquence d'actions de base qu'un ordinateur peut exécuter. Il est facile de penser à un ordinateur en termes de classes, de génériques et de listes de compréhension mais ceux-ci n'existent que dans nos langages de programmation de haut niveau.

Nous pouvons penser à des constructions de langage qui ont l'air vraiment sympa mais qui ne se traduisent pas très bien par une manière de faire de bas niveau. En sachant comment cela fonctionne vraiment, vous comprendrez mieux pourquoi les choses fonctionnent comme elles le font.

188
Simeon Visser

Il vous donnera une meilleure compréhension de ce qui se passe "sous le capot" et du fonctionnement des pointeurs et de la signification des variables et de l'architecture des registres (allocation et gestion de la mémoire, passage des paramètres (par valeur/par référence), etc.) en général.

Pour un coup d'œil rapide avec C, comment ça se passe?

#include <stdio.h>

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

compiler avec gcc -S so.c et jetez un œil à la sortie de l'assembly dans 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

Je pense que la réponse que vous cherchez est ici: http://www.codeproject.com/Articles/89460/Why-Learn-Assembly-Language

Une citation de l'article:

Bien que ce soit vrai, vous ne vous trouverez probablement pas en train d'écrire l'application de votre prochain client dans Assembly, il y a encore beaucoup à gagner à apprendre Assembly. Aujourd'hui, le langage d'assemblage est utilisé principalement pour la manipulation directe du matériel, l'accès à des instructions de processeur spécialisées ou pour résoudre des problèmes de performances critiques. Les utilisations typiques sont les pilotes de périphériques, les systèmes embarqués de bas niveau et les systèmes en temps réel.

Le fait est que plus les langages de haut niveau deviennent complexes et plus les ADT (types de données abstraits) sont écrits, plus les frais généraux sont supportés pour supporter ces options. Dans les cas de .NET, MSIL peut-être gonflé. Imaginez si vous connaissiez MSIL. C'est là que le langage de l'Assemblée brille.

Le langage d'assemblage est aussi proche du processeur que possible en tant que programmeur, donc un algorithme bien conçu est flamboyant - L'assemblage est idéal pour optimiser la vitesse. C'est une question de performance et d'efficacité. Le langage d'assemblage vous donne un contrôle complet sur les ressources du système. Tout comme une ligne d'assemblage, vous écrivez du code pour pousser des valeurs uniques dans des registres, vous traitez les adresses mémoire directement pour récupérer des valeurs ou des pointeurs.

Écrire dans Assembly, c'est comprendre exactement comment le processeur et la mémoire fonctionnent ensemble pour "faire bouger les choses". Soyez averti, le langage d'assemblage est cryptique et la taille du code source des applications est beaucoup plus grande que celle d'un langage de haut niveau. Mais ne vous y trompez pas, si vous êtes prêt à consacrer du temps et des efforts pour maîtriser l'assemblage, vous vous améliorerez et vous deviendrez un acteur hors du commun.

De plus, je recommanderais ce livre car il a une version simplifiée de l'architecture informatique: Introduction to Computing Systems: From Bits and Gates to C and Beyond, 2/e Yale N. Patt, University of Texas at Austin Sanjay J. Patel, Université de l'Illinois à Urbana/Champaign

30
Brynne

À mon humble avis, cela n'aide pas beaucoup.

Je connaissais très bien l'assemblage x86. Cela a un peu aidé lorsque Assembly est apparu dans mes cours, il est apparu une fois lors d'une interview, et cela m'a aidé à prouver qu'un compilateur (Metrowerks) générait un mauvais code. C'est fascinant de voir comment l'ordinateur fonctionne réellement, et je me sens intellectuellement plus riche pour l'avoir appris. C'était aussi très amusant de jouer avec à l'époque.

Cependant, les compilateurs d'aujourd'hui sont mieux à même de générer des assemblys que presque n'importe qui sur presque n'importe quel morceau de code. À moins d'écrire un compilateur ou de vérifier que votre compilateur fait la bonne chose, vous perdez probablement votre temps en l'apprenant.

J'admets que de nombreuses questions que les programmeurs C++ posent encore utilement sont éclairées par la connaissance de Assembly. Par exemple: dois-je utiliser des variables de pile ou de tas? dois-je passer par valeur ou par référence const? Dans presque tous les cas, cependant, je pense que ces choix devraient être faits en fonction de la lisibilité du code plutôt que des gains de temps de calcul. (Par exemple, utilisez des variables de pile chaque fois que vous souhaitez limiter une variable à une étendue.)

Ma modeste suggestion est de se concentrer sur les compétences qui comptent vraiment: la conception de logiciels, l'analyse d'algorithmes et la résolution de problèmes. Avec de l'expérience dans le développement de grands projets, votre intuition s'améliorera, ce qui augmentera votre valeur bien plus que de connaître l'assemblage (à mon avis).

22
Neil G

Vous devez être familier avec un niveau "plus profond" du système sur lequel vous travaillez. Sauter trop loin en une seule fois n'est pas mauvais, mais peut ne pas être aussi utile qu'on le souhaiterait.

Un programmeur dans un langage de haut niveau devrait apprendre un langage de niveau inférieur (C est une excellente option). Vous n'avez pas besoin d'aller jusqu'à Assembly pour apprécier ce qui se passe sous les couvertures lorsque vous dites à l'ordinateur d'instancier un objet ou de créer une table de hachage ou un ensemble, mais vous devriez pouvoir coder leur.

Pour un programmeur Java, l'apprentissage d'un certain C vous aiderait à gérer la mémoire et à passer des arguments. L'écriture de la vaste bibliothèque Java en C permettrait de comprendre quand utiliser quelle implémentation de Set (voulez-vous un hachage? ou un arbre?). La manipulation de char * dans un environnement fileté aidera à comprendre pourquoi String est immuable.

Passé au niveau suivant ... Un programmeur C devrait avoir une certaine familiarité avec l'assemblage, et les types d'assemblage (souvent trouvés dans les magasins de systèmes embarqués) feraient probablement bien de comprendre les choses au niveau des portes. Ceux qui travaillent avec des portes devraient connaître la physique quantique. Et ces physiciens quantiques, eh bien, ils essaient toujours de comprendre quelle est la prochaine abstraction.

21
user40980

Puisque vous n'avez pas mentionné C ou C++ dans la liste des langages que vous connaissez. Je recommanderais FORTEMENT de bien les apprendre avant même de penser à l'Assemblée. C ou C++ donnera tous les concepts de base qui sont totalement transparents dans les langages managés et vous comprendrez la plupart des concepts mentionnés dans cette page avec l'un des langages les plus importants que vous pourriez utiliser dans des projets du monde réel. C'est une réelle valeur ajoutée à vos compétences en programmation. Veuillez noter que Assembly est utilisé dans des domaines très spécifiques et qu'il n'est pas aussi utile que C ou C++.

J'irais même plus loin pour dire que vous ne devriez pas plonger à l'Assemblée avant de comprendre comment fonctionnent les langues non gérées. C'est presque une lecture obligatoire.

Vous devriez apprendre l'assemblage si vous voulez aller encore plus loin. Vous voulez savoir exactement comment chaque construction du langage est créée. C'est informatif mais c'est une complexité de niveau très différent.

5
AhHatem

Si vous connaissez bien une langue, vous devez avoir au moins une connaissance de base de la technologie un niveau d'abstraction plus bas.

Pourquoi? Lorsque les choses tournent mal, la connaissance des mécanismes sous-jacents facilite le débogage de problèmes étranges et permet naturellement d'écrire du code plus efficace

En utilisant Python (/ CPython) comme exemple, si vous commencez à avoir des plantages bizarres ou de mauvaises performances, la connaissance du débogage du code C peut être très utile, de même que la connaissance de sa méthode de gestion de la mémoire de comptage des références. Cela vous aiderait également à savoir quand/si écrire quelque chose en tant qu'extension C, etc.

Pour répondre à votre question dans ce cas, la connaissance de Assembly n'aiderait vraiment pas un développeur expérimenté Python (c'est trop d'étapes vers le bas dans l'abstraction - tout ce qui se fait dans Python = entraînerait de nombreuses instructions d'assemblage)

..mais, si vous êtes expérimenté avec C, alors connaître "le prochain niveau" (Assemblage) serait en effet utile.

De même, si vous utilisez CoffeScript, il est (très) utile de connaître Javascript. Si vous utilisez Clojure, la connaissance de Java/JVM est utile.

Cette idée fonctionne également en dehors des langages de programmation - si vous utilisez Assembly, c'est une bonne idée de vous familiariser avec le fonctionnement du matériel sous-jacent. Si vous êtes un concepteur Web, c'est une bonne idée de savoir comment l'application Web est mise en œuvre. Si vous êtes mécanicien automobile, c'est une bonne idée d'avoir une certaine connaissance de la physique

5
dbr

Écrivez un petit programme c et démontez la sortie. C'est tout. Cependant, préparez-vous à un degré plus ou moins élevé de code "d'entretien ménager" qui est ajouté au profit du système d'exploitation.

L'assemblage vous aide à comprendre ce qui se passe sous le capot car il traite directement avec la mémoire, les registres du processeur et autres.

Si vous voulez vraiment aller au bare-metal sans toute la complexité d'un système d'exploitation compliquant les choses, essayez de programmer un Arduino en langage assembleur.

3
Robert Harvey

Il n'y a pas de réponse définitive, car les programmeurs ne sont pas tous d'un type. AVEZ-VOUS BESOIN de savoir ce qui se cache en dessous? Si oui, apprenez-le. voulez-vous simplement l'apprendre, par curiosité? Si oui, apprenez-le. Si cela ne vous procurera aucun avantage pratique, pourquoi vous en préoccuper? A-t-on besoin du niveau de connaissance d'un mécanicien juste pour conduire une voiture? Un mécanicien a-t-il besoin du niveau de connaissance d'un ingénieur, juste pour travailler sur une voiture? C'est une sérieuse analogie. Un mécanicien peut être un très bon mécanicien productif sans plonger pour comprendre en profondeur les véhicules qu'il entretient. Pareil pour la musique. Avez-vous vraiment à sonder les complexités de la mélodie, de l'harmonie et du rythme pour être un bon chanteur ou joueur? Non. Certains musiciens exceptionnellement talentueux ne peuvent pas lire un morceau de partitions, et encore moins vous faire la différence entre les modes Dorian et Lydian. Si vous le voulez bien, mais non, vous n'en avez pas besoin. Si vous êtes un développeur Web, Assembly n'a aucune utilité pratique à laquelle je peux penser. Si vous êtes dans des systèmes embarqués ou quelque chose de vraiment spécial, cela pourrait être nécessaire, mais si c'était le cas, vous le sauriez.

Voici le point de vue de Joel sur ces valeurs de s'appuyer sur un langage non de haut niveau: http://www.joelonsoftware.com/articles/ThePerilsofJavaSchools.html

3
GrayFox374

En fait, ce qui serait probablement le mieux pour vous serait une classe qui n'existe (à ma connaissance) nulle part: Ce serait une classe qui combine un bref aperçu du langage machine/assembleur et des concepts d'adressage de stockage avec une visite guidée de la construction du compilateur , génération de code et environnements d'exécution.

Le problème est qu'avec un langage de haut niveau, loin du matériel comme C # ou Python vous n'appréciez pas vraiment le fait que chaque mouvement que vous faites se transforme en centaines si pas des milliers d'instructions machine, et vous n'avez pas tendance à comprendre comment quelques lignes d'un langage de haut niveau peuvent entraîner l'accès et la modification de vastes quantités de stockage. Ce n'est pas tellement que vous devez savoir précisément ce qui se passe "sous les couvertures", mais vous devez avoir une appréciation de la portée de ce qui se passe, et une conception générale des types de choses qui se produisent.

2
Daniel R Hicks

Ma réponse à cette question a évolué relativement récemment. Les réponses existantes couvrent ce que j'aurais dit dans le passé. En fait, cela est toujours couvert par le point réponse du haut - le "apprécie les constructions dans la programmation de niveau supérieur", mais c'est un cas spécial qui, je pense, mérite d'être mentionné ...

Selon cet article de blog de Jeff Atwood , qui fait référence à une étude, la compréhension de l'affectation est un problème clé pour comprendre la programmation. Les programmeurs apprenants comprennent que la notation ne représente que les étapes que l'ordinateur suit et raisonne par les étapes, ou bien ils sont perpétuellement confus par des analogies trompeuses avec des équations mathématiques, etc.

Eh bien, si vous comprenez ce qui suit de l'assembleur 6502 ...

LDA variable
CLC
ADC #1
STA variable

Ce ne sont vraiment que les étapes. Ensuite, lorsque vous apprenez à traduire cela en une déclaration d'affectation ...

variable = variable + 1;

Vous n'avez pas besoin d'une analogie trompeuse avec une équation mathématique - vous avez déjà un modèle mental correct pour le mapper.

[~ # ~] éditez [~ # ~] - bien sûr si l'explication que vous obtenez de LDA variable est essentiellement ACCUMULATOR = variable, qui est exactement ce que vous obtenez de certains tutoriels et références, vous vous retrouvez là où vous avez commencé et ce n'est pas du tout utile.

J'ai appris l'assembleur 6502 comme deuxième langue, la première étant Commodore Basic, et je n'en avais pas vraiment appris beaucoup à l'époque - en partie parce qu'il y avait si peu à apprendre, mais aussi parce que l'assembleur semblait tellement plus intéressant à l'époque. . En partie les fois, en partie parce que j'étais un geek de 14 ans.

Je ne recommande pas de faire ce que j'ai fait, mais je me demande si l'étude de quelques exemples très simples dans un langage assembleur très simple pourrait être un préalable utile à l'apprentissage de langages de niveau supérieur.

1
Steve314

L'écriture dans Assembly ne vous donnerait pas une augmentation magique de la vitesse, car en raison de la quantité de détails (allocation des registres, etc.), vous écrirez probablement l'algorithme le plus trivial de tous les temps.

De plus, avec les processeurs modernes (lus - conçus après les années 70-80), Assembly ne vous donnera pas suffisamment de détails pour savoir ce qui se passe (c'est-à-dire sur la plupart des processeurs). Moderne PU (CPU et GPU) sont assez complexes en ce qui concerne les instructions de planification. Connaître les bases de l'assemblage (ou pseudo-assemblage) permettra de comprendre les livres/cours d'architecture informatique qui fourniraient des connaissances supplémentaires (caches , exécution dans le désordre, MMU etc.). Habituellement, vous n'avez pas besoin de connaître la complexité ISA pour les comprendre (MIPS 5 est assez populaire) IIRC).

Pourquoi comprendre le processeur? Cela pourrait vous permettre de mieux comprendre ce qui se passe. Disons que vous écrivez la multiplication matricielle de manière naïve:

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]

Il peut être "assez bon" pour votre objectif (s'il s'agit d'une matrice 4x4, il peut être compilé de toute façon en instructions vectorielles). Cependant, il existe des programmes assez importants lorsque vous compilez des tableaux massifs - comment les optimiser? Si vous écrivez le code dans Assembly, vous pourriez avoir quelques% d'amélioration (à moins que vous ne fassiez comme la plupart des gens - également de manière naïve, sous-utilisant les registres, chargeant/stockant en mémoire constamment et ayant en fait un programme plus lent qu'en langage HL) .

Cependant, vous pouvez inverser les lignes et gagner en performance comme par magie (pourquoi? Je le laisse comme "devoir") - IIRC selon divers facteurs pour les grandes matrices, il peut même être 10x.

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]

Cela dit - des compilateurs travaillent sur le fait de pouvoir le faire ( graphite pour gcc et Polly pour tout ce qui utilise LLVM). Ils sont même capables de le transformer en (désolé - j'écris le blocage de la mémoire):

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]

Pour résumer - connaître les bases d'un assemblage vous permet de creuser dans divers "détails" de la conception du processeur qui vous permettraient d'écrire des programmes plus rapides. Il peut être utile de connaître les différences entre les architectures RISC/CISC ou VLIW/processeur vectoriel/SIMD/.... Cependant, je ne commencerais pas avec x86 car ils ont tendance à être assez compliqués (peut-être ARM aussi) - savoir ce qu'est un registre, etc. est à mon humble avis suffisant pour commencer.

0
Maciej Piechotka

Sauf si vous êtes un rédacteur de compilateur ou si vous avez besoin de quelque chose de hautement optimisé (comme un algorithme de traitement des données), l'apprentissage du codage d'assemblage ne vous procurera aucun avantage.

Écrire et maintenir du code écrit dans Assembly est très difficile, donc même si vous connaissez très bien le langage assembleur, vous ne devriez pas l'utiliser, sauf s'il n'y a pas d'autres moyens.

L'article " Optimisation pour SSE: une étude de cas " montre ce qu'il est possible de faire si vous accédez à Assembly. L'auteur a réussi à optimiser l'algorithme de 100 cycles/vecteur à 17 cycles/vecteur.

0
BЈовић