CODINGCHRONIQUE Jean-Pierre Richard pour l'Ordinateur Individuel ★ Les opérations arithmétiques: addition et soustraction ★

L'Ordinateur individuel n°21 - Les opérations arithmétiques: addition et soustraction
Nous voici arrivés à la quatrième partie sur l'assembleur du microprocesseur Z80. Avec l'addition, la soustraction, la multiplication et la division, nous allons y aborder un point délicat du langage machine. Cet article, à la différence des précédents, posera de sérieux problèmes au lecteur qui n'a pas eu la curiosité de fréquenter l'école primaire, ou tout au moins n'a pas d'atomes crochus avec les « maths ». Mais ne nous décourageons pas si vite et attaquons courageusement opérations arithmétiques, opérations de comparaison, de logique, de décalage ou de rotation... et finalement les opérations d'entrée et de sortie. Mais comme de si nombreuses opérations seraient indigestes en une seule fois, nous nous contenterons dans cette avant-dernière partie de l'étude des additions et des soustractions.

Mais d'abord, avant toutes choses et réciproquement (Pierre Dac), effectuons ensemble quelques révisions nécessaires à la bonne compréhension de ce qui va suivre...

Expliquer ce qu'est un nombre en base n n'est pas si simple : il existe des règles dont certaines nous paraissent évidentes car nous les appliquons couramment. En voici quelques-unes :

  • dans un nombre entier chaque chiffre (a) porte un indice de position (i) : il est de 0 pour le chiffre le plus à droite, 1 pour son voisin de gauche et ainsi de suite en continuant vers la gauche.
  • la valeur numérique représentée par un chiffre (a) répond à la formule suivante: a que multiplie la base n portée à la puissance i soit : a x n.
    où a est le chiffre, n la base et i l'indice de position du chiffre dans le nombre.
  • la valeur représentée par le nombre est la somme des valeurs respectives de chaque chiffre. Par exemple, en base 10 (ou base décimale, la plus couramment utilisée) la valeur du nombre 342 est :
    (3 x 10²) 4- (4 x 10¹) + (2 x 100)
    = (3 x 100H- (4 x 10) + (2 x 1)
    = 342 (Ouf !)

En base 10, on dit que :

3 est à la position des centaines
4 est à la position des dizaines
2 est à la position des unités.

Il y a encore deux règles à se rappeler avant de manipuler les nombres en des bases différentes :

  • n à la puissance 0 est égal à 1 quelle que soit la base n.
  • le chiffre a est toujours inférieur à la base n (le chiffre maximum est 9 en base 10 et 1 en base 2).

Prenons quelques exemples pour nous entraîner : quelle valeur prendra le nombre 101 suivant la base choisie ?

En base 10 (ou base décimale), suivant la formule a x 10 la valeur du nombre 101 est :

(1 x 10²)+ (0 x 10¹) + (1 x 100)
= (1 x 100) + (0 x 10) + (1 x 1)
= 101

En base 8 (ou base octale), toujours suivant la formule a x 8 , le nombre 101 représente la valeur décimale :

(1 x8²) + (0x8¹) + (1 x 80)
= (1 x 64) + (0 x 8) + (1 x 1)
= 65

C'est-à-dire 101 (base 8) = 65 (base 10).

C'est compris? alors la base 16 n'est plus qu'un jeu d'enfant :

En base 16 (ou base hexadécimale), la formule à appliquer est a x 16l et le nombre 101 prend la valeur décimale :

(1 x 16²) + (0 x 16¹) + (1 x 160)
= (1 x 256) + (0 x 16) + (1 x 1)
= 257

En effet, le nombre noté 101 représente en base 8 la valeur 65, en base 16 la valeur 257 et bien sûr en base 10 la valeur 101 (ouf !).

Pour une base supérieure à 10, le problème de la représentation du chiffre se pose : en effet, si a est supérieur à 9, a n'est plus un chiffre mais un nombre (dans « notre » notation décimale !) Il occupe alors deux places et la détermination de l'indice i devient problématique.

Un exemple classique est celui de la représentation du temps (celui qui passe...) :

Dans la valeur 3 h 30 mn 45 s, a est un nombre. La séparation dans l'ordre par les symboles h, mn, s est imposée : l'heure est à l'indice i = 2, les mn à l'indice i = 1 et les secondes à l'indice i = 0. (Sans cette séparation par des symboles, un rendez-vous donné à 33045 sera manqué à coup sûr !).

Dans le cas h, mn, s la base est 60 et la formule bien connue maintenant donne : a x 60i :

(3 x 60²) + (30 x 60¹) + (45 x 600)
= (3 x 3600) + (30 x 60) + (45 x 1)
= 12 645 secondes.

Cette représentation est très lourde à manipuler : c'est pourquoi en base hexadécimale on a chois de représenter 10 par la lettre A, 11 par B et ainsi de suite jusqu'à F qu correspond à 15; ainsi a n'occupe dans cette base qu'une seule place.

Et en base 2 (ou binaire) quelle valeur prend le nombre 101 ?

a x 2i :
(1 x 2²) + (0 x 2¹) + (1 x 20)
= (1 x 4) + (0 x 2) + (1 x 1)
5

C'est-à-dire que 101 (base 2) = 5 (base 10)

Et maintenant
l'utilisation
pratique

La représentation binaire ne doit plus avoir de secrets pour vous; l'ensemble de 8 chiffres s'appelle octet et le chiffre ne peut prendre que la valeur 0 ou 1 (cf. règles précédemment énoncées).

Quittons maintenant les problèmes posés par la manipulation des bases et gardons uniquement en mémoire (si j'ose m'exprimer ainsi) la représentation en base binaire.

La première des opérations arithmétiques à étudier est l'addition : la règle primaire ou table de vérité est la suivante :

1 + 1 = (1) 0 où (1 ) est la retenue.
1+0=1
0+1=1
0 + 0 = 0

Voici un exemple élémentaire qui met cette règle en pratique :

 0011 (3)
+ 0001 (1)
 0100 (4)

Entre parenthèses on trouve la valeur décimale correspondante.

L'addition se décompose de la façon suivante :

1re colonne : 1 + 1 = 0 retenue (1 )
2e colonne : (1 ) + 1 +0 = 0 retenue (1)
3e colonne : (1 ) + 0 + 0 = 1
4e colonne : 0 + 0 = 0

Continuons sur notre lancée et attaquons la soustraction : en fait, la soustraction est une addition entre un nombre positif et un nombre

négatif. Nous avons déjà étudié la représentation du signe dans un octet Le BPS (Bit le Plus Significatif), chiffre indice 7, est égal à zéro (0)si le nombre est positif. Pour que le résultat de la soustraction soit exact il est nécessaire d'utiliser la représentation en complément à deux. Voici la marche à suivre pour trouver la représentation en complément à deux : la valeur décimale 17 se représente en binaire de la façon suivante :

000 1000 1

La représentation à un consiste à passer les 0 à l'état 1 et les 1 à l'état 0:

1110 1110

Pour obtenir la représentation à deux, il faut ajouter 1, ce qui donne : 1110 1111 soit — 17 (valeur décimale) en complément à deux (ou EF en hexadécimal que l'on notera EFH).

Effectuons la soustraction 18 moins 17 :

0001 0010 ( 18)
-1110 1111 (-17)
(1) 0000 0001 ( 1)

Le résultat est correct (ouf !). Une retenue a été posée sur le bit indice 0 d'un octet qui serait apparié à l'octet résultat.

Ce nouvel octet est en fait le registre indicateur d'état, tandis que le bit indice 0 est l'indicateur de report C (C comme Carry).

La représentation en complément à deux permet d'afficher sur un octet une valeur positive maximale de 01111111 soit 127 (décimal) et une valeur négative de 1000 0000 soit -128 (décimal).

Vérifions à titre d'exemple si le nombre 1111 1111 (ou FFH en hexadécimal) est bien la représentation de signe négatif de la valeur décimale 1.

Effectuons le complément àun(1 devient 0 et 0 devient 1), soit 00000000 puis le complément à deux (+ 1 ), soit 0000 0001 qui est bien égal à + 1.

La programmation d'une opération arithmétique utilise beaucoup le registre indicateur d'état.

Nous avons vu précédemment l'utilité de l'indicateur de report, voyons maintenant celle de l'indicateur de dépassement et de parité (parity overflow). Si l'on applique rigoureusement les règles précédentes, la somme de 01110000 (112 en décimal) et de 01001000 (72) donne 10111000: cette somme est bien évidemment négative puisqu'elle commence par 1. Son complément à deux est 0100 1000 (72). Le résultat obtenu est donc — 72 en décimal : ceci est complètement faux car, comme chacun le sait, la somme de deux nombres positifs est obligatoirement positive ! Pourquoi cette erreur ? En fait la somme décimale de 112 et de 72 doit donner 184, et nous avons vu précédemment que nous étions limités à + 127. Ce problème surviendra chaque fois que le résultat d'une opération sur 8 bits (addition ou soustraction) sera supérieur à +127 ou inférieur à — 128. De la même façon, le résultat d'une opération sur 16 bits devra être compris entre -32768 et + 32767.

C'est ici qu'intervient le registre indicateur d'état et plus précisément le bit indice 2, indicateur P/V de dépassement. Ce bit et celui correspondant à l'indicateur de report permettront de vérifier la bonne exécution des opérations arithmétiques.

Les exemples suivants vont nous permettre de mettre en évidence les modifications d'état des indicateurs considérés.

0000111 + 01000000 = 01000111
(+7) + (+64) = (+71)
C = 0 P/V = 0

00000111 + 11111100 = (1)00000011
(7) + (— 4) = (+ 3)
C = 1 P/V = 0

0111 1111 + 0000 0001 = 10000000
(+ 127) + (+ 1) = (—128)
C = 0 P/V = — 1 FAUX !

10000000 + 1111 1111 = (1)0111 1111
(-128) + (-1) = +127
C = 1 P/V= 1 FAUX !

Si l'indicateur C est égal à 1, cela nous indique que le résultat est trop élevé pour être contenu dans le registre et qu'il y a un report sur un bit extérieur à l'octet; le résultat n'est pas faux pour autant.

Si l'indicateur P/V est différent de zéro, il y a une erreur dans le résultat: il faudra donc appeler un sous-programme par JP pour y remédier.

Quels sont les ordres d'exécution des additions ou soustractions en langage assembleur?

Une table de vérité pour l'addition

Dans le cas d'opérations arithmétiques 8 bits, un des termes se trouve obligatoirement dans l'accumulateur, l'autre terme étant soit dans un registre, soit à une adresse pointée par HL ou un registre indexé ; il peut aussi tout simplement être une valeur'numérique. Le résultat est consigné dans l'accumulateur.

Voici ci-contre un exemple simple d'addition et de soustraction (voir liste A) :

Les instructions ADC et SBC effectuent une addition ou soustraction tout comme ADD et SBB mais il y a ajout (ADC) ou retrait (SBC) de la retenue située dans l'indicateur de report.

L'exemple de programme d'addition multibit qui va suivre illustre cette fonction d'ajout de la retenue.

Les termes de cette addition, IX et IY, sont indiqués dans le tableau suivant :

IXIY
d = + 10101 11110111 0100
d = + 21111 10011001 1001
d = + 30101 1111 1001 0111

A titre d'exercice, je vous conseille de faire l'addition «à la main » (le résultat est : 0111 0100 1001 0010 1111 0110) et de constater le report entre les deuxième et troisième octets (voir ci-dessus liste B).

Le début du programme devra comprendre l'instruction ORA pour mettre à zéro l'indicateur de report, s'il doit être intégré comme sous-programme.

Pour une opération sur 16 bits, le registre pair de base est le plus souvent HL (par contre les instructions ADC et SBC utilisent obligatoirement HL). La durée d'exécution de l'instruction est plus courte pour HL que pour les trois autres registres pairs possibles, IX, IY ou SP. Il faut noter que seul SBC (soustraction avec carry) existe en 16 bits. Un tableau peut être établi comme précédemment : les valeurs seront exprimées en 1 6 bits au lieu de huit bits. Le programme sera très similaire, à vous d'essayer...


Liste A : un exemple simple d'addition et de soustraction


Liste B : un exemple d'addition multibit

Un moniteur (NASBUG, TBUG...) vous permettra de connaître le contenu des adresses mémoires et de vérifier le résultat.

Multiplication et division en «binaire » seront étudiées le mois prochain en même temps que les « dernières» opérations disponibles qui sont néanmoins encore très nombreuses.

Allons ! Encore un petit effort ! Il ne vous restera plus ensuite que... la pratique.

Jean-Pierre Richard, L'Ordinateur individuel n°21

★ REVUE: L'Ordinateur Individuel
★ ANNÉE: ???
★ AUTEUR: Jean-Pierre RICHARD

Je participe au site:

» Vous avez remarqué une erreur dans ce texte ?
» Aidez-nous à améliorer cette page : en nous contactant via le forum ou par email.

CPCrulez[Content Management System] v8.732-desktop/c
Page créée en 330 millisecondes et consultée 238 fois

L'Amstrad CPC est une machine 8 bits à base d'un Z80 à 4MHz. Le premier de la gamme fut le CPC 464 en 1984, équipé d'un lecteur de cassettes intégré il se plaçait en concurrent  du Commodore C64 beaucoup plus compliqué à utiliser et plus cher. Ce fut un réel succès et sorti cette même années le CPC 664 équipé d'un lecteur de disquettes trois pouces intégré. Sa vie fut de courte durée puisqu'en 1985 il fut remplacé par le CPC 6128 qui était plus compact, plus soigné et surtout qui avait 128Ko de RAM au lieu de 64Ko.