Cours gratuits » Cours informatique » Cours programmation » Cours Assembleur » Cours Assembleur i8086 en PDF

Cours Assembleur i8086 en PDF

Problème à signaler:

Télécharger



★★★★★★★★★★3.5 étoiles sur 5 basé sur 1 votes.
Votez ce document:

Cours Assembleur i8086 enjeux et pratique

...

2 Les systèmes numériques

2.1. LE BINAIRE

Nous l'avons déjà dit, les microprocesseurs ne comprennent que ce mode de numération.

De même que le décimal travaille sur les chiffres 0, 1, 2, 3, 4, 5, 6,

7, 8. 9, le binaire ne travaille que sur 0 et 1.

On dit que le décimal et le binaire sont respectivemen

t des systèmes de base 10 et 2.

Considérons par exemple le nombre 3783. 11 est composé de chiffres des milliers (3), des centaines (7), des dizaines (8) et des unités(3).

On peut donc écrire :

3783 - (3 1000) + (7 x 100) + (8 x 10) + (3)

ou bien encore

3783 L- (3 x 1g3) + (7 1g2) 4- (8 x 101) +(3 \ 10°)

Si nous nous plaçons maintenant dans un système de base 2 on aura

3783 --- (1 x 2048) + (1 x 1024) ÷ (1 x 512) 4- 01 x 256) + (1 x 128) +

(1 x 64) +             x 32) + (fg x 16) +(0x 8) + ("1 x 4) + (1 x )+I1 x ou encore

3783 = (1 x 2") + (1 x 210) + (1 x 29) + (0 x 28) + (1 x 27)  26) +

x 25) + (fi x 24) + (0 x 23) + (1 x 22) + (1 x 1)+(1 x 20).

Le nombre 3 78 3 en base 2 s'écrira donc

3783 —111011000111

Ce nombre peut donc être représenté en binaire à l'aide d'un mot de

12 bits.

Par un petit calcul simple on pourrait montrer qu'avec 12 bits il est possible de coder des nombres compris entre 0 et 4095

(= 11111 1111111 c'est-à-dire 4096 nombres différents.

Plus généralement un mot binaire de N bits permet de coder 2N nombres qui sont compris entre0 et 2N-1.

Nous avons vu dans le chapitre précédent que les codes-opérations du 6 809 étaient donnés sous forme d'un ou deux octets. Il peut donc exister au maximum 2' = 65535 codes-opérations différents ; en fait tous les codes ne sont pas attribués et le jeu d'instruction du 6809 est plus réduit.

Mais, nous direz-vous, pourquoi avoir choisi le binaire? C'est bien simple : en raison de sa grande facilité de mise en oeuvre.

Il est beaucoup plus facile de réaliser des circuits pouvant prendre deux états différents (état "0" ou " 1", OV ou 5V, "OUI" ou "NON") même s'ils doivent être en grand nombre (il faut huit chiffres binaires pour coder les nombres compris entre 0 et 255), que de réaliser des circuits pouvant prendre 10 états différents (cas du décimal).

2.2. L'HÉXADÉCIMAL

Nous avons jusqu'à présent parlé des systèmes de base 10 (le déci  mal) et de base 2 (le binaire). Pourquoi n'existerait-il pas de système de base 16 d'autant plus que, nous allons le voir, un tel système facilite grandement l'écriture des octets (en se plaçant cette fois-ci du côté de l'utilisateur et non pas du côté de la machine). De même que le décimal comporte 10 chiffres (0 à 9), l'hexadécimal comporte 16 caractères qui sont les suivants :

1, 2, -3, 4, 5, 6, 7,              9, A, B, C, D, E, F

On a donc les équivalences suivantes:

hexadécimal      décimal                binaire

0             0             0000

1             1             0001

                2             0010

3             3             0011

4             4             01040

5             5             0101

6             6             0110

7             7             0111

8             8             1000

9             9             1001

A             10           1010

B             11           1011

C             12           1100

D             13           1101

E             14           1110

F             15           1111

Voyons maintenant comment il est possible de convertir un mot binaire en un nombre hexadécimal et inversement.

C'est en fait extrêmement simple : le mot binaire est séparé, de la droite vers la gauche, en groupes de 4 bits, chacun de ces derniers étant converti en son équivalent hexadécimal.

Considérons tout d'abord l'octet suivant

                11           1001

                6             9

donc 01101001 = 69 en hexadécimal = 105 en décimal.

 Supposons maintenant que le mot binaire ne contienne pas un nombre entier de fois 4 bits.

Soit par exemple le mot suivant

(00)11   0110 y e

1-1.7

On opère maintenant exactement de la même façon que précédemment en remplaçant les bits manquant à gauche par des zéros.

Cela nous donne ici

326D en hexadécimal

Grâce à cette notation, un mot-mémoire est codé à l'aide de deux caractères. Une adresse de 16 bits nécessitera de même quatre caractères hexadécimaux.

La plupart des codes-opérations sont compris entre 00et FF.

2.3. LE CODE BCD (Binaire Codé Décimal)

Ce code permet de représenter d'une manière simple les nombres décimaux. Chaque chiffre décimal est transformé en son équivalent sur

4 bits. On a donc :

0 =

1 = 0001

2 -= 0010

3 = 0011

4 = 0100

5 = 0101

=0110

7 = 0111

8 ---- 1000

9 = 1001

Dans un nombre décimal, chaque chiffre est remplacé par son équivalent binaire.

Par exemple

36 = 0011             0110

Cela nous amène à une constatation : ce code perd une grande quantité de place mémoire. En effet un octet ne permet que de coder des nombres décimaux compris entre 0 et 99 (contre 0 et 255 pour le binaire).

Ce code n'en reste pas moins très utilisé surtout dans le 6809 qui permet d'effectuer des additions et des soustractions sur des nombres codés en BCD.

2.4. LE CODE ASCII

.Jusqu'à présent nous avons vu différents moyens de codage des nombres. Cvlais il est nécessaire de savoir également comment coder les caractères alphanumériques (par exemple lors de leur entrée à partir d'un clavier).

C'est dans ce but qu'a été créé le code ASCII (en anglais

" American Standard Code for Information Interchange”) qui est actuellement le plus répandu. II s'agit d'un code à 8. bits mais dont le bit de poids fort est utilisé pour la détection des erreurs c'est le bit de parité.

L'information n'est donc réellement contenue que dans 7 bits ce qui permet de coder 128 caractères différents.

Ces 128 codes permettront de représenter toutes les lettres de ['alphabet" les chiffres, ainsi que différents caractères spéciaux. Les codes restant sont utilisés comme des commandes.

Nous donnons ci-après la liste des différents codes ASCII ainsi que leur signification (nous avons supposé que le bit de parité était toujours à zéro pour simplifier).

Code

Caractère

Code

Caractère

Code Caractère

NUL       N'Al

S014      Sian o Heading

STX        Sian of Text

ET X       End of Text

FOI"       End of Transmission

ENO. Enquiry

ACK Acknowleclge

BEL         Bell

BS           • Backspice

HT          . Horizontal Tabulation

LF           : Line Feed

VT          Vertical Tabulation

FF           Form Feed

CR          Carnage Return

SO          : Shift out

SI            : Shift in

DLE : Data Iink Escape DC1  Device Control 1 DC2z

DC33

DC44

NAD      Negative Acknowledge

SYN        Synchronous Idie

ETB        End of Transmission Block

CAN : Carcel

E AGI     ; End of Medium

SUB Ï ubstitute

ESC        Escape

E             FileSeparator

GS          : Group Separator

AS          • Record Separator

US          • Unit Separalor

SP           : Space

2.5. REPRÉSENTATION DES NOMBRES NÉGATIFS

Jusqu'à présent nous avons parlé de mots binaires sans en spécifier le signe. De même qu'il existe des nombres décimaux négatifs pourquoi n'existerait-il pas des nombres binaires négatifs ?

Nous avons vu qu'avec un octet il était possible de coder les nombres 0 à 255 en décimal ou 00 à FF en hexadécimal.

Considérons l'opération 0-1 = —1 en décimal (elle consiste à retrancher 1 de 0) et tentons de la réaliser en binaire :

Og000000

— 1 — 00000001

                - 1           11111111 = FF

Donc —1 sera représenté par FF.

Recommençons et soustrayons 1 à —1 :

  1. 1         11111111

— 1 — FJ0000001

-= -2      _ 11111110 - FE

Donc :

—2 = FE en hexadécimal

Ceci dit cette méthode de détermination de la représentation binaire d'un nombre négatif n'est pas très commode, c'est pourquoi nous allons introduire la notion de notation en complément à 2.

La méthode est la suivante: on prend le mot binaire correspondant à la valeur absolue du nombre dont on veut déterminer l'opposé (soit X),

— tous les bits sont changés en leur opposé: 0—>1 et 1-4,

—           tr on ajoute au nombre trouvé, ce qui donne la représentation binaire de (—.  

Exemple : Soit à déterminer la représentation binaire de 2. On a

2 = 00000010

11-1111g1 par inversion des bits —2 = 'IMMO= FE

Le résultat trouvé est bien le même que précédemment. Nous pouvons vérifier que l'opération +2 —2 donne bien zéro (sur 8 bits). Le tableau suivant donne la valeur décimale associée à chacun des octets compris entre 00 et FF.

                               1             2             3                             5             5             1             1             8             9             1             A             B                C             D             E             F

  1. 0             1             2             3             4             5             6             7             8             9             10           11           12           13                14           15

1             16           17           18           19           20           21           22           23           I              24          25           2G          27           2                29           30           31

                32           33           34           35           36           37           38           39           40           41           42           43           44           45                46           41

3             48           49           50           51           52           53           54           55           56           67           58           59           60           51                1             62           63

4             54           65           66           67           68           69           70           71           72           73           74           75           75           71           '                78           79

  1. 80           81           82           83           84           85           86           87           88           i               89           90           91           92                93           !              94           95

6             96           97           98           99           100         101         102         103 '

i               104         105         10S         107         108         109 '       110         111

7             112         113         114         115         116         111         118         119         120         121         121         123         124         12.5                126         127

8             128         -127       -126       -125       -124       -123       -122       -121       -110       -119       -118       -117       -116       -115                -114       -113

9: ili        11.2

-96         -111

-95         -110

-94         -109

-93         -108

-92         -107

-91         -106

-90         -105

-89         -104

-88         -1031-102

-87         -86         -101

-85         -100

-84         -99         ,

-83         ;              -98

  • 82          -9?

-811

B             -80         -19         -78         -17         -76         -75         -74         -73         -72.        -11         -70         -69         -68         -f1          '                -66         -65

C             -64         -5            -62         -61         -60         -59         -58         -57         -56         -55         I              -54         -53         -52                -51         ·              -50         -49

D:           -48         -47         -46         -46         -44         -43         -42         41           40           -39         -38         -37         -36         -35                -34         -33

E             -32         -31         -30         -29         -28         47           -26         -25        -24         -23         -22         -21         -20         -19                J 18        -17

                -16         -15         -14         I              -13         -12         -11         -10         I              -9            -8            I              -7            -6                -5            -4            i               -3            -2            -1

Par cette méthode il est donc possible de coder les nombres décimaux compris entre —128 et +127. Le bit de poids fort (bit 7) de chaque octet est égal à 0 si le nombre est positif, égal à 1 si le nombre est négatif.

Notons que cette notation en complément à deux n'est pas obligatoire. C'est au programmeur de décider si les nombres qu'il utilise sont compris entre 0 et 255 ou bien entre —128 et +127.

Dans le prochain chapitre nous rentrons cette fois-ci dans le vif du sujet en décrivant le microprocesseur qui nous intéresse ici le 6809, ou plutôt son assembleur.

La syntaxe assembleur 6809

3.1. INTRODUCTION

Eh oui, comme toute "langue vivante", l'assembleur possède ses propres règles de "grammaire" et cl" orthographe". Et gare à vous si, dans un désir d'indépendance tout à fait mal à propos, vous décidez de

ne pas \fou> y plier!

Ceci dit, ces règles sont tré simples et il ne vous faudra qu'un peu d'habitude pour les connaitre. 1,01irux même, ces programmes que jusqu'à maintenant vous considériez être du chinois en seront réduits à n'être

finalement que._ de l'anglais: on tombe vraiment dans la facilité! Nous pourrons distinguer deux sortes de règles dans la programmation en assembleur:

- les règles absolues : si par malheur vous les transgressez, vous vous ferez froidement "jeter" par la machine avec en guise de compliment de petits mots d'amitié du type "ILLEGAL FORMAT",

"MISSING OPERAND", le tout dans le plus pur anglais de

Shakespeare

les règles conseillées: ce sont celles qui sont laissées à l'appréciation du client. En gros, si vous ne les suivez pas, vous risquez :

* d'une part de passer beaucoup plus de temps que nécessaire pour faire tourner votre programme,

* d'autre part de devoir vous reporter au chapitre consacré aux codes d'erreurs par suite d'une étourderie ce qui est très désagréable.

Nous allons maintenant passer en revue les différentes régies à observer dans le cas d'un assembleur 6809 classique et nous indiquerons au passage ce qu'il faut et ce qu'il ne faut pas faire.

3.2. LA SYNTAXE ASSEMBLEUR

Une ligne en langage d'assemblage est subdivisée en un certain nombre de parties appelées "champs". En effet, un programme écrit en assembleur véhicule un certain nombre d'informations distinctes qui, pour être bien comprises par l'assembleur, doivent être bien séparées les unes des autres.

3.2.1. Le champ étiquette (Lebel)

Vous qui ciinnaissez le BASIC, vous devez savoir ce qu'est une étiquette : celle-ci représente une adresse de branchement.

Exemple:

GO TO leg

La zone étiquette est le premier champ dans une ligne écrite en assembleur. Elle peul être vide (pas d'étiquette) ou remplie. Les labels sont utilisés lors des instructions de saut inconditionnel, conditionnel et d'appel de sous-programme. Du fait de la taille limitée du champ qui lui est affecté, une étiquette doit avoir un nombre maximum de caractères (souvent 6) dont le premier doit être une lettre.      •

Exemple:

BOUCLE

BRANCH

DECIM

ou si vous aimez t'anglais :

LOOP

START

Nous vous donnons ci-dessous à titre indicatif le listing d'une ligne en assembleur :

SOMME               ADDA É3ei          ; EFFECTUE LA 501vIME

Champ label

Ce qu'il faut faire:

Les noms donnés aux étiquettes doivent (c'est un conseil d'ami) être des noms compréhensibles au commun des mortels. Cela permettra à d'autres que vous-même de aire vos programmes ; et puis imaginez que vous vouliez améliorer le programme que vous avez écrit l'année précé  dente si vous faites...

Ce qu'il ne faut pas faire:

Utiliser les "96", "*" et autres "S" pour définir une étiquette.

D'autre part rassembleur risque de ne pas être content et de vous lancer un l'ILLEGAL LABEL" en guise de reproche. D'autre part avouez que de tels signes (bien qu'utilisés très largement en micro-informatique) ne sont pas très explicites.

3.2.2. Le champ opération

Le champ opération est situé juste après le champ étiquette duquel il est séparé par un symbole spécial appelé DELIMITEUR. Le plus commun est tout simplement un espace (touche "SPACE"). Dans ce champ on trouve le mnémonique de l'instruction.

SOMME               ADDA* 30           ; EFFECTUE LA SOMME

champ champ délimiteur opération

3.2.3. Le champ opérande

Ce champ est celui qui risque de poser le plus de problèmes au programmeur novice en assembleur. 1l est généralement séparé du champ opération par un délimiteur.

L'opérande sert à définir la donnée sur laquelle s'effectue l'instruction. Elle doit donner à l'assembleur toutes les précisions nécessaires à sa compréhension du programme et en particulier concernant le mode d'adressage.

Nous reparlerons de ceci dans le prochain chapitre qui sera en partie consacré aux différents modes d'adressage du 6809+

Dans le champ opérande on peut trouver

—           des nombres, des noms de variables,

—           des étiquettes, des expressions arithmétiques ou logiques.

  1. a) Les nombres

La plupart des assembleurs acceptent des nombres sous forme déci  male, hexadécimale, binaire, le tout étant de le préciser.

i existe donc des caractères qui permettent de renseigner l'assembleur sur le système numérique dans lequel ils sont représentés.

les nombres décimaux. En général le nombre 80 (en base 10) s'écrira 80, Il n'y a pas besoin ici de caractère spécial (on appelle cela l'option de défaut). Les nombres décimaux pourront être positifs ou négatifs.

Exempk : –3

1-75

—           les nombres hexadécimaux. Le caractère utilisé est généralement un "S" (dollar), parfois un "H" comme hexadécimal.

Exemple:            $80 ( 128)

ou bien :              80H

les nombres binaires. Les caractères utilisés peuvent être le

1", 1[6 91 ou bien "B". L'octet 01001101 s'écrira alors :

ou bien 'A1010011141

1410fi11ii51B

les caractères ASCII. Il s'agit d'un unique caractère ASCII précédé d'une apostrophe.

Exemple:

A L'assembleur remplace ce caractère par le code ASCII correspondant.

— les déplacements par rapport au registre PC (compteur Ordinal dont nous parlerons plus loin).

Un déplacement de 7 octets par rapport au PC s'écrira : *÷7

Le déplacement peut étre positif ou négatif.

  1. b)           Les noms de variables

Dans le champ opérande peuvent apparaitre des noms de variables pour définir une adresse par exemple. L'assembleur les traite comme des nombres (à condition qu'une valeur ait été assignée à chacune d'elles auparavant).

Exemple:

ADCA VALEUR

Supposons que VALEUR = $10, alors ily aura addition entre l'accumulateur et la case-mémoire d'adresse S0010.

  1. c)            Les noms d'étiquettes

Dans les instructions de saut on peut voir apparaitre une étiquette dans le champ opérande. Cette étiquette possède les caractéristiques décrites précédemment.

Exemple:

JMP BOUGE

  1. d)           Les expressions arithmétiques et logiques

Certains assembleurs acceptent comme opérande des expressions arithmétiques et logiques mettant en jeu des nombres, des noms de variables, des noms d'étiquettes, etc...

 Exemple:           ADCA VALEUR 1-1

jtviP BOUGE-5

Ces expressions arithmétiques utilisent les opérateurs + (addition),

— (soustraction), * (multiplication), I (division entière).

Attention: Ce type d'expressions est une grande source d'erreurs surtout lorsqu'elles sont compliquées, donc essayez de les utiliser le moins fréquemment possible.

3.2.4. Le champ commentaire

Dans un programme en assembleur le commentaire n'a aucune influence (à condition bien sûr qu'il soit placé au bon endroit et séparé du champ opérande par un délimiteur).

Les commentaires, bien que trop souvent négligés, sont très utiles car ils permettent de documenter un programme et de ce fait de le rendre plus intelligible.

Le délimiteur, destiné à signaler à l'assembleur qu'il est en présence d'un commentaire, est généralement un point-virgule (";").

Exemple : ; BOUCLE DE DELAI

Contrairement à ce que l'on pourrait croire, écrire des commentaires utiles est assez difficile. En effet il ne faut pas écrire n'importe quoi. Voici quelques règles et conseils à observer

Les commentaires doivent servir à éclairer le fonctionnement global du programme.

— Us peuvent' servir à expliquer non seulement l'utilité d'une instruction particulière mais aussi d'un morceau de programme (sous  programme par exemple).

Un commentaire doit être clair et concis.

Il est inutile de s'attarder sur des points évidents mais il ne faut pas hésiter à insister sur des endroits clefs.

Écrivez par exemple "TEMPS MAXIMAL ECOULE?" ou bien "TESTE SI L'INTERRUPTEUR EST FERME" plutôt que "TESTE LA VALEUR DU BIT CARRY", " BRANCHEMENT AU

REBUT".

Il faut savoir que le temps passé à commenter un programme est pratiquement toujours récupéré et même fait gagner du temps lors de la phase "mise au point" par exemple.

Tous ces détails vous semblent peut-être un peu abstraits. Ne vous inquiétez pas, nous vous donnerons un petit peu plus loin un exemple de listing en assembleur afin de vous familiariser avec la syntaxe. Mais avant cela examinons un point très important dans l'écriture d'un programme en assembleur.

3.2.5. Les peeudo-inetructione

Nous appelons pseudo-instructions les instructions qui ne font pas partie de la bibliothèque du 6809 et qui sont juste destinées à donner des informations (ou directives) à l'assembleur.

Nous allons en répertorier quelques-unes sachant qu'elles peuvent différer d'un assembleur a l'autre.

  1. a)            La directive origine

Elle permet de définir l'adresse de départ d'un programme ou d'un sous -programme.

Supposons que nous voulions faire commencer notre programme à l'adresse $0200, nous écrirons alors

ORG $0200

Après assemblage l'adresse de la première instruction sera donc

$0200.

  1. b)           La directive de fin

De même qu'il est nécessaire de fournir à l'assembleur une indication concernant l'adresse de début du programme, il faut qu'il connaisse également l'endroit où il se termine. C'est le rôle de la directive END notée généralement END nn. Elle se place à la dernière ligne du programme.

Prenons par exemple le petit programme suivant

DEBUT LDA         $78

ADCA #05

END DEBUT

Lors de l'assemblage, la pseudo-instruction "END DEBUT" indique à l'assembleur que la première instruction à exécuter sera située à l'adresse DEBUT. Alors que la directive ORG donne l'adresse de chargement mémoire du code-objet, la directive END donne l'adresicik lancement du programme (ces deux adresses ne sont pas forcément égales). La définition du code-objet sera donnée un peu plus loin.

  1. e) La directive Equate

Nous avons vu précédemment que l'on pouvait donner des noms à des variables représentant soit des adresses soit des données. Afin que l'assembleur puissè générer le code-objet, il faut préalablement définir ces variables.

Suivant l'assembleur utilisé on écrira:

COMPT E(U $05

FIN         EQU DEBUT+$60

Cette dernière ligne suppose bien sûr que la variable DEBUT ait été préalablement définie.

En général, on placera les directives " EQU" au début du programme. Cela accroit la lisibilité et surtout cela permet de les changer facilement.

  1. d) Les directives de réservation d'espace-mémoirt

Il peut arriver que l'on veuille réserver des octets, des doubles octets ou des portions entières de mémoire pour y stocker des données, des tableaux, des chaires de caractères ASCII. Nous allons définir ici un certain nombre de directives qui remplissent ces rôles.


96