web-dev-qa-db-fra.com

Pourquoi les identifiants courts cryptiques sont-ils encore si courants dans la programmation de bas niveau?

Il y avait de très bonnes raisons de garder les instructions/registres courts. Ces raisons ne s'appliquent plus, mais les noms cryptiques courts sont encore très courants dans la programmation de bas niveau.

Pourquoi est-ce? Est-ce simplement parce que les vieilles habitudes sont difficiles à briser, ou y a-t-il de meilleures raisons?

Par exemple:

  • Atmel ATMEGA32U2 (2010?): TIFR1 (au lieu de TimerCounter1InterruptFlag), ICR1H (au lieu de InputCapture1High), DDRB (au lieu de DataDirectionPortB), etc.
  • Jeu d'instructions .NET CLR (2002): bge.s (au lieu de branch-if-greater-or-equal.short), etc.

Les noms plus longs et non cryptiques ne sont-ils pas plus faciles à utiliser?


Lorsque vous répondez et votez, veuillez tenir compte des éléments suivants. Bon nombre des explications possibles suggérées ici s'appliquent également à la programmation de haut niveau, et pourtant le consensus, dans l'ensemble, est d'utiliser des noms non cryptiques consistant en un mot ou deux (acronymes généralement compris exclus) .

De plus, si votre argument principal concerne espace physique sur un diagramme papier, veuillez considérer que cela ne s'applique absolument pas au langage d'assemblage ou au CIL, et j'apprécierais si vous me montriez un diagramme où les noms concis correspondent mais ceux lisibles aggravent le diagramme. D'après leur expérience personnelle dans une entreprise de semi-conducteurs sans usine, les noms lisibles conviennent parfaitement et donnent des diagrammes plus lisibles.

Quelle est la chose principale qui est différente au sujet de la programmation de bas niveau par opposition aux langages de haut niveau qui rend les noms cryptiques laconiques désirables dans programmation de bas niveau mais pas de haut niveau?

68
Roman Starkov

Il y a tellement d'idées différentes ici. Je ne peux accepter aucune des réponses existantes comme la réponse : premièrement, il y a probablement de nombreux facteurs qui y contribuent, et deuxièmement, je ne peux pas peut-être savoir lequel est le plus important.

Voici donc un résumé des réponses publié par d'autres ici. Je poste ceci comme CW et mon intention est de le marquer éventuellement comme accepté. Veuillez modifier si j'ai oublié quelque chose. J'ai essayé de reformuler chaque idée pour l'exprimer de manière concise et claire.

Alors pourquoi les identifiants courts cryptiques sont-ils si courants dans la programmation de bas niveau?

  • Parce que beaucoup d'entre eux sont assez communs dans le domaine respectif pour justifier un nom très court. Cela aggrave la courbe d'apprentissage, mais est un compromis intéressant compte tenu de la fréquence d'utilisation.
  • Parce qu'il y a généralement un petit ensemble de possibilités qui est fixe (le le programmeur ne peut pas ajouter à l'ensemble).
  • Parce que la lisibilité est une question d'habitude et de pratique. branch-if-greater-than-or-equal.short est initialement plus lisible que bge.s, mais avec un peu de pratique, la situation s'inverse.
  • Parce qu'ils doivent souvent être tapés à la main, car les langages de bas niveau ne sont souvent pas fournis avec des IDE puissants qui ont une bonne autocomplétion, ou la climatisation n'est pas fiable.
  • Parce qu'il est parfois souhaitable de regrouper beaucoup d'informations dans l'identifiant, et un nom lisible serait inacceptablement long, même selon des normes de haut niveau.
  • Parce que c'est à cela que les environnements de bas niveau ont toujours ressemblé. Briser l'habitude nécessite un effort conscient, risque d'agacer ceux qui aimaient les anciennes méthodes et doit être justifié comme valable. Rester fidèle à la méthode établie est le "défaut".
  • Parce que beaucoup d'entre eux proviennent d'ailleurs, comme les schémas et les fiches techniques. Ceux-ci, à leur tour, sont affectés par des contraintes d'espace.
  • Parce que les personnes chargées de nommer les choses n'ont même jamais considéré la lisibilité, ou ne réalisent pas qu'elles créent un problème, ou sont paresseuses.
  • Parce que dans certains cas, les noms sont devenus partie intégrante d'un protocole pour l'échange de données, tel que l'utilisation du langage d'assemblage comme représentation intermédiaire par certains compilateurs.
  • Parce que ce style est instantanément reconnaissable comme étant de bas niveau et semble donc cool pour les geeks.

