7 Assembleur 68000
Table des matières
7.1 Objectif
Dans ce TP vous allez devoir écrire du code en langage assembleur du processeur Motorola 68000, l'assembler et vérifier son fonctionnement dans un émulateur. Une documentation complète des instructions est donnée dans le fichier M68000.pdf.
Plusieurs exercices sont similaires à ceux effectués pour l'Ordinapoche, mais adaptés à ce processeur.
7.2 Préambule
L'obtention du code machine à partir d'un fichier en langage assembleur se fait en deux étapes:
- l'assemblage: converti le programme en code machine mais ne résout pas toutes les adresses,
- l'édition de liens: résout les adresses non connues à l'assemblage.
Cette séparation vient de la gestion des code relogeables et de la possibilité d'utiliser des librairies, c'est-à-dire du code inclus dans d'autres fichiers.
La commande à utiliser pour l'étape d'assemblage est la suivante :
m68k-linux-gnu-as -ahlns --register-prefix-optional -am -m 68000
La commande à utiliser pour l'étape d'édition de lien est :
m68k-linux-gnu-ld -M --oformat srec -Ttext 0
Afin d'éviter d'écrire ces commandes avec tous ces arguments à chaque fois, vous allez définir 2 alias dans votre shell :
m68kas : pour l'assembleur
m68kld : pour l'éditeur de liens
Pour cela faut ajouter dans votre fichier de configuration du shell (fichier verb|.bashrc|) des commandes alias nom_alias='commande '.
Affichez le contenu de votre variable d'environnement PATH, et s'il n'est pas dedans, ajoutez lui le chemin /home/partage/UE23/. Vous aurez ainsi quelques caractères de moins à écrire dans le terminal pour exécuter l'émulateur.
7.3 Prise en main de l'assembleur
Soit le programme en langage assembleur suivant :
.equ A, 12 _start: move.b #A, d0 .xdef _start
Son assemblage par la commande m68kas donne l'affichage suivant :
1 .equ A,12 2 _start: 3 0000 103C 000C move.b #A,d0 4 .xdef _start DEFINED SYMBOLS {exemple.s}:1 *ABS*:0000000c A {exemple.s}:2 .text:00000000 _start NO UNDEFINED SYMBOLS
Dans la première partie, on retrouve le code et son assemblage :
la première colonne est le numéro de ligne dans le programme source,
la seconde colonne est le code machine des instructions assemblée avec son adresse en mémoire :
- 0000: est l'adresse en mémoire de cette instruction,
- 103C 000C: est l'assemblage en code machine de l'instruction et de ses paramètres.
la troisième colonne est l'instruction d'origine en langage assembleur.
Dans la seconde partie, sont listés les différents symboles (constantes, variables, labels) définis dans le programme avec les informations suivantes :
numéro de ligne de définition dans le programme source,
le type de symbole:
*ABS* : pour les constantes, leur valeur, et leur symbole,
.text : pour les variables et labels en mémoire dans le segment .text, leur adresse, et leur symbole
La troisième partie liste les symboles non définis, pouvant venir de codes externes.
S'il n'y a pas eu d'erreur, la commande génère aussi un fichier à destination de l'éditeur de liens. Sans indication de nom de fichier, le fichier généré est a.out.
Ce fichier est appelé fichier objet. Pour lui spécifier un nom il faudra passer l'option -o et le nom du fichier de sortie. Par convention, les fichiers objets ont l'extension .o.
Ce fichier n'est pas l'exécutable et n'est pas lisible.
Si tout s'est bien passé jusque là, l'étape suivante est l'édition de liens avec la commande m68ld. S'il n'y a pas d'erreur à cette étape, un fichier en code machine est généré au format SREC qui sera lisible par l'émulateur. Contrairement au fichier objet, ce format est lisible :
$> cat exemple.x S0060000742E78DF S1070000103C000CA0 S9030000FC
La première ligne est un commentaire, la seconde ligne correspond au code en langage machine (0000 103C 000C), et la dernière ligne indique le point d'entrée du programme, c'est-à-dire l'adresse de la première instruction du programme correspondant au label _start (0000).
- Si ce n'est fait, refaite ces étapes par vous-même pour vous en assurer.
7.4 Prise en main de l'émulateur
L'émulateur de processeur Motorola 68000 qui sera utilisé s'appelle pym68k. Cet émulateur accepte les fichiers au format SREC et affiche par défaut l'état des registres du CPU ainsi que le contenu de la RAM.
Avec l'exemple précédent nous obtenons :
D0: 0000000C D4: 00000000 D1: 00000000 D5: 00000000 D2: 00000000 D6: 00000000 D3: 00000000 D7: 00000000 A0: 00000000 A4: 00000000 A1: 00000000 A5: 00000000 A2: 00000000 A6: 00000000 A3: 00000000 A7/SP: 00000000 PC: 00000004 SR: ---------- 00000000 10 3C 00 0C 00 00 00 00 - 00 00 00 00 00 00 00 00
Le programme s'est exécuté et terminé, la valeur 12 se trouve bien dans le registre d0, comme escompté.
L'émulateur propose également un mode pas-à-pas pour exécuter une seule instruction à la fois et pas tout le programme.
- Tester votre programme exemple précédent sur l'émulateur.
7.5 Exercice 1: swap
Ce premier exercice simple a pour objectif de réaliser l'ensemble de la chaîne de production d'un code machine exécutable par l'émulateur sur un énoncé simple.
Écrivez le code en langage assembleur 68000 d'un programme réalisant :
- l'initialisation de l'octet faible du registre D1 à 0x11,
- l'initialisation de l'octet faible du registre D2 à 0x22,
- la permutation des deux registres.
Vérifiez le résultat de l'exécution de votre programme avec l'émulateur.
7.6 Exercice 2: swap en mémoire
Soient:
- une variable A en mémoire à l'adresse 0, de taille BYTE et initialisée à 0x11;
- une variable B en mémoire à l'adresse suivante, de taille BYTE et initialisée à 0x22;
- Écrivez un programme qui permute ces deux valeurs.
7.7 Exercice 3: décomposition de nombre
Soit un nombre décimal à 2 chiffres placé dans le registre D0 (de taille LONG). Écrivez un programme simple (sans boucle) permettant de placer :
- dans le registre D1 le chiffre des unités,
- dans le registre D2 le chiffre des dizaines.
Tester votre programme avec différentes valeur d'initialisation de D0 (≤ 999).
7.8 Exercice 4: affichage
Grâce à l'instruction trap #1 il est possible d'afficher une chaîne de caractères codée en ASCII ou en UTF-8. Pour cela il faut d'abord placer dans le registre A0 l'adresse de la chaîne en mémoire, puis faire appel à l'instruction trap.
Autre particularité à laquelle il faut préter attention, c'est que la chaîne de caractères à afficher doit absolument se terminer par le caractère NULL, c'est-à-dire la valeur 0 codée sur 1 octet. En effet, cette valeur sert de marqueur de fin de chaîne.
Écrivez un programme qui affiche la chaîne « Décomposition d'un nombre! », avec retour à la ligne.
Complétez votre programme en utilisant le code de l'exercice précédent pour qu'il affiche la chaîne, puis le nombre à décomposer, et enfin chaque chiffre, tous sur des lignes isolées.
Indication : analyser bien la table des caractères ASCII en hexadécimal (man ascii).
7.9 Exercice 5: compte à rebours
Dans cet exercice nous allons aborder la programmation d’une structure répétitive (while ou for) et donc les tests et sauts conditionnels.
un décompte de 5 à 0 et la fin la chaîne « décollage ».
Écrivez un programme qui commence par afficher « Compte à rebours enclenché ! »
Soit le registre D0 initialisé à la valeur 5.
Écrivez un programme qui affiche le décompte de la valeur de D0 à 0 (5...4...3...2...1...0) en utilisant une boucle avec comparaison et saut, la comparaison se faisant sur le code ASCII.
Complétez le programme pour qu'à la fin il affiche la chaîne de caractères « Décollage ! ».
7.10 Exercice 6: saisie numérique
L'instruction trap #2 permet de placer en mémoire à l'adresse contenue dans A0 une chaîne de caractères saisie au clavier (sans le retour à la ligne mais avec le marqueur).
- Écrivez en programme qui affiche « Entrez un nombre : », puis_attend la saisie d'un nombre d'au plus 4 chiffres et place sa valeur dans le registre D0.