Maison / Avatar / Format des données et structure des instructions du langage d'assemblage. Résumé : Plan : Préface. Langage d'assemblage et structure d'instructions. La structure du fichier exe (analyse sémantique) La structure de la commande en langage assembleur contient

Format des données et structure des instructions du langage d'assemblage. Résumé : Plan : Préface. Langage d'assemblage et structure d'instructions. La structure du fichier exe (analyse sémantique) La structure de la commande en langage assembleur contient

Sujet 1.4 Mnémoniques assembleur. Structure et formats des commandes. Types d'adressage. Jeu d'instructions du microprocesseur

Planifier:

1 Langage d'assemblage. Concepts de base

2 Symboles du langage d'assemblage

3 Types d'instructions assembleur

4 Directives de montage

5 Jeu d'instructions du processeur

1 jelangage d'assemblage. Concepts de base

langage d'assemblageest une représentation symbolique du langage machine. Tous les processus de la machine au niveau matériel le plus bas ne sont pilotés que par des commandes (instructions) du langage machine. Il en ressort clairement que, malgré le nom commun, le langage d'assemblage de chaque type d'ordinateur est différent.

Un programme en langage assembleur est un ensemble de blocs de mémoire appelés tranches de mémoire. Un programme peut consister en un ou plusieurs de ces blocs-segments. Chaque segment contient une collection de phrases de langage, dont chacune occupe une ligne distincte de code de programme.

Les instructions d'assemblage sont de quatre types :

1) commandes ou instructions qui sont des analogues symboliques des commandes machine. Pendant le processus de traduction, les instructions d'assemblage sont converties en commandes correspondantes du jeu d'instructions du microprocesseur ;

2) macro -les phrases du texte de l'émission, qui sont formalisées d'une certaine manière, sont remplacées par d'autres phrases lors de la diffusion ;

3) directives,qui sont des instructions au traducteur assembleur pour effectuer certaines actions. Les directives n'ont pas d'équivalent dans la représentation machine ;

4) lignes de commentaires , contenant tous les caractères, y compris les lettres de l'alphabet russe. Les commentaires sont ignorés par le traducteur.

­ Structure du programme d'assemblage. syntaxe assembleur.

Les phrases qui composent un programme peuvent être une construction syntaxique correspondant à une commande, une macro, une directive ou un commentaire. Pour que le traducteur assembleur les reconnaisse, ils doivent être formés selon certaines règles syntaxiques. Pour ce faire, il est préférable d'utiliser une description formelle de la syntaxe du langage, comme les règles de grammaire. Les façons les plus courantes de décrire un langage de programmation comme celui-ci - diagrammes de syntaxe et formes étendues de Backus-Naur. Pour utilisation pratique plus confortable diagrammes de syntaxe. Par exemple, la syntaxe des instructions en langage assembleur peut être décrite à l'aide des diagrammes de syntaxe illustrés dans les figures 10, 11, 12 suivantes.

Figure 10 - Format de phrase d'assemblage


­ Figure 11 - Format des directives

­ Figure 12 - Format des commandes et des macros

Sur ces dessins :

­ nom de l'étiquette- identifiant dont la valeur est l'adresse du premier octet de la phrase du code source du programme qu'il désigne ;

­ Nom -un identifiant qui distingue cette directive des autres directives du même nom. Suite au traitement par l'assembleur d'une certaine directive, certaines caractéristiques peuvent être affectées à ce nom ;

­ code d'opération (COP) et directive - il s'agit de symboles mnémoniques pour l'instruction machine, l'instruction de macro ou la directive de compilateur correspondante ;

­ opérandes -parties d'une commande, d'une macro ou d'une directive assembleur, désignant les objets sur lesquels des actions sont effectuées. Les opérandes assembleur sont décrits par des expressions avec des constantes numériques et textuelles, des étiquettes de variables et des identificateurs utilisant des signes d'opération et des mots réservés.

Aide des diagrammes de syntaxe trouvez puis parcourez le chemin de l'entrée du diagramme (à gauche) à sa sortie (à droite). Si un tel chemin existe, alors la phrase ou la construction est syntaxiquement correcte. Si un tel chemin n'existe pas, le compilateur n'acceptera pas cette construction.

­ 2 Symboles du langage d'assemblage

Les caractères autorisés lors de l'écriture du texte des programmes sont :

1) toutes les lettres latines : A-Z,de a à z. Dans ce cas, les majuscules et les minuscules sont considérées comme équivalentes ;

2) numéros de 0 avant de 9 ;

3) signes ? , @ , $ , _ , & ;

4) séparateurs , . () < > { } + / * % ! " " ? = # ^ .

Les phrases en assembleur sont formées à partir de jetons, qui sont des séquences syntaxiquement inséparables de caractères linguistiques valides qui ont un sens pour le traducteur.

jetons sommes:

1) identifiants - séquences de caractères valides utilisées pour désigner des objets de programme tels que des opcodes, des noms de variables et des noms d'étiquettes. La règle d'écriture des identifiants est la suivante : un identifiant peut être composé d'un ou plusieurs caractères ;

2) chaînes de caractères - séquences de caractères entre guillemets simples ou doubles ;

3) entiers dans l'un des systèmes de numération suivants : binaire, décimal, hexadécimal. L'identification des nombres lors de leur écriture dans les programmes assembleur s'effectue selon certaines règles:

4) les nombres décimaux ne nécessitent aucun symbole supplémentaire pour leur identification, par exemple 25 ou 139. Pour l'identification dans le code source du programme nombres binaires il faut, après avoir écrit les zéros et les uns inclus dans leur composition, mettre le latin « b”, par exemple 10010101 b.

5) les nombres hexadécimaux ont plus de conventions dans leur notation :

Premièrement, ils sont composés de nombres. 0...9 , minuscules et majuscules de l'alphabet latin un,b, c,,e,F ou UN,B,C,,E,F.

Deuxièmement, le traducteur peut avoir des difficultés à reconnaître les nombres hexadécimaux du fait qu'ils peuvent être constitués uniquement des chiffres 0...9 (par exemple, 190845) ou commencer par une lettre de l'alphabet latin (par exemple, ef15). Afin "d'expliquer" au traducteur que le lexème donné n'est pas un nombre décimal ou un identifiant, le programmeur doit spécialement allouer le nombre hexadécimal. Pour ce faire, à la fin de la séquence de chiffres hexadécimaux qui composent le nombre hexadécimal, écrivez la lettre latine " h". C'est un pré-requis. Si un nombre hexadécimal commence par une lettre, il est précédé d'un zéro non significatif : 0 ef15 h.

Presque chaque phrase contient une description de l'objet sur lequel ou à l'aide duquel une action est effectuée. Ces objets sont appelés opérandes. Ils peuvent être définis comme ceci : opérandes- ce sont des objets (certaines valeurs, registres ou cellules de mémoire) qui sont affectés par des instructions ou des directives, ou ce sont des objets qui définissent ou affinent l'action d'instructions ou de directives.

Il est possible d'effectuer la classification d'opérandes suivante :

­ opérandes constants ou immédiats ;

­ opérandes d'adresse ;

­ opérandes déplacés ;

compteur d'adresses ;

­ enregistrer l'opérande ;

­ opérandes de base et d'index ;

­ opérandes structurels ;

enregistrements.

Les opérandes sont des composants élémentaires qui font partie de l'instruction machine, désignant les objets sur lesquels l'opération est effectuée. Dans un cas plus général, les opérandes peuvent être inclus comme composants dans des formations plus complexes appelées expressions.

Expressions sont des combinaisons d'opérandes et d'opérateurs considérés comme un tout. Le résultat de l'évaluation de l'expression peut être l'adresse d'une cellule de mémoire ou une valeur constante (absolue).

­ 3 Types d'instructions assembleur

Listons les types possibles instructions de l'assembleur et des règles syntaxiques pour la formation des expressions en assembleur :

­ opérateurs arithmétiques;

­ opérateurs de quarts;

­ opérateurs de comparaison ;

­ Opérateurs logiques;

­ opérateur d'index ;

­ opérateur de remplacement de type ;

­ opérateur de redéfinition de segment ;

­ opérateur de dénomination de type de structure ;

­ opérateur pour obtenir la composante segment de l'adresse de l'expression ;

­ décalage d'expression obtenir l'opérateur.

1 Directives de montage

­ Les directives de l'assembleur sont :

1) Directives de segmentation. Au cours de la discussion précédente, nous avons découvert toutes les règles de base pour écrire des instructions et des opérandes dans un programme en langage assembleur. La question de savoir comment formater correctement la séquence de commandes pour que le traducteur puisse les traiter et que le microprocesseur puisse les exécuter reste ouverte.

Lors de l'examen de l'architecture du microprocesseur, nous avons appris qu'il dispose de six registres de segments, à travers lesquels il peut fonctionner simultanément :

­ avec un segment de code ;

­ avec un segment de pile ;

­ avec un segment de données ;

­ avec trois segments de données supplémentaires.

Physiquement, un segment est une zone mémoire occupée par des commandes et (ou) des données dont les adresses sont calculées par rapport à la valeur dans le registre de segment correspondant. Description de la syntaxe segment en assembleur est la construction illustrée à la figure 13 :


­ Figure 13 - Description syntaxique du segment en assembleur

Il est important de noter que la fonctionnalité d'un segment est un peu plus large que la simple décomposition du programme en blocs de code, de données et de pile. La segmentation s'inscrit dans un mécanisme plus général lié à concept de programmation modulaire. Cela implique l'unification de la conception des modules objets créés par le compilateur, y compris ceux de différents langages de programmation. Cela vous permet de combiner des programmes écrits dans différentes langues. C'est à la mise en œuvre de diverses options pour une telle union que les opérandes de la directive SEGMENT sont destinés.

2) Liste des directives de contrôle. Les directives de contrôle des listes sont réparties dans les groupes suivants :

­ directives générales de contrôle de cotation;

­ directives de sortie pour inclure la liste des fichiers ;

­ directives de sortie pour les blocs d'assemblage conditionnels ;

­ directives de sortie pour la liste des macros ;

­ directives pour afficher des informations sur les références croisées dans la liste ;

­ directives de changement de format de liste.

2 Jeu d'instructions du processeur

Le jeu d'instructions du processeur est illustré à la figure 14.

Considérez les principaux groupes de commandes.

­ Figure 14 - Classification des instructions de montage

Les commandes sont :

1 Commandes de transfert de données. Ces instructions occupent une place très importante dans le jeu d'instructions de tout processeur. Ils remplissent les fonctions essentielles suivantes :

­ sauvegarder en mémoire le contenu des registres internes du processeur ;

­ copier le contenu d'une zone de mémoire à une autre ;

­ l'écriture sur les périphériques d'E/S et la lecture à partir des périphériques d'E/S.

Dans certains processeurs, toutes ces fonctions sont exécutées par une seule instruction MOV (pour les transferts d'octets - MOVB ) nez diverses méthodes adressage des opérandes.

Dans d'autres processeurs en plus de l'instruction MOV il existe plusieurs autres commandes pour exécuter les fonctions répertoriées. Les commandes de transfert de données incluent également les commandes d'échange d'informations (leur désignation est basée sur le motÉchanger ). Il peut être possible de prévoir l'échange d'informations entre registres internes, entre deux moitiés d'un registre (ÉCHANGER ) ou entre un registre et un emplacement mémoire.

2 commandes arithmétiques. Les instructions arithmétiques traitent les codes d'opérandes comme des codes numériques binaires ou BCD. Ces commandes peuvent être divisées en cinq groupes principaux :

­ commandes pour les opérations avec un point fixe (addition, soustraction, multiplication, division);

­ instructions en virgule flottante (addition, soustraction, multiplication, division);

­ commandes de nettoyage ;

­ commandes d'incrémentation et de décrémentation ;

­ commande de comparaison.

3 Les instructions en virgule fixe fonctionnent sur des codes dans les registres du processeur ou en mémoire comme elles le feraient avec des codes binaires normaux. Les instructions à virgule flottante (virgule) utilisent un format de représentation numérique avec un exposant et une mantisse (généralement ces nombres occupent deux emplacements de mémoire consécutifs). En moderne processeurs puissants le jeu d'instructions en virgule flottante n'est pas limité à seulement quatre opérations arithmétiques, mais contient également de nombreuses autres instructions plus complexes, par exemple, le calcul de fonctions trigonométriques, de fonctions logarithmiques, et aussi fonctions complexes nécessaire au traitement du son et de l'image.

4 Les commandes d'effacement sont conçues pour écrire un code zéro dans un registre ou une cellule mémoire. Ces commandes peuvent être remplacées par des instructions de transfert à code zéro, mais les instructions claires spéciales sont généralement plus rapides que les instructions de transfert.

5 Commandes d'incrémentation (augmentation de un) et de décrémentation

(réductions par un) sont également très pratiques. Ils pourraient en principe être remplacés par des instructions d'addition ou de soustraction, mais l'incrémentation et la décrémentation sont plus rapides que l'addition et la soustraction. Ces instructions nécessitent un opérande d'entrée qui est également un opérande de sortie.

6 L'instruction de comparaison sert à comparer deux opérandes d'entrée. En fait, il calcule la différence de ces deux opérandes, mais ne forme pas l'opérande de sortie, mais modifie uniquement les bits dans le registre d'état du processeur en fonction du résultat de cette soustraction. L'instruction suivant l'instruction de comparaison (généralement une instruction de saut) analysera les bits dans le registre d'état du processeur et effectuera des actions en fonction de leurs valeurs. Certains processeurs fournissent des instructions pour comparer en chaîne deux séquences d'opérandes en mémoire.

7 Commandes logiques. Les instructions logiques effectuent des opérations logiques (au niveau du bit) sur les opérandes, c'est-à-dire qu'elles considèrent les codes d'opérande non pas comme un nombre unique, mais comme un ensemble de bits individuels. En cela, ils diffèrent des commandes arithmétiques. Les commandes logiques effectuent les opérations de base suivantes :

­ ET logique, OU logique, addition modulo 2 (XOR);

­ décalages logiques, arithmétiques et cycliques ;

­ vérification des bits et des opérandes ;

­ réglage et effacement des bits (drapeaux) du registre d'état du processeur ( PSW).

Équipes opérations logiques permettent le calcul bit à bit des fonctions logiques de base à partir de deux opérandes d'entrée. De plus, l'opération ET est utilisée pour forcer l'effacement des bits donnés (l'un des opérandes est le code de masque, dans lequel les bits à effacer sont mis à zéro). L'opération OU est utilisée pour forcer les bits définis (comme l'un des opérandes, le code de masque est utilisé, dans lequel les bits qui doivent être définis sur un sont égaux à un). L'opération XOR est utilisée pour inverser les bits donnés (comme l'un des opérandes, le code de masque est utilisé dans lequel les bits à inverser sont mis à un). Les instructions nécessitent deux opérandes d'entrée et forment un opérande de sortie.

8 Les commandes de décalage permettent de décaler le code de l'opérande petit à petit vers la droite (vers les bits inférieurs) ou vers la gauche (vers les bits supérieurs). Le type de décalage (booléen, arithmétique ou cyclique) détermine quelle sera la nouvelle valeur du bit le plus significatif (lorsqu'il est décalé vers la droite) ou du bit le moins significatif (lorsqu'il est décalé vers la gauche), et détermine également si l'ancienne valeur du bit le plus significatif bit sera stocké quelque part (lorsqu'il est décalé vers la gauche) ou le bit le moins significatif (lorsqu'il est décalé vers la droite). Les décalages rotatifs vous permettent de décaler les bits du code d'opérande dans un cercle (dans le sens des aiguilles d'une montre lors d'un décalage vers la droite ou dans le sens inverse des aiguilles d'une montre lors d'un décalage vers la gauche). Dans ce cas, la bague de décalage peut ou non inclure le drapeau de report. Le bit d'indicateur de report (s'il est utilisé) est défini sur le bit le plus significatif pour la rotation à gauche et sur le bit le moins significatif pour la rotation à droite. En conséquence, la valeur du bit d'indicateur de report sera réécrite sur le bit le moins significatif lors d'un décalage cyclique vers la gauche et sur le bit le plus significatif lors d'un décalage cyclique vers la droite.

9 Commandes de saut. Les commandes de saut sont conçues pour organiser toutes sortes de boucles, de branchements, d'appels de sous-programmes, etc., c'est-à-dire qu'elles perturbent le flux séquentiel du programme. Ces instructions écrivent une nouvelle valeur dans le registre du compteur d'instructions et amènent ainsi le processeur à sauter non pas à l'instruction suivante dans l'ordre, mais à toute autre instruction dans la mémoire programme. Certaines commandes de saut vous permettent de revenir au point à partir duquel le saut a été effectué, tandis que d'autres ne le permettent pas. Si un retour est fourni, les paramètres actuels du processeur sont stockés sur la pile. Si aucun retour n'est fourni, les paramètres actuels du processeur ne sont pas enregistrés.

Les commandes de saut sans retour arrière sont divisées en deux groupes :

­ commandes de sauts inconditionnels ;

­ instructions de saut conditionnel.

Ces commandes utilisent les mots Branche (branche) et Jump (saut).

Les instructions de saut inconditionnel provoquent un saut vers une nouvelle adresse quoi qu'il arrive. Ils peuvent provoquer un saut à la valeur de décalage spécifiée (avant ou arrière) ou à l'adresse mémoire spécifiée. La valeur de décalage ou la nouvelle valeur d'adresse est spécifiée comme opérande d'entrée.

Les commandes de saut conditionnel ne provoquent pas toujours un saut, mais uniquement lorsque les conditions spécifiées sont remplies. Ces conditions sont généralement les valeurs des drapeaux dans le registre d'état du processeur ( PSW ). Autrement dit, la condition de transition est le résultat de l'opération précédente qui modifie les valeurs des drapeaux. Au total, ces conditions de saut peuvent être au nombre de 4 à 16. Quelques exemples de commandes de saut conditionnel :

­ sauter si égal à zéro ;

­ sauter si non nul ;

­ sauter s'il y a un débordement ;

­ sauter s'il n'y a pas de débordement ;

­ sauter si supérieur à zéro ;

­ sauter si inférieur ou égal à zéro.

Si la condition de transition est remplie, alors une nouvelle valeur est chargée dans le registre du compteur d'instructions. Si la condition de saut n'est pas satisfaite, le compteur d'instructions est simplement incrémenté et le processeur sélectionne et exécute l'instruction suivante en séquence.

Spécifiquement pour vérifier les conditions de branchement, on utilise une instruction de comparaison (CMP) qui précède une instruction de saut conditionnel (voire plusieurs instructions de saut conditionnel). Mais les drapeaux peuvent être définis par n'importe quelle autre commande, telle qu'une commande de transfert de données, n'importe quelle commande arithmétique ou logique. Notez que les commandes de saut elles-mêmes ne changent pas les drapeaux, ce qui vous permet simplement de mettre plusieurs commandes de saut les unes après les autres.

Les commandes d'interruption occupent une place particulière parmi les commandes de saut avec retour. Ces instructions nécessitent un numéro d'interruption (adresse vectorielle) comme opérande d'entrée.

Conclusion:

Le langage assembleur est une représentation symbolique du langage machine. Le langage d'assemblage de chaque type d'ordinateur est différent. Un programme en langage assembleur est un ensemble de blocs de mémoire appelés segments de mémoire. Chaque segment contient une collection de phrases de langage, dont chacune occupe une ligne distincte de code de programme. Les instructions d'assemblage sont de quatre types : commandes ou instructions, macros, directives, lignes de commentaires.

Les caractères valides lors de l'écriture du texte des programmes sont toutes des lettres latines : A-Z,de a à z. Dans ce cas, les majuscules et les minuscules sont considérées comme équivalentes ; chiffres de 0 avant de 9 ; panneaux ? , @ , $ , _ , & ; séparateurs , . () < > { } + / * % ! " " ? = # ^ .

Les types d'instructions d'assembleur et les règles de syntaxe suivants pour la formation d'expressions d'assembleur s'appliquent. opérateurs arithmétiques, opérateurs de décalage, opérateurs de comparaison, opérateurs logiques, opérateur d'index, opérateur de redéfinition de type, opérateur de redéfinition de segment, opérateur de dénomination de type de structure, opérateur d'obtention de composant de segment d'adresse d'expression, opérateur d'obtention de décalage d'expression.

Le système de commandement est divisé en 8 groupes principaux.

­ Question test :

1 Qu'est-ce que le langage d'assemblage ?

2 Quels symboles peuvent être utilisés pour écrire des commandes en assembleur ?

3 Que sont les labels et à quoi servent-ils ?

4 Expliquer la structure des instructions de montage.

5 Énumérez 4 types d'instructions en assembleur.

Pour que la machine exécute des commandes humaines au niveau matériel, il est nécessaire de définir une certaine séquence d'actions dans le langage des «zéros et des uns». L'assembleur deviendra un assistant dans cette affaire. Il s'agit d'un utilitaire qui fonctionne avec la traduction de commandes en langage machine. Cependant, écrire un programme est un processus très long et complexe. Ce langage n'est pas destiné à créer de la lumière et gestes simples. Sur le ce moment n'importe quel langage de programmation que vous utilisez (Assembler fonctionne très bien) vous permet d'écrire des tâches spéciales efficaces qui affectent grandement le fonctionnement du matériel. Le but principal est de créer des micro-instructions et des petits codes. Ce langage offre plus de fonctionnalités que, par exemple, Pascal ou C.

Brève description des langages d'assemblage

Tous les langages de programmation sont divisés en niveaux : bas et haut. Chacun des systèmes syntaxiques de la "famille" de l'assembleur est différent en ce qu'il combine à la fois certains des avantages des systèmes les plus courants et langues modernes. Ils sont également liés aux autres par le fait que vous pouvez utiliser pleinement le système informatique.

Une caractéristique distinctive du compilateur est sa facilité d'utilisation. En cela, il diffère de ceux qui ne fonctionnent qu'avec des niveaux élevés. Si un tel langage de programmation est pris en compte, Assembler fonctionne deux fois plus vite et mieux. Pour y écrire programme léger ne prendra pas trop de temps.

En bref sur la structure de la langue

Si nous parlons en général du travail et de la structure du fonctionnement du langage, nous pouvons dire avec certitude que ses commandes sont parfaitement cohérentes avec les commandes du processeur. C'est-à-dire que l'assembleur utilise des codes mnémoniques les plus pratiques à écrire pour une personne.

Contrairement à d'autres langages de programmation, Assembler utilise des étiquettes spécifiques au lieu d'adresses pour écrire des cellules de mémoire. Ils sont traduits dans les soi-disant directives avec le processus d'exécution du code. Ce sont des adresses relatives qui n'affectent pas le fonctionnement du processeur (elles ne sont pas traduites en langage machine), mais sont nécessaires à la reconnaissance par l'environnement de programmation lui-même.

Chaque ligne de processeur a la sienne, dans cette situation, n'importe quel processus sera correct, y compris celui traduit.

Le langage d'assemblage a plusieurs syntaxes, qui seront discutées dans l'article.

Les pros de la langue

L'adaptation la plus importante et la plus pratique du langage d'assemblage sera qu'il peut être utilisé pour écrire n'importe quel programme pour le processeur, qui sera très compact. Si le code est énorme, certains processus sont redirigés vers RAM. Dans le même temps, ils fonctionnent tous assez rapidement et sans échec, à moins, bien sûr, qu'ils ne soient contrôlés par un programmeur qualifié.

Les pilotes, les systèmes d'exploitation, le BIOS, les compilateurs, les interpréteurs, etc. sont tous des programmes en langage assembleur.

Lorsque vous utilisez un désassembleur qui traduit de machine en machine, vous pouvez facilement comprendre comment fonctionne telle ou telle tâche système, même s'il n'y a pas d'explications à ce sujet. Cependant, cela n'est possible que si les programmes sont légers. Malheureusement, il est assez difficile de comprendre des codes non triviaux.

Inconvénients de la langue

Malheureusement, il est difficile pour les programmeurs novices (et souvent professionnels) de comprendre le langage. L'assembleur a besoin Description détaillée la commande requise. Du fait que vous devez utiliser des instructions machine, la probabilité d'actions erronées et la complexité de l'exécution augmentent.

Afin d'écrire même le plus un programme simple, le programmeur doit être qualifié, et son niveau de connaissances est suffisamment élevé. Le spécialiste moyen, malheureusement, écrit souvent de mauvais codes.

Si la plate-forme pour laquelle le programme est créé est mise à jour, toutes les commandes doivent être réécrites manuellement - cela est requis par le langage lui-même. L'assembleur ne prend pas en charge la fonction de régulation automatique de la santé des processus et le remplacement de tout élément.

Commandes de langue

Comme mentionné ci-dessus, chaque processeur a son propre ensemble d'instructions. Les éléments les plus simples reconnus par n'importe quel type sont les codes suivants :


Utilisation de directives

Programmation des microcontrôleurs dans le langage (Assembler le permet et fait un excellent travail de fonctionnement) du niveau faible dans la plupart des cas, cela se termine bien. Il est préférable d'utiliser des processeurs avec une ressource limitée. Pour la technologie 32 bits langue donnée convient très bien. Vous pouvez souvent voir des directives dans les codes. Qu'est-ce que c'est? Et à quoi ça sert ?

Pour commencer, il faut souligner que les directives ne sont pas traduites en langage machine. Ils régissent le fonctionnement du compilateur. Contrairement aux commandes, ces paramètres, ayant diverses fonctions, ne diffèrent pas en raison de processeurs différents, mais en raison d'un traducteur différent. Les principales directives comprennent ce qui suit :


origine du nom

Quel est le nom du langage - "Assembleur" ? On parle d'un traducteur et d'un compilateur, qui chiffrent les données. De l'anglais Assembler ne signifie rien de plus qu'un assembleur. Le programme n'a pas été compilé à la main, une structure automatique a été utilisée. De plus, pour le moment, les utilisateurs et les spécialistes ont déjà effacé la différence entre les termes. Souvent, l'assembleur est appelé langage de programmation, bien qu'il ne s'agisse que d'un utilitaire.

En raison du nom collectif généralement accepté, certaines personnes ont l'hypothèse erronée qu'il existe un seul langage de bas niveau (ou des normes standard pour celui-ci). Pour que le programmeur comprenne quelle structure Dans la question, il faut préciser pour quelle plateforme tel ou tel langage d'assemblage est utilisé.

outils macros

Les langages assembleurs, qui sont relativement récents, disposent de macro-fonctionnalités. Ils facilitent à la fois l'écriture et l'exécution d'un programme. En raison de leur présence, le traducteur exécute le code écrit plusieurs fois plus rapidement. Lors de la création d'un choix conditionnel, vous pouvez écrire un énorme bloc de commandes, mais il est plus facile d'utiliser des macros. Ils vous permettront de passer rapidement d'une action à l'autre, en cas de condition remplie ou non.

Lors de l'utilisation de directives de langage macro, le programmeur reçoit des macros Assembleur. Parfois, il peut être largement utilisé, et parfois son caractéristiques fonctionnelles jusqu'à une seule équipe. Leur présence dans le code facilite le travail avec celui-ci, le rend plus compréhensible et visuel. Cependant, vous devez toujours être prudent - dans certains cas, les macros, au contraire, aggravent la situation.

Introduction.

Le langage dans lequel le programme original est écrit est appelé saisir langue, et la langue dans laquelle il est traduit pour exécution par le processeur - fin de semaine Langue. Le processus de conversion d'une langue d'entrée en une langue de sortie est appelé diffuser.Étant donné que les processeurs sont capables d'exécuter des programmes en langage machine binaire, qui n'est pas utilisé pour la programmation, la traduction de tous les programmes sources est nécessaire. connu deux manières traductions : compilation et interprétation.

À compilation le programme source est d'abord complètement traduit en un programme équivalent dans la langue cible, appelé objet programme puis exécuté. Ce processus est effectué à l'aide d'un programmes, appelé compilateur. Un compilateur pour lequel le langage d'entrée est une représentation symbolique du langage machine (de sortie) des codes binaires est appelé assembleur.

À interprétations chaque ligne de texte du programme source est analysée (interprétée) et la commande qui y est spécifiée est immédiatement exécutée. La mise en œuvre de cette méthode repose sur programme d'interprétation. L'interprétation prend beaucoup de temps. Pour augmenter son efficacité, au lieu de traiter chaque ligne, l'interpréteur convertit au préalable toutes commande chaînes en caractères (

). La séquence de symboles générée est utilisée pour exécuter les fonctions attribuées au programme d'origine.

Le langage d'assemblage décrit ci-dessous est implémenté à l'aide de la compilation.

Caractéristiques de la langue.

Les principales caractéristiques de l'assembleur :

● au lieu de codes binaires, le langage utilise des noms symboliques - mnémotechnique. Par exemple, pour la commande d'addition (

) mnémonique est utilisé

Soustractions (

multiplier (

Divisions (

etc. Des noms symboliques sont également utilisés pour adresser des cellules de mémoire. Pour programmer en langage assembleur, au lieu de codes binaires et d'adresses, vous n'avez besoin de connaître que les noms symboliques que l'assembleur traduit en codes binaires;

chaque énoncé correspond une commande machine(code), c'est-à-dire qu'il existe une correspondance biunivoque entre les instructions machine et les opérateurs dans un programme en langage assembleur ;

● la langue donne accès à tous les objets et équipes. Langues haut niveau n'ont pas une telle capacité. Par exemple, le langage d'assemblage vous permet de vérifier un bit de registre d'indicateur et un langage de haut niveau (par exemple,

) n'a pas cette capacité. Notez que les langages de programmation système (par exemple, C) occupent souvent une position intermédiaire. En termes d'accessibilité, ils sont plus proches du langage d'assemblage, mais ils ont la syntaxe d'un langage de haut niveau ;

● langage d'assemblage n'est pas une langue universelle. Chaque groupe spécifique de microprocesseurs possède son propre assembleur. Les langages de haut niveau n'ont pas cet inconvénient.

Contrairement aux langages de haut niveau, écrire et déboguer un programme en langage assembleur prend beaucoup de temps. Malgré cela, le langage d'assemblage est devenu large utilisation en raison des circonstances suivantes :

● Un programme écrit en langage assembleur a une petites tailles et est beaucoup plus rapide qu'un programme écrit dans un langage de haut niveau. Pour certaines applications, ces indicateurs jouent un rôle primordial, par exemple, de nombreux programmes système (y compris des compilateurs), des programmes de cartes de crédit, téléphones portables, pilotes de périphériques, etc. ;

● Certaines procédures nécessitent un accès complet au matériel, ce qui n'est généralement pas possible dans un langage de haut niveau. Ce cas inclut les interruptions et les gestionnaires d'interruptions dans systèmes d'exploitation, ainsi que des contrôleurs de dispositifs dans des systèmes embarqués fonctionnant en temps réel.

Dans la plupart des programmes, seul un petit pourcentage du code total est responsable d'un grand pourcentage du temps d'exécution du programme. En règle générale, 1 % du programme est responsable de 50 % du temps d'exécution et 10 % du programme est responsable de 90 % du temps d'exécution. Par conséquent, écrire programme spécifique dans des conditions réelles, l'assembleur et l'un des langages de haut niveau sont utilisés.

Format d'opérateur en langage assembleur.

Un programme en langage assembleur est une liste de commandes (instructions, phrases), dont chacune occupe une ligne distincte et contient quatre champs : un champ d'étiquette, un champ d'opération, un champ d'opérande et un champ de commentaire. Chaque champ a une colonne distincte.

Champ d'étiquette.

La colonne 1 est allouée au champ de libellé. Un libellé est un nom symbolique, ou identifiant, adresses Mémoire. Il est nécessaire pour pouvoir :

● faire une transition conditionnelle ou inconditionnelle vers la commande ;

● accéder à l'endroit où les données sont stockées.

Ces déclarations sont étiquetées. Pour désigner un nom, on utilise des lettres (majuscules) de l'alphabet anglais et des chiffres. Le nom doit commencer par une lettre et se terminer par deux-points. L'étiquette deux-points peut être écrite sur une ligne séparée, et l'opcode peut être écrit sur la ligne suivante dans la colonne 2, ce qui simplifie le travail du compilateur. L'absence de deux-points rend impossible la distinction entre une étiquette et un opcode s'ils sont sur des lignes séparées.

Dans certaines versions du langage d'assemblage, les deux-points sont placés uniquement après les étiquettes d'instructions, pas après les étiquettes de données, et la longueur des étiquettes peut être limitée à 6 ou 8 caractères.

Le champ label ne doit pas contenir les mêmes noms, puisque le label est associé aux adresses des commandes. Si pendant l'exécution du programme, il n'est pas nécessaire d'appeler une commande ou des données de la mémoire, le champ d'étiquette reste vide.

Champ de code de transaction.

Ce champ contient le mnémonique ou la pseudo-commande de la commande (voir ci-dessous). Le code mnémonique de la commande est choisi par les développeurs du langage. En langage assembleur

mnémonique sélectionné pour charger le registre depuis la mémoire

), et de stocker le contenu du registre en mémoire - le mnémonique

). Dans les langages d'assemblage

vous pouvez utiliser le même nom pour les deux opérations, respectivement

Si le choix des noms mnémoniques peut être arbitraire, alors la nécessité d'utiliser deux instructions machine est due à l'architecture du processeur

Les mnémoniques des registres dépendent également de la version de l'assembleur (tableau 5.2.1).

Champ opérande.

Ici se trouve Informations Complémentaires nécessaire pour effectuer l'opération. Dans le champ des opérandes pour les instructions de saut, l'adresse où vous voulez sauter est indiquée, ainsi que les adresses et les registres qui sont des opérandes pour l'instruction machine. A titre d'exemple, voici les opérandes utilisables pour les processeurs 8 bits

● données numériques,

Présenté dans divers systèmes compte. Pour indiquer le système de numération utilisé, la constante est suivie d'une des lettres latines : B,

Respectivement binaire, octal, hexadécimal, système décimal compte (

peut ne pas être enregistré). Si le premier chiffre du nombre hexadécimal est A, B, C,

Ensuite, un 0 (zéro) non significatif est ajouté devant ;

● codes des registres internes du microprocesseur et des cellules mémoire

M (sources ou récepteurs d'informations) sous la forme des lettres A, B, C,

M ou leurs adresses dans n'importe quel système de numérotation (par exemple, 10V - adresse de registre

en système binaire);

● identifiants,

pour les paires d'avions immatriculés,

Les premières lettres B

H; pour une paire d'accumulateur et de registre de fonctions -

; pour le compteur de programme -

; pour le pointeur de pile -

● étiquettes indiquant les adresses des opérandes ou instructions suivantes au conditionnel

(lorsque la condition est remplie) et transitions inconditionnelles. Par exemple, l'opérande M1 dans la commande

signifie la nécessité d'une transition inconditionnelle vers la commande, dont l'adresse dans le champ d'étiquette est marquée avec l'identifiant M1 ;

● expressions,

qui sont construits en reliant les données décrites ci-dessus à l'aide d'opérateurs arithmétiques et logiques. Notez que la manière dont l'espace de données est réservé dépend de la version du langage. Développeurs de langage d'assemblage pour

Définir le mot), et introduit plus tard Option alternative.

qui dès le début était dans le langage des processeurs

En version linguistique

utilisé

définir une constante).

Les processeurs traitent des opérandes de longueurs différentes. Pour le définir, les développeurs assembleurs ont pris différentes décisions, par exemple :

Les registres II de différentes longueurs ont des noms différents : EAX - pour placer des opérandes 32 bits (type

); AX - pour 16 bits (type

et AN - pour 8 bits (type

● pour les processeurs

des suffixes sont ajoutés à chaque opcode : suffix

Pour le genre

; suffixe ".B" pour le type

pour des opérandes de longueurs différentes, différents opcodes sont utilisés, par exemple pour charger un octet, un demi-mot (

) et les mots dans le registre 64 bits utilisent des opcodes

respectivement.

Champ de commentaires.

Ce champ fournit des explications sur les actions du programme. Les commentaires n'affectent pas le fonctionnement du programme et sont destinés à une personne. Ils peuvent être nécessaires pour modifier un programme qui, sans ces commentaires, peut être complètement incompréhensible même pour les programmeurs expérimentés. Un commentaire commence par un caractère et est utilisé pour expliquer et documenter les programmes. Le caractère de début d'un commentaire peut être :

● point-virgule (;) dans les langues pour les sous-traitants de l'entreprise

Point d'exclamation(!) dans les langues pour

Chaque ligne distincte réservée à un commentaire est précédée d'un caractère de début.

Pseudo commandes (directives).

En langage assembleur, on distingue deux grands types de commandes :

de base instructions équivalentes au code machine du processeur. Ces commandes effectuent tout le traitement fourni par le programme ;

pseudo-commandes ou directives, conçu pour servir le processus de traduction du programme dans le langage des combinaisons de codes. A titre d'exemple, dans le tableau. 5.2.2 montre quelques pseudo-commandes de l'as-assembleur

pour la famille

.

Lors de la programmation, il existe des situations où, selon l'algorithme, la même chaîne de commandes doit être répétée plusieurs fois. Pour sortir de cette situation, vous pouvez :

● écrire la séquence de commandes souhaitée chaque fois qu'elle se produit. Cette approche conduit à une augmentation du volume du programme ;

● organiser cette séquence dans une procédure (sous-programme) et l'appeler si nécessaire. Une telle sortie a ses inconvénients : il faut à chaque fois exécuter une instruction d'appel de procédure spéciale et une instruction de retour, ce qui, avec une séquence courte et fréquemment utilisée, peut fortement réduire la vitesse du programme.

Le plus simple et méthode efficace la répétition répétée d'une chaîne de commandes consiste à utiliser macro, qui peut être considéré comme une pseudo-commande destinée à retraduire un groupe de commandes fréquemment rencontrées dans un programme.

Une macro, ou instruction de macro, est caractérisée par trois aspects : la définition de macro, l'inversion de macro et l'expansion de macro.

macro définition

Il s'agit d'une désignation pour une séquence répétée de commandes de programme, utilisée pour les références dans le texte du programme.

Une macro a la structure suivante :

Liste d'expressions ; macro définition

La structure de définition de macro ci-dessus comporte trois parties :

● en-tête

macro contenant le nom

Pseudo-commande

et un ensemble de paramètres ;

● pointillé corps macro;

● équipe

l'obtention du diplôme

macro définitions.

Un jeu de paramètres de macro contient une liste de tous les paramètres indiqués dans le champ d'opérande pour le groupe d'instructions sélectionné. Si ces paramètres sont donnés plus tôt dans le programme, ils peuvent être omis dans l'en-tête de définition de macro.

Pour le réassemblage du groupe d'instructions sélectionné, un appel est utilisé, composé du nom

macro et liste de paramètres avec d'autres valeurs.

Lorsque l'assembleur rencontre une définition de macro lors de la compilation, il la stocke dans la table de définition de macro. Avec des apparitions ultérieures dans le programme du nom (

) d'une macro, l'assembleur le remplace par le corps de la macro.

L'utilisation d'un nom de macro comme opcode s'appelle macro-inversion(appel de macro), et son remplacement par le corps de la macro - extension macro.

Si le programme est représenté par une séquence de caractères (lettres, chiffres, espaces, ponctuation et retour chariot pour passer à nouvelle ligne), alors la macro-expansion consiste à remplacer certaines chaînes de cette séquence par d'autres chaînes.

L'expansion de la macro se produit pendant le processus d'assemblage, pas pendant l'exécution du programme. Les manières de manipuler les chaînes de caractères sont attribuées à outils macros.

Le processus d'assemblage est effectué en deux passes :

● Lors de la première passe, toutes les définitions de macros sont conservées et les appels de macros sont développés. Dans ce cas, le programme source est lu et converti en un programme dans lequel toutes les définitions de macro sont supprimées, et chaque appel de macro est remplacé par un corps de macro ;

● La deuxième passe traite le programme reçu sans macros.

Macros avec paramètres.

Pour travailler avec des séquences de commandes répétitives, dont les paramètres peuvent prendre différentes valeurs, des définitions de macro sont fournies :

● avec réel les paramètres qui sont placés dans le champ opérande de l'appel de macro ;

● avec officiel paramètres. Lors du développement de la macro, chaque paramètre formel qui apparaît dans le corps de la macro est remplacé par le paramètre réel correspondant.

en utilisant des macros avec des paramètres.

Le programme 1 montre deux séquences de commandes similaires, différant en ce que la première permute P et

Et le deuxième

Le programme 2 comprend une macro avec deux paramètres formels P1 et P2. Lors de l'expansion de la macro, chaque caractère P1 à l'intérieur du corps de la macro est remplacé par le premier paramètre réel (P,

), et le symbole P2 est remplacé par le deuxième paramètre réel (

) du programme n° 1. Dans un appel de macro

le programme 2 est marqué : P,

Le premier paramètre réel,

Le deuxième paramètre réel.

Programme 1

Programme 2

MOV EBX,Q MOV EAX,Pl

MOV Q,EAX MOV EBX,P2

MOV P,EBX MOV P2,EAX

Capacités étendues.

Considérez quelques fonctionnalités avancées du langage

Si une macro contenant une instruction de branchement conditionnel et une étiquette vers laquelle sauter est appelée deux fois ou plus, l'étiquette sera dupliquée (problème de duplication d'étiquette), ce qui provoquera une erreur. Par conséquent, chaque appel se voit attribuer (par le programmeur) une étiquette distincte en tant que paramètre. En langue

le label est déclaré local (

) et grâce aux fonctionnalités avancées, l'assembleur génère automatiquement une étiquette différente à chaque expansion de la macro.

vous permet de définir des macros à l'intérieur d'autres macros. Cette fonction avancée est très utile lorsqu'elle est associée à une liaison conditionnelle de programmes. Envisager

SI WORDSIZE GT 16 M2 MACRO

La macro M2 peut être définie dans les deux parties de la déclaration

Cependant, la définition varie selon que le programme est assemblé sur un processeur 16 bits ou 32 bits. Si M1 n'est pas appelée, alors la macro M2 ne sera pas définie du tout.

Une autre fonctionnalité avancée est que les macros peuvent appeler d'autres macros, y compris elles-mêmes - récursif appel. Dans ce dernier cas, afin d'éviter une boucle infinie, la macro doit se passer un paramètre, qui change à chaque expansion, et aussi Chèque ce paramètre et termine la récursivité lorsque le paramètre atteint une certaine valeur.

Sur l'utilisation des macros en assembleur.

Lors de l'utilisation de macros, l'assembleur doit être capable d'effectuer deux fonctions : enregistrer les définitions de macro et développer les appels de macro.

Enregistrement des définitions de macro.

Tous les noms de macro sont stockés dans une table. Chaque nom est accompagné d'un pointeur sur la macro correspondante afin de pouvoir l'appeler si nécessaire. Certains assembleurs ont une table séparée pour les noms de macros, d'autres ont une table commune dans laquelle, avec les noms de macros, il y a toutes les commandes et directives de la machine.

Lorsque vous rencontrez une macro lors de l'assemblage établi:

nouvel élément les tables avec le nom de la macro, le nombre de paramètres et un pointeur vers une autre table de définition de macro où le corps de la macro sera stocké ;

● liste officiel paramètres.

Le corps de la macro, qui est simplement une chaîne de caractères, est ensuite lu et stocké dans la table de définition de macro. Les paramètres formels apparaissant dans le corps de la boucle sont marqués Caractère spécial.

Représentation interne d'une macro

de l'exemple ci-dessus pour le programme 2 (p. 244) est :

MOV EAX, MOV EBX, MOV MOV &

où le point-virgule est utilisé comme caractère de retour chariot et l'esperluette & est utilisé comme caractère de paramètre formel.

Extension d'appel macro.

Chaque fois qu'une définition de macro est rencontrée lors de l'assemblage, elle est stockée dans la table des macros. Lorsqu'une macro est appelée, l'assembleur suspend temporairement la lecture des données d'entrée à partir du périphérique d'entrée et commence à lire le corps de la macro enregistrée. Les paramètres formels extraits du corps de la macro sont remplacés par les paramètres réels et fournis par l'appel. Une esperluette & devant les paramètres permet à l'assembleur de les reconnaître.

Bien qu'il existe de nombreuses versions d'assembleur, les processus d'assemblage ont des caractéristiques communes et sont similaires à bien des égards. Le travail d'un assembleur à deux passes est considéré ci-dessous.

Assembleur en deux passes.

Le programme se compose d'un certain nombre d'opérateurs. Par conséquent, il semblerait que la séquence d'actions suivante puisse être utilisée lors de l'assemblage :

● le traduire en langage machine ;

● transférer le code machine reçu dans un fichier et la partie correspondante de la liste - dans un autre fichier ;

● répéter les procédures ci-dessus jusqu'à ce que l'intégralité du programme soit diffusée.

Cependant, cette approche n'est pas efficace. Un exemple est le soi-disant problème lien principal. Si la première instruction est un saut à l'instruction P à la toute fin du programme, l'assembleur ne peut pas la traduire. Il doit d'abord déterminer l'adresse de l'opérateur P, et pour cela il est nécessaire de lire tout le programme. Chaque lecture complète du programme original est appelée passage. Montrons comment nous pouvons résoudre le problème de référence directe en utilisant deux passes :

au premier passage recueillir et stockez toutes les définitions de symboles (y compris les étiquettes) dans le tableau, et lors de la deuxième passe, lisez et assemblez chaque opérateur. Cette méthode est relativement simple, mais le deuxième passage dans le programme d'origine nécessite un temps d'E/S supplémentaire ;

● au premier passage, convertir programme dans un formulaire intermédiaire et enregistrez-le dans un tableau, et la deuxième passe est effectuée non pas selon le programme d'origine, mais selon le tableau. Cette méthode d'assemblage permet de gagner du temps, car aucune opération d'E/S n'est effectuée lors de la deuxième passe.

Premier passage.

But du premier passage- construire une table de symboles. Comme indiqué ci-dessus, un autre objectif de la première passe est d'enregistrer toutes les définitions de macro et de développer les appels au fur et à mesure qu'ils apparaissent. Par conséquent, la définition des caractères et l'expansion des macros se produisent dans la même passe. Le symbole peut être soit étiquette, ou sens, qui reçoit un nom spécifique à l'aide de la directive -you :

;Valeur - taille de la mémoire tampon

En donnant une signification aux noms symboliques dans le champ d'étiquette d'instruction, l'assembleur définit essentiellement les adresses que chaque instruction aura lors de l'exécution du programme. Pour ce faire, l'assembleur lors du processus d'assemblage enregistre compteur d'adresses d'instructions(

) comme variable spéciale. Au début de la première passe, la valeur de la variable spéciale est définie sur 0 et incrémentée après chaque commande traitée de la longueur de cette commande. A titre d'exemple, dans le tableau. 5.2.3 montre un fragment du programme indiquant la longueur des commandes et les valeurs des compteurs. Les tableaux sont générés lors de la première passe noms de symboles, directives et codes de fonctionnement, et si nécessaire littéral table. Un littéral est une constante pour laquelle l'assembleur réserve automatiquement de la mémoire. On remarque tout de suite que les processeurs modernes contiennent des instructions avec des adresses directes, donc leurs assembleurs ne supportent pas les littéraux.

Tableau des symboles

contient un élément pour chaque nom (tableau 5.2.4). Chaque élément de la table des symboles contient le nom lui-même (ou un pointeur vers celui-ci), sa valeur numérique et parfois des informations supplémentaires, qui peuvent inclure :

● la longueur du champ de données associé au symbole ;

● bits de remappage mémoire (qui indiquent si la valeur d'un symbole change si le programme est chargé à une adresse différente de celle prévue par l'assembleur) ;

● des informations indiquant si le symbole est accessible depuis l'extérieur de la procédure.

Les noms symboliques sont des étiquettes. Ils peuvent être spécifiés à l'aide d'opérateurs (par exemple,

Tableau des directives.

Ce tableau répertorie toutes les directives, ou pseudo-commandes, qui surviennent lors de l'assemblage d'un programme.

Tableau des codes d'opération.

Pour chaque opcode, le tableau comporte des colonnes distinctes : désignation de l'opcode, opérande 1, opérande 2, valeur hexadécimale de l'opcode, longueur de l'instruction et type d'instruction (tableau 5.2.5). Les codes d'opération sont divisés en groupes selon le nombre et le type d'opérandes. Le type de commande détermine le numéro de groupe et spécifie la procédure qui est appelée pour traiter toutes les commandes de ce groupe.

Deuxième passe.

But de la deuxième passe- créer un programme objet et imprimer, si nécessaire, un protocole d'assemblage ; les informations de sortie nécessaires à l'éditeur de liens pour lier des procédures qui ont été assemblées à différents moments dans un fichier exécutable.

Dans la deuxième passe (comme dans la première), les lignes contenant les instructions sont lues et traitées les unes après les autres. L'opérateur d'origine et la sortie qui en est dérivée en hexadécimal objet le code peut être imprimé ou mis en mémoire tampon pour une impression ultérieure. Après avoir réinitialisé le compteur d'adresse de commande, l'instruction suivante est appelée.

Le programme d'origine peut contenir des erreurs, par exemple :

le symbole donné n'est pas défini ou défini plus d'une fois ;

● L'opcode est représenté par un nom invalide (en raison d'une faute de frappe), n'est pas fourni avec suffisamment d'opérandes ou contient trop d'opérandes ;

● pas d'opérateur

Certains assembleurs peuvent détecter un symbole indéfini et le remplacer. Cependant, dans la plupart des cas, lorsqu'une instruction contenant une erreur est trouvée, l'assembleur affiche un message d'erreur à l'écran et tente de poursuivre le processus d'assemblage.

Articles dédiés au langage assembleur.

Informations générales sur le langage d'assemblage

Le langage d'assemblage symbolique permet d'éliminer en grande partie les lacunes de la programmation en langage machine.

Son principal avantage est qu'en langage assembleur tous les éléments du programme sont représentés sous forme symbolique. La transformation des noms de commandes symboliques en leurs codes binaires est de la responsabilité de programme spécial- assembleur, qui libère le programmeur d'un travail laborieux et élimine les erreurs inévitables.

Les noms symboliques introduits lors de la programmation en langage d'assemblage reflètent généralement la sémantique du programme et l'abréviation des commandes - leur fonction principale. Par exemple : PARAM - paramètre, TABLE - table, MASK - masque, ADD - addition, SUB - soustraction, etc. n. De tels noms sont facilement mémorisés par le programmeur.

Pour programmer en langage assembleur, il faut disposer d'outils plus complexes que pour programmer en langage machine : il faut des systèmes informatiques à base de micro-ordinateurs ou de PC avec un ensemble périphériques(clavier alphanumérique, afficheur de caractères, lecteur de disquette et imprimante), ainsi que des systèmes de programmation résidente ou croisée pour les types de microprocesseurs requis. Le langage d'assemblage vous permet d'écrire et de déboguer efficacement des programmes beaucoup plus complexes que le langage machine (jusqu'à 1 à 4 Ko).

Les langages d'assemblage sont orientés machine, c'est-à-dire dépendants du langage machine et de la structure du microprocesseur correspondant, puisqu'ils attribuent un nom symbolique spécifique à chaque instruction du microprocesseur.

Les langages d'assemblage offrent une augmentation significative de la productivité des programmeurs par rapport aux langages machine et conservent en même temps la possibilité d'utiliser toutes les ressources matérielles accessibles par logiciel du microprocesseur. Cela permet aux programmeurs expérimentés d'écrire des programmes qui s'exécutent plus rapidement et occupent moins de mémoire que les programmes écrits dans un langage de haut niveau.

À cet égard, presque tous les programmes de contrôle de périphériques d'E / S (pilotes) sont écrits en langage d'assemblage, malgré la présence d'une gamme assez large de langages de haut niveau.

En utilisant le langage assembleur, le programmeur peut définir les paramètres suivants :

mnémonique (nom symbolique) de chaque commande du langage machine du microprocesseur ;

format standard des lignes d'un programme décrit en assembleur ;

format de spécification différentes manières options d'adressage et de commande ;

format pour spécifier des constantes de caractères et des constantes de type entier dans divers systèmes de numération ;

pseudo-commandes qui contrôlent le processus d'assemblage (traduction) du programme.

En langage assembleur, le programme est écrit ligne par ligne, c'est-à-dire qu'une ligne est allouée à chaque instruction.

Pour les micro-ordinateurs construits sur la base des types de microprocesseurs les plus courants, il peut exister plusieurs variantes de langage d'assemblage, cependant, on a généralement une distribution pratique - c'est ce qu'on appelle le langage d'assemblage standard

La programmation au niveau des instructions machine est le niveau minimum auquel la programmation est possible. Le système d'instructions machine doit être suffisant pour mettre en œuvre les actions requises en envoyant des instructions au matériel informatique.

Chaque instruction machine se compose de deux parties :

fonctionnement - déterminer "que faire" ;

· opérande - définissant les objets de traitement, "que faire avec".

L'instruction machine du microprocesseur, écrite en langage assembleur, est une seule ligne avec la forme syntaxique suivante :

label commande/directive opérande(s) ; commentaires

Dans ce cas, un champ obligatoire dans une ligne est une commande ou une directive.

L'étiquette, la commande/directive et les opérandes (le cas échéant) sont séparés par au moins un espace ou un caractère de tabulation.

Si une commande ou une directive doit être poursuivie sur la ligne suivante, le caractère barre oblique inverse est utilisé : \.

Par défaut, le langage d'assemblage ne fait pas la distinction entre les lettres majuscules et minuscules dans les commandes ou les directives.

Adressage direct: L'adresse effective est déterminée directement par le champ de décalage d'instruction machine, qui peut avoir une taille de 8, 16 ou 32 bits.

mov eax, somme ; eax = somme

L'assembleur remplace sum par l'adresse correspondante stockée dans le segment de données (par défaut, adressée par le registre ds) et place la valeur stockée à l'adresse sum dans le registre eax.

adressage indirectà son tour a les types suivants:

Adressage de base indirect (registre);

Adressage de base indirect (registre) avec décalage ;

· adressage d'index indirect ;

· adressage indirect d'index de base.

Adressage de base indirect (registre). Avec cet adressage, l'adresse effective de l'opérande peut être dans n'importe lequel des registres usage général, sauf pour sp/esp et bp/ebp (ce sont des registres spécifiques pour travailler avec un segment de pile). Syntaxiquement dans une instruction, ce mode d'adressage s'exprime en mettant le nom du registre entre crochets.

déplacer eax, ; eax = *esi; *valeur esi à l'adresse esi

Structures en langage assembleur

Les tableaux que nous avons considérés ci-dessus sont une collection d'éléments du même type. Mais souvent, dans les applications, il est nécessaire de prendre en compte un certain ensemble de données type différent comme un seul type.

Ceci est très pertinent, par exemple, pour les programmes de base de données, où il est nécessaire d'associer une collection de données de différents types à un objet.

Par exemple, nous avons précédemment examiné le Listing 4, qui fonctionnait avec un tableau d'éléments de trois octets. Chaque élément, à son tour, était constitué de deux éléments de types différents : un champ de compteur d'un octet et un champ de deux octets pouvant contenir des informations supplémentaires nécessaires au stockage et au traitement. Si le lecteur est familier avec l'un des langages de haut niveau, alors il sait qu'un tel objet est généralement décrit à l'aide d'un type de données spécial - structures.

Afin d'améliorer la convivialité du langage d'assemblage, ce type de données y a également été introduit.

Par définition structure est un type de données composé d'un nombre fixe d'éléments de types différents.

Pour utiliser des structures dans un programme, vous devez faire trois choses :

    Interroger modèle de structure .

    Essentiellement, cela signifie définir un nouveau type de données, qui pourra ensuite être utilisé pour définir des variables de ce type.

    Définir exemple de structure .

    Cette étape implique l'initialisation d'une variable spécifique avec une structure prédéfinie (à l'aide d'un modèle).

    Organiser accéder aux membres de la structure .

Il est très important que vous compreniez dès le début quelle est la différence entre la description structures du programme et ses définition.

décris la structure dans un programme signifie uniquement indiquer son schéma ou son modèle ; la mémoire n'est pas allouée.

Ce modèle ne peut être considéré que comme une information pour le traducteur sur l'emplacement des champs et leur valeur par défaut.

Définir structure signifie demander au traducteur d'allouer de la mémoire et d'attribuer un nom symbolique à cette zone mémoire.

Vous ne pouvez décrire la structure dans le programme qu'une seule fois et la définir autant de fois que vous le souhaitez.

Description du modèle de structure

La déclaration du modèle de structure a la syntaxe suivante :

nom_structure STRUC

nom_structure FIN

Ici est une séquence de directives de description de données db, dw, jj, dq et dt.

Leurs opérandes déterminent la taille des champs et éventuellement des valeurs initiales. Ces valeurs vont éventuellement initialiser les champs correspondants lors de la définition de la structure.

Comme nous l'avons déjà noté lors de la description du modèle, aucune mémoire n'est allouée, car il ne s'agit que d'informations pour le traducteur.

Emplacement modèle dans le programme peut être arbitraire, mais, suivant la logique du traducteur à une passe, il doit être situé avant l'endroit où la variable avec le type de cette structure est définie. Autrement dit, lors de la description d'une variable avec le type d'une structure dans un segment de données, son modèle doit être placé au début du segment de données ou avant celui-ci.

Envisagez de travailler avec des structures en utilisant l'exemple de la modélisation d'une base de données d'employés d'un certain département.

Pour simplifier, afin de s'affranchir des problèmes de conversion des informations lors de la saisie, on conviendra que tous les champs sont symboliques.

Définissons la structure d'enregistrement de cette base de données avec le modèle suivant :

Définir des données avec un type de structure

Pour utiliser la structure décrite à l'aide du modèle dans le programme, il est nécessaire de définir une variable avec le type de cette structure. La syntaxe suivante est utilisée pour cela :

[nom de variable] nom_structure

    Nom de variable- identificateur de variable du type structurel donné.

    La spécification d'un nom de variable est facultative. S'il n'est pas spécifié, une zone mémoire de la taille de la somme des longueurs de tous les éléments de la structure sera simplement allouée.

    liste de valeurs- une liste séparée par des virgules des valeurs initiales des éléments de structure entre crochets.

    Sa tâche est également facultative.

    Si la liste est incomplète, tous les champs de la structure de la variable donnée sont initialisés avec les valeurs du modèle, le cas échéant.

    Il est permis d'initialiser des champs individuels, mais dans ce cas, les champs manquants doivent être séparés par des virgules. Les champs manquants seront initialisés avec les valeurs du modèle de structure. Si, lors de la définition d'une nouvelle variable avec le type de cette structure, nous sommes d'accord avec toutes les valeurs de champ ​​​​dans son modèle (c'est-à-dire défini par défaut), alors il vous suffit d'écrire des crochets angulaires.

    Par exemple: ouvrier vainqueur.

Par exemple, définissons plusieurs variables avec le type de la structure décrite ci-dessus.

Méthodes structurées

L'idée d'introduire un type structurel dans n'importe quel langage de programmation est de combiner des variables de différents types en un seul objet.

Le langage doit fournir un moyen d'accéder à ces variables dans une instance de structure particulière. Pour faire référence dans une commande à un champ d'une certaine structure, un opérateur spécial est utilisé - symbole ". " (point). Il est utilisé dans la syntaxe suivante :

    adresse_expression- un identificateur de variable d'un certain type structurel ou une expression entre parenthèses conformément aux règles de syntaxe indiquées ci-dessous (Fig. 1) ;

    structure_field_name- nom de champ du modèle de structure.

    Ceci, en fait, est aussi une adresse, ou plutôt, le décalage du champ depuis le début de la structure.

Donc l'opérateur " . " (point) évalue l'expression

Riz. 5. Syntaxe d'une expression d'adresse dans un opérateur d'accès à un champ de structure

Démontrons sur l'exemple de la structure que nous avons définie ouvrier quelques techniques pour travailler avec des structures.

Par exemple, extrayez vers hache valeurs de champ avec l'âge. Puisqu'il est peu probable que l'âge d'une personne valide soit supérieur à 99 ans, après avoir placé le contenu de ce champ de caractère dans le registre hache il sera commode de le convertir en représentation binaire avec la commande un ad.

Attention, car en raison du principe de stockage des données "octet bas à l'adresse basse" le chiffre le plus élevé de l'âge sera placé dans Al, et le plus jeune de Ah.

Pour le corriger, il suffit d'utiliser la commande xchg al, ah:

mov hache,mot ptr sotr1.age ;à tout âge sotr1

et c'est possible comme ça :

Le travail ultérieur avec un réseau de structures est effectué de la même manière qu'avec un réseau unidimensionnel. Plusieurs questions se posent ici :

Comment gérer la taille et comment organiser l'indexation des éléments du tableau ?

Comme les autres identificateurs définis dans le programme, le traducteur attribue au nom du type de structure et au nom de la variable avec le type de structure un attribut de type. La valeur de cet attribut est la taille en octets occupée par les champs de cette structure. Vous pouvez extraire cette valeur en utilisant l'opérateur taper.

Une fois la taille d'une instance de structure connue, organiser l'indexation dans un tableau de structures n'est pas particulièrement difficile.

Par exemple:

Comment copier un champ d'une structure vers le champ correspondant d'une autre structure ? Ou comment copier la structure entière? Copions le champ nom troisième employé sur le terrain nom cinquième employé :

mas_sotr travailleur 10 dup()

mov bx, décalage mas_sotr

mov si,(type worker)*2 ;si=77*2

mov di,(type worker)*4 ;si=77*4

Il me semble que le métier de programmeur fait tôt ou tard ressembler une personne à une bonne femme au foyer. Lui, comme elle, est constamment à la recherche d'où économiser quelque chose, réduire et faire un merveilleux dîner avec un minimum de nourriture. Et si cela réussit, alors la satisfaction morale n'est pas moindre, et peut-être plus, qu'un merveilleux dîner chez la femme au foyer. Le degré de cette satisfaction, me semble-t-il, dépend du degré d'amour pour son métier.

D'autre part, les progrès dans le développement de logiciels et de matériel détendent quelque peu le programmeur, et il se produit assez souvent une situation similaire au proverbe bien connu sur la mouche et l'éléphant - pour résoudre un petit problème, des outils lourds sont impliqués, dont l'efficacité, dans le cas général, n'est significative que lors de la mise en œuvre de projets relativement importants.

La présence dans le langage des deux types de données suivants est probablement due au désir de «l'hôtesse» d'utiliser le plus efficacement possible la zone de travail de la table (RAM) lors de la préparation des aliments ou du placement des produits (données du programme ).