Personnellement, je pense que certains d'entre eux ne contribuent pas réellement aux raisons pour lesquelles un système nouvellement développé choisirait ce style de dénomination, mais je pensais qu'il serait mal de filtrer certaines idées dans ce type de réponse.

11
Roman Starkov

La raison pour laquelle le logiciel utilise ces noms est que les fiches techniques utilisent ces noms. Étant donné que le code à ce niveau est très difficile à comprendre sans la feuille de données de toute façon, créer des noms de variables que vous ne pouvez pas rechercher est extrêmement inutile.

Cela soulève la question de savoir pourquoi les fiches techniques utilisent des noms courts. C'est probablement parce que vous devez souvent présenter les noms dans des tableaux comme celui-ci où vous n'avez pas de place pour les identifiants à 25 caractères:

TIFR1 table from datasheet

En outre, des éléments tels que les schémas, les diagrammes à broches et les sérigraphies PCB sont souvent très exigus pour l'espace.

107
Karl Bielefeldt

La loi de Zipf

Vous pouvez vous-même observer en regardant ce texte même que la longueur et la fréquence d'utilisation des mots sont, en général, inversement liées. Les mots utilisés très fréquemment, comme it, a, but, you et and sont très courts, tandis que les mots qui sont utilisés moins souvent comme observe, comprehension et verbosity sont plus longs. Cette relation observée entre fréquence et longueur est appelée loi de Zipf .

Le nombre d'instructions dans le jeu d'instructions pour un microprocesseur donné est généralement de plusieurs dizaines ou centaines. Par exemple, le jeu d'instructions Atmel AVR semble contenir une centaine d'instructions distinctes (je n'ai pas compté), mais beaucoup d'entre elles sont des variations sur un thème commun et ont des mnémoniques très similaires. Par exemple, les instructions de multiplication incluent MUL, MULS, MULSU, FMUL, FMULS et FMULSU. Vous n'avez pas besoin de regarder la liste d'instructions très longtemps avant de vous faire une idée générale que les instructions qui commencent par "BR" sont des branches, les instructions qui commencent par "LD" sont des charges, etc. La même chose s'applique aux variables: même les processeurs complexes ne fournissent qu'un nombre limité d'emplacements pour stocker des valeurs: registres de conditions, registres à usage général, etc.

Parce qu'il y a si peu d'instructions et parce que les noms longs prennent plus de temps à lire, il est logique de leur donner des noms courts. En revanche, les langages de niveau supérieur permettent aux programmeurs de créer un grand nombre de fonctions, méthodes, classes, variables, etc. Chacun d'eux sera utilisé beaucoup moins fréquemment que la plupart des instructions d'assemblage, et des noms plus longs et plus descriptifs sont de plus en plus importants pour donner aux lecteurs (et aux écrivains) suffisamment d'informations pour comprendre ce qu'ils sont et ce qu'ils font.

De plus, les jeux d'instructions pour différents processeurs utilisent souvent des noms similaires pour des opérations similaires. La plupart des jeux d'instructions incluent des opérations pour ADD, MUL, SUB, LD, ST, BR, NOP, et s'ils n'utilisent pas ces noms exacts, ils utilisent généralement des noms très proches. Une fois que vous avez appris les mnémoniques pour un jeu d'instructions, il ne faut pas longtemps pour s'adapter aux jeux d'instructions pour d'autres appareils. Ainsi, les noms qui peuvent vous sembler "cryptiques" sont à peu près aussi familiers que des mots comme and, or et not pour les programmeurs qui sont qualifiés dans l'art de la programmation de bas niveau. . Je pense que la plupart des gens qui travaillent au niveau de l'Assemblée vous diraient qu'apprendre à lire le code n'est pas l'un des plus grands défis de la programmation de bas niveau.

61
Caleb

En général

La qualité de la dénomination ne consiste pas seulement à avoir des noms descriptifs, elle doit également prendre en compte d'autres aspects, et cela conduit à des recommandations telles que:

  • plus la portée est globale, plus le nom doit être descriptif
  • plus il est utilisé, plus le nom doit être court
  • le même nom doit être utilisé dans tous les contextes pour la même chose
  • différentes choses devraient avoir des noms différents même si le contexte est différent
  • les variations doivent être facilement détectées
  • ...

Notez que ces recommandations sont contradictoires.

Mnémoniques d'instructions

En tant que programmeur de langage d'assemblage, en utilisant short-branch-if-greater-or-equal pour bge.s me donne la même impression que lorsque je vois, en tant que programmeur ALGOL faisant de la géométrie informatique, SUBSTRACT THE-HORIZONTAL-COORDINATE-OF-THE-FIRST-POINT TO THE-HORIZONTAL-COORDINATE-OF-THE-SECOND-POINT GIVING THE-DIFFERENCES-OF-THE-COORDINATE-OF-THE-TWO-POINTS au lieu de dx := p2.x - p1.x. Je ne peux tout simplement pas convenir que les premiers sont plus lisibles dans les contextes dont je me soucie.

Enregistrer les noms

Vous choisissez le nom officiel dans la documentation. La documentation choisit le nom de la conception. La conception utilise beaucoup de formats graphiques où les noms longs ne sont pas adéquats et l'équipe de conception vivra avec ces noms pendant des mois, voire des années. Pour les deux raisons, ils n'utiliseront pas "Drapeau d'interruption du premier compteur de temporisation", ils l'abrèveront dans leur schéma ainsi que lorsqu'ils parleront. Ils le savent et ils utilisent des abréviations systématiques comme TIFR1 pour réduire les risques de confusion. Un point ici est que TIFR1 n'est pas une abréviation aléatoire, c'est le résultat d'un schéma de nommage.

37
AProgrammer

Hormis les "vieilles habitudes", le code hérité qui a été écrit il y a 30 ans et qui est toujours utilisé est très courant. Malgré ce que pensent certaines personnes moins expérimentées, la refonte de ces systèmes pour qu'ils soient beaux a un coût très élevé pour un petit gain et n'est pas commercialement viable.

Les systèmes embarqués proches du matériel - et accédant aux registres, ont tendance à utiliser les mêmes étiquettes ou des étiquettes similaires à celles utilisées dans les fiches techniques du matériel, pour de très bonnes raisons. Si le registre est appelé XYZZY1 dans les fiches techniques du matériel, il est logique que la variable qui le représente soit probablement XYZZY1, ou si le programmeur passe une bonne journée, RegXYZZY1.

Jusqu'au bge.s, c'est similaire à l'assembleur - pour les quelques personnes qui ont besoin de le savoir, les noms plus longs sont moins lisibles. Si vous ne pouvez pas vous déplacer bge.s et pense branch-if-greater-or-equal.short fera la différence - vous jouez simplement avec le CLR et vous ne le savez pas.

L'autre raison pour laquelle vous verrez des noms de variables courts est due à la large diffusion d'abréviations dans le domaine ciblé par le logiciel.

En résumé - des noms de variables abrégés courts qui reflètent une influence externe tels que les normes de l'industrie et les fiches techniques du matériel sont attendus. Les noms de variables abrégés courts qui sont internes au logiciel sont normalement moins souhaitables.

25
mattnz

Je vais jeter mon chapeau dans ce bordel.

Les conventions et normes de codage de haut niveau ne sont pas les mêmes que les normes et pratiques de codage de bas niveau. Malheureusement, la plupart d'entre eux sont des restes de code hérité et de vieux processus de pensée.

Certains, cependant, servent un but. Bien sûr BranchGreaterThan serait beaucoup plus lisible que BGT , mais il y a une convention maintenant, c'est une instruction et en tant que telle, elle a gagné peu de traction au cours des 30 dernières années d'utilisation en standard. Pourquoi ont-ils commencé avec cela, probablement une limite de largeur de caractère arbitraire pour les instructions, les variables et autres; pourquoi le gardent-ils, c'est une norme. Cette norme équivaut à utiliser int comme identifiant, il serait plus lisible d'utiliser Entier dans tous les cas, mais est-ce nécessaire pour toute personne qui a programmé plus de quelques semaines ... non. Pourquoi? Parce que c'est une pratique standard.

Deuxièmement, comme je l'ai dit dans mon commentaire, bon nombre des interruptions sont nommées INTG1 et d'autres noms cryptiques, ils ont également un but. Dans les schémas de circuits, c'est PAS bonne convention pour nommer vos lignes et si verbeusement cela encombre le diagramme et nuit à la lisibilité. Toute verbosité est traitée dans la documentation. Et puisque tous les schémas de câblage/circuit ont ces noms courts pour les lignes d'interruption, les interruptions elles-mêmes obtiennent également le même nom que pour garder la cohérence pour le concepteur intégré du schéma de circuit jusqu'au code pour le programmer.

Un concepteur a un certain contrôle sur cela, mais comme tout champ/nouveau langage, il existe des conventions qui suivent d'un matériel à un autre, et en tant que telles doivent rester similaires dans chaque langage d'assemblage. Je peux regarder un extrait d'Assembly et être en mesure d'obtenir l'essentiel du code sans jamais utiliser cet ensemble d'instructions car ils respectent une convention, LDA ou une relation avec cela charge probablement un registre [[# #]] mv [~ # ~] déplace probablement quelque chose d'un endroit à un autre, ce n'est pas ce que vous pensez être Nice ou est un la pratique de haut niveau, c'est une langue en soi et en tant que telle a ses propres normes et signifie que vous, en tant que concepteur, devez suivre, celles-ci ne sont souvent pas aussi arbitraires qu'elles le semblent.

Je vous laisse avec ceci: demander à la communauté intégrée d'utiliser des pratiques verbeuses de haut niveau, c'est comme demander aux chimistes de toujours écrire les composés chimiques. Le chimiste les écrit pour lui-même et n'importe qui d'autre dans le domaine le comprendra, mais cela peut prendre un peu de temps à un nouveau venu pour s'adapter.

10
Jeff Langemeier

L'une des raisons pour lesquelles ils utilisent des identifiants courts cryptiques est qu'ils ne sont pas cryptiques pour les développeurs. Vous devez réaliser qu'ils fonctionnent avec lui tous les jours et que ces noms sont vraiment des noms de domaine. Ils savent donc par cœur ce que signifie exactement TIFR1.

Si un nouveau développeur vient dans l'équipe, il devra lire les fiches techniques (comme expliqué par @KarlBielefeldt) afin de se familiariser avec celles-ci.

Je crois que votre question a utilisé un mauvais exemple, car en effet, sur ce type de codes source, vous voyez généralement beaucoup d'identificateurs de cryptage inutiles pour des éléments n'appartenant pas au domaine.

Je dirais surtout qu'ils le font à cause des mauvaises habitudes qui existaient lorsque les compilateurs ne complétaient pas automatiquement tout ce que vous tapez.

6
Alex

Sommaire

L'initialisme est un phénomène omniprésent dans de nombreux cercles techniques et non techniques. En tant que tel, il ne se limite pas à une programmation de bas niveau. Pour la discussion générale, voir l'article Wikipedia sur Acronyme . Ma réponse est spécifique à la programmation de bas niveau.

Causes des noms cryptiques:

  1. Les instructions de bas niveau sont fortement typées
  2. Besoin de mettre beaucoup d'informations de type dans le nom d'une instruction de bas niveau
  3. Historiquement, les codes à un seul caractère sont privilégiés pour emballer les informations de type.

Solutions et leurs inconvénients:

  1. Il existe des schémas de dénomination bas niveau modernes qui sont plus cohérents que les schémas historiques.
    • LLVM
  2. Cependant, la nécessité de regrouper un grand nombre d'informations de type existe toujours.
    • Ainsi, des abréviations cryptiques peuvent encore être trouvées partout.
  3. La lisibilité améliorée de ligne à ligne aidera un programmeur débutant de bas niveau à maîtriser la langue plus rapidement, mais ne permettra pas de comprendre de gros morceaux de code de bas niveau.

Réponse complète

(A) Des noms plus longs sont possibles. Par exemple, les noms des éléments intrinsèques C++ SSE2 comptent en moyenne 12 caractères par rapport aux 7 caractères de la mnémonique Assembly. http://msdn.Microsoft.com/en-us/library/c8c5hx3b (v = vs.80) .aspx

(B) La question passe ensuite à: combien de temps/non cryptique faut-il pour obtenir des instructions de bas niveau?

(C) Nous analysons maintenant la composition de ces schémas de dénomination. Voici deux schémas de dénomination pour la même instruction de bas niveau :

  • Schéma de dénomination n ° 1: CVTSI2SD
  • Schéma de dénomination n ° 2: __m128d _mm_cvtsi32_sd (__m128d a, int b);

(C.1) Les instructions de bas niveau sont toujours fortement typées. Il ne peut y avoir d'ambiguïté, d'inférence de type, de conversion automatique de type ou de surcharge (réutilisation du nom de l'instruction pour signifier des opérations similaires mais non équivalentes).

(C.2) Chaque instruction de bas niveau doit coder un grand nombre d'informations de type dans son nom. Exemples d'informations:

  • Famille d'architecture
  • Opération
  • Arguments (entrées) et sorties
  • Types (entier signé, entier non signé, flottant)
  • Précision (largeur de bit)

(C.3) Si chaque élément d'information est énoncé, le programme sera plus détaillé.

(C.4) Les schémas de codage de type utilisés par divers fournisseurs avaient de longues racines historiques. Par exemple, dans le jeu d'instructions x86:

  • B signifie octet (8 bits)
  • W signifie Word (16 bits)
  • D signifie dword "double-Word" (32 bits)
  • Q signifie qword "quad-Word" (64 bits)
  • DQ signifie dqword "double-quad-Word" (128 bits)

Ces références historiques n'avaient aucune signification moderne, mais elles persistent. Un schéma plus cohérent aurait mis la valeur de largeur de bit (8, 16, 32, 64, 128) dans le nom.

Au contraire, LLVM est un bon pas dans la direction de la cohérence des instructions de bas niveau: http://llvm.org/docs/LangRef.html#functions

(D) Indépendamment du schéma de dénomination des instructions, les programmes de bas niveau sont déjà verbeux et difficiles à comprendre car ils se concentrent sur les moindres détails de l'exécution. La modification du schéma de dénomination des instructions améliorera la lisibilité au niveau ligne à ligne, mais ne supprimera pas la difficulté de comprendre les opérations d'un gros morceau de code.

5
rwong

Les humains ne lisent et n'écrivent l'assemblage qu'occasionnellement, et la plupart du temps ce n'est qu'un protocole de communication. C'est-à-dire qu'il est le plus souvent utilisé comme représentation textuelle sérialisée intermédiaire entre le compilateur et l'assembleur. Plus cette représentation est détaillée, plus la surcharge est inutile dans ce protocole.

Dans le cas des opcodes et des noms de registre, les noms longs nuisent en fait à la lisibilité. Les mnémoniques courts sont meilleurs pour un protocole de communication (entre le compilateur et l'assembleur), et le langage d'assemblage est un protocole de communication la plupart du temps. Les mnémoniques courts sont meilleurs pour les programmeurs, car le code du compilateur est plus facile à lire.

2
SK-logic

Je suis surpris que personne n'ait mentionné la paresse et que les autres sciences ne soient pas discutées. Mon travail quotidien en tant que programmeur me montre que les conventions de dénomination pour tout type de variable dans un programme sont influencées par trois aspects différents:

  1. Le contexte scientifique du programmeur.
  2. Les compétences en programmation du programmeur.
  3. L'environnement du programmeur.

Je pense qu'il est inutile de discuter de programmation de bas niveau ou de haut niveau. En fin de compte, il peut toujours être lié aux trois premiers aspects.


ne explication du premier aspect: Beaucoup de "programmeurs" ne sont pas des programmeurs en premier lieu. Ce sont des mathématiciens, des physiciens, des biologistes ou même des psychologues ou des économistes mais beaucoup d'entre eux ne sont pas des informaticiens. La plupart d'entre eux ont leurs propres mots-clés et abréviations spécifiques au domaine que vous pouvez voir dans leurs "conventions" de nommage. Ils sont souvent piégés dans leur domaine et utilisent ces abréviations connues sans penser à la lisibilité ou aux guides de codage.

ne explication du deuxième aspect: Comme la plupart des programmeurs ne sont pas des informaticiens, leurs compétences en programmation sont limitées. C'est pourquoi ils ne se soucient souvent pas des conventions de codage mais plus des conventions spécifiques au domaine comme indiqué en premier aspect. De plus, si vous n'avez pas les compétences d'un programmeur, vous n'avez pas la compréhension des conventions de codage. Je pense que la plupart d'entre eux ne voient pas l'urgence d'écrire du code compréhensible. C'est comme le feu et oublier.

ne explication du troisième aspect: Il est peu probable de freiner avec les conventions de votre environnement qui peuvent être d'anciens codes que vous devez supporter, les normes de codage de votre entreprise (dirigées par des économistes qui ne se soucient pas du codage) ou le domaine auquel vous appartenez. Si quelqu'un a commencé à utiliser des noms cryptiques et que vous devez prendre en charge lui ou son code, il est peu probable que vous changiez les noms cryptiques. S'il n'y a pas de normes de codage dans votre entreprise, je parie que presque tous les programmeurs écriront leur propre norme. Et enfin, si vous êtes entouré d'utilisateurs de domaine, vous ne commencerez pas à écrire une autre langue que celle qu'ils utilisent.

1
wagnerpeer

C'est surtout idiomatique. Comme @TMN le dit ailleurs, tout comme vous n'écrivez pas import JavaScriptObjectNotation ou import HypertextTransferProtocolLibrary en Python, vous n'écrivez pas Timer1LowerHalf = 0xFFFF en C. Cela semble tout aussi ridicule dans son contexte. Tous ceux qui ont besoin de savoir le savent déjà.

La résistance au changement peut résulter, en partie, du fait que certains fournisseurs de compilateurs C pour les systèmes embarqués s'écartent de la norme et de la syntaxe du langage afin d'implémenter des fonctionnalités plus utiles à la programmation embarquée. Cela signifie que vous ne pouvez pas toujours utiliser la fonction de saisie semi-automatique de votre favori IDE ou éditeur de texte lors de l'écriture de code de bas niveau, car ces personnalisations nuisent à leur capacité à analyser le code. D'où l'utilité du registre court noms, macros et constantes.

Par exemple, le compilateur C de HiTech a inclus une syntaxe spéciale pour les variables qui devaient avoir une position spécifiée par l'utilisateur en mémoire. Vous pourriez déclarer:

volatile char MAGIC_REGISTER @ 0x7FFFABCD;

Maintenant, le seul IDE existant qui analysera ceci est le propre de HiTech IDE (HiTide). Dans tout autre éditeur, vous ' Il faudra le taper manuellement, de mémoire, à chaque fois. Cela vieillit très rapidement.

Ensuite, il y a aussi le fait que lorsque vous utilisez des outils de développement pour inspecter les registres, vous aurez souvent un tableau affiché avec plusieurs colonnes (nom du registre, valeur en hexadécimal, valeur en binaire, dernière valeur en hexadécimal, etc.). Les noms longs signifient que vous devez étendre la colonne des noms à 13 caractères pour voir la différence entre deux registres et jouer "repérer la différence" sur des dizaines de lignes de mots répétés.

Celles-ci peuvent ressembler à de petites bêtises idiotes, mais toutes les conventions de codage ne sont-elles pas conçues pour réduire la fatigue oculaire, diminuer la frappe superflue ou répondre à l'une des millions d'autres petites plaintes?

1
detly