assembleur

Le langage assembleur

Un langage d’assemblage ou langage assembleur est, en programmation informatique, le langage de plus bas niveau qui représente le langage machine sous une forme lisible par un humain. (wiki)

Le premier programme assembleur a été écrit par Nathaniel Rochester pour l’IBM 701 (le premier ordinateur commercialisé par IBM) en 1954.

exemple de programme assembleur pour  le microprocessor Motorola 6800 8-bit  - source :

exemple de programme assembleur pour le microprocessor Motorola 6800 8-bit - source :

Pour échanger des données avec la mémoire, le processeur transfert l’état d’un registre dans une case mémoire (STR) ou l’état d’une case mémoire dans un registre (LDR). On rappelle que la mémoire contient à la fois les instructions et les données.

D’ailleurs, une instruction machine est une chaine binaire composée de 2 parties:

  • un champ “code opération” qui indique au processeur le type de traitement à effectuer.
  • un champ opérande qui indique l’adresse des données.

Le simulateur

  • Lancer le simulateur

    clic droit > ouvrir dans un nouvel onglet pour lancer le simulateur ARM

    clic droit > ouvrir dans un nouvel onglet pour lancer le simulateur ARM

  • Explications en video

    Explications (video) sur le simulateur ARM -

    Explications (video) sur le simulateur ARM -

Les 3 familles d’instructions machine

Ce sont les instructions:

  • de transfert de données
  • arithmétiques
  • de rupture de séquence

Transfert de données

Les opérations de transfert se font d’un registre vers un emplacement mémoire, ou l’inverse.

Ordre Instruction Description en langage naturel
Affectation (variable) x: 23 Place 23 dans la variable x, c’est à dire 23 dans l’emplacement RAM prévu pour x
Affectation (registre) MOV R1, #23 Place la valeur 23 dans le registre R1
Charger LDR R1, 78 LOAD: Place dans le registre R1 la valeur stockée à l’emplacement 78 de la RAM
Stocker STR R1, 151 STORE: Place dans la RAM à l’emplacement 151, la valeur stockée dans le registre R1
Stocker STR R1, x STORE: Place dans la RAM à l’emplacement prévu pour x, la valeur stockée dans le registre R1

Exemple 1:

Le programme suivant affecte une valeur dans un registre, puis la copie dans la RAM.

      MOV R0, #16
      STR R0, 55
      HALT

Copier-coller le script, assembler. Régler le bouton OPTIONS sur hex

question a: Vérifier que 16 (base 10) = 10 (base 16).

question b: Combien de lignes fait le programme? Quelles sont les adresses dans la RAM des instructions (donner la somme colonne + ligne)?

Dérouler le script pas à pas (appuis successifs sur STEP)

question c: Quel est le registre utilisé? Quelle est la valeur déplacée? Quelle adresse de la RAM va contenir la valeur à stocker?

question d: Si l’on suppose que la complexité temporelle est égale au nombre de fois qu’il faut appuyer sur le bouton STEP pour arriver à la dernière ligne du programme: Quelle est la compléxité de ce programme?

Exemple 2: échange de valeurs

Dans un programme en assembleur, il sera plus facile de manipuler des variables que des adresses mémoires.

      LDR R0, x
      LDR R1, y
      STR R0, y
      STR R1, x
      HALT
      0
      0
      0
x:    23
y:    18

Copier-coller le script, assembler.

question a: Vérifier que 23 (base 10) = 12 (base 16), et que 18 (base 10) = 12 (base 16).

question b: Combien de lignes fait le programme? Quelles sont les adresses dans la RAM des instructions (donner la somme colonne + ligne)? Quelles sont les adresses RAM des données?

Dérouler le programme à vitesse réduite.

question c: Interpréter les lignes 0 à 4 du programme (donner une explication en langage naturel).

Arithmétique

Ce sont les opérations courantes (addition, soustraction, multiplication par 2, division par 2). Elles se font depuis un registre, vers un autre registre.

Voici une liste non exaustive des instructions du simulateur ARM

Les instructions de traitement suivantes concernent uniquement les registres.

L’un de ces registres est le Program Counter, PC. Celui-ci repère l’état courant dans le programme (la ligne du script à executer).

Ordre Instruction Description en langage naturel
Ajouter ADD R0, R1, #16 Ajoute 16 à R1 et place le résultat dans R0
Ajouter ADD R0, R0, R1 Ajoute R1 à R0 et place le résultat dans R0
Soustraire SUB R0, R0, #16 Soustrait 16 à R0 et place le résultat dans R0
Ajouter ADD R0, R1, #16 Ajoute 16 à R1 et place le résultat dans R0
Multiplier par 2 LSL R0, R0, #1 déplace les bits de R0 d’un seul rang (#1) vers la gauche et place dans R0
Diviser par 2 LSR R0, R0, #1 déplace les bits de R0 d’un seul rang (#1) vers la droite et place dans R0

Exemple 3 add: programme qui ajoute 2 nombres entrés par l’utilisateur

  • INP R0,2: attend un nombre en entrée.
  • OUT Rd, nombre: affiche à l’écran. out Rd,4 affiche un nombre signé ou non(Rd,5). Rd,6 affiche en hexadécimal et Rd,7 affiche un caractère.
      INP R0,2
      INP R1,2
      ADD R2,R1,R0
      OUT R2,4
      HALT

question a: Ce programme, permet-il d’additionner $123 + (-145)$? Pourquoi?

question b: Créer un programme qui multiplie par 2 le nombre saisi par l’utilisateur (avec LSL), affiche le résultat, et le stocke dans la RAM. (ou dans une variable).

Rupture de séquence

Les ruptures de séquence utilisent des étiquettes, à définir dans le programme. Le programme va alors s’executer normalement, ligne après ligne, sauf si un branchement l’amène à une ligne, portant une etiquette.

  • HALT: arrêt du programme

  • CMP Ri, Rj: effectue la comparaison entre Ri et lRj. Attention, cette instruction ne traite pas le résultat de la comparaison! C’est le rôle de la commande suivante.

  • B ou BGT, … sont les opérations de branchement

plus grand que: On utilise une combinaison de 2 lignes pour effectuer le test si R1 > R2 aller à la ligne label:

CMP R1, R2
BGT label

est egal à: On utilise une combinaison de 2 lignes pour effectuer le test si R1 == R2 aller à la ligne label:

CMP R1, R2
BEQ label

aller systematiquement à: B label va obliger à toujours revenir à la ligne d’etiquette label

La liste complète des instructions se trouve à la page INFO accessible depuis le bouton info du simulateur.

Exemple 4 boucle infinie

Le programme s’execute de la manière suivante: ligne 0 (affectation de la valeur 16 au registre R0), puis ligne 1 (on definit une etiquette boucle), puis ligne 2 (addition R0+1), puis ligne 3, ligne 4, …

      MOV R0, #16
boucle:
      ADD R0, R0, #1
      OUT R0,4
      B boucle
      HALT

question a: Pourquoi le programme s’appelle-t-il boucle infinie?

Le test conditionnel if R0 > 20: break, qui va permettre de sortir de la boucle va s’écrire en assembleur:

CMP R0, #20
BGT break

L’étiquette break devra alors être placée après celle B boucle afin de pouvoir poursuivre le programme.

question b: Ré-écrire le script précédent afin de sortir de la boucle lorsque R0 stocke une vameur supérieure à 20.

Exemple 5 max: programme qui retourne le plus grand des 2 nombres saisis par l’utilisateur

      INP R0,2
      INP R1,2
      CMP R1,R0
      BGT HIGHER
      OUT R0,4
      B DONE
HIGHER:
      OUT R1,4
DONE:
      HALT
      // Input two numbers and output the higher

Dans ce 2eme exemple, si R1 est supérieur à R0 (test à la ligne 3), alors le programme effectue un branchement conditionnel à la ligne 4 (BGT est le branchement pour Greater Than). Il execute à ligne 4 l’appel de la fonction HIGHER), sinon il passe à la ligne 5 (OUT R0,4).

question a: qu’est ce qui est affiché si l’on saisit la valeur 18 pour R0 et 9 pour R1? Puis 10 pour R0 et 20 pour R1? question b: à quoi sert la ligne 6 B DONE? Que se passerait-il si cette ligne n’y était pas, et que l’on saisit la valeur 18 pour R0 et 9 pour R1?

Travail pratique: Assembleur

Utiliser le simulateur

Opérations simples

1. Prog 1. Il s’agit d’obtenir le nombre 84 à partir des nombres 50,25,8,7,3 et 1 avec les opérations : addition et soustraction uniquement.

Copier-coller le script dans le simulateur:

MOV R0,#50
ADD R0,R0,#25
ADD R0,R0,#8
ADD R0,R0,#1
HALT

Cliquer sur le bouton ASSEMBLE. Le simulateur va alors charger toutes les valeurs numériques dans la RAM. Choisir la représentation des nombres en hexadécimal avec le bouton OPTION > hex.

chargement des valeurs en hexadecimal

chargement des valeurs en hexadecimal

Tester le programme en le déroulant pas à pas (appuis successifs sur le bouton STEP)

2. Prog 2. Obtenir 84 à partir de 90,25,8,7,3 et 1 avec les opérations : addition et soustraction uniquement.

3. Prog 3. Obtenir 128, en partant de la valeur 1 stockée dans R0. Utilisez les instructions de multiplication par 2 du langage.

Programmer avec des boucles

1. Cliquer sur SELECT et choisir le programme max en assembleur qui affiche le plus grand de deux entiers entrés au clavier, le comprendre et l’exécuter (Bien comprendre les instructions B, CMP et BGT voir le manuel)

2. Prog 4. Ecrire en assembleur un programme utilisant des fonctions parmis LSL, LSR, B et BNE qui affiche 1 si le nombre est pair , 0 sinon. (BNE: Branchement si Not Equal).

Calculer 1+2+3…+n où n est entré au clavier:

1. Compléter le programme en assembleur ci-dessous pour résoudre le problème puis essayer avec n = 3 en mode pas à pas Exécuter avec RUN en vitesse maximale pour n = 10

INP R0,2
MOV R1,#0 // compteur de boucle
MOV R2,#0 // somme 
boucle:
ADD ...........
ADD ...........
CMP ...........
.... boucle
OUT R2,4
HALT

2. Estimer le nombre d’opérations significatives effectuées pour n = 10. Combien d’opérations significatives seraient réalisées pour n = 100?

Liens