Additionnons...Tout un chacun connaît la formule que des générations d'écoliers ont anonnée : "Je pose n et je retiens 1". On retrouve exactement le même mécanisme dans une addition en base 2, à cette nuance près que l'opération "je pose n et je retiens 1" intervient bien plus tôt, dès que la valeur 2 est atteinte. Essayons, si vous voulez bien. 111 valeur en base 10:7 + 10 valeur en base 10:2 ----- 1001 valeur en base 10:9On peut décomposer :0 + 1 = 1 je pose 1 1 + 1 = 2 je pose 0 et je retiens 1 1 + 1 = 2 je pose 0 et je retiens 1 1 + 0 = 1 je pose 1Les choses se compliquent légèrement au niveau de l'accumulateur du Z80 puisqu'il ne dispose que de 8 positions binaires et n'autorise donc que 8 colonnes. Voyons tout de même, en nous plaçant d'emblée dans une condition bien particulière. 11111111 valeur en fasse 10:255 + 1 ----------- 00000000 résultat CL'accumulateur n'ayant que 8 positions, il est impossible d'y loger la retenue, qui tombe en dehors. Fort heureusement, la retenue ne tombe pas n'importe où, mais aux pieds d'un sémaphore qu'elle active. Il s'agit de l'indicateur "C. Ce nouveau-venu se comporte un peu comme l'indicateur "Z" que nous connaissons déjà. Attention ! L'indicateur "C" n'a rien à voir avec le registre "C" que l'on trouve dans la paire BC. Le "C" qui nous occupe vient du mot "Carry", report. On dit généralement que le bit qui ne trouve pas à se loger dans l'accumulateur (ou ailleurs comme nous le verrons plus bas) tombe dans "Carry".Que se passe-t-il si nous additionnons dans l'accumulateur deux valeurs telles que 75 + 250, par exemple? Nous trouverons dans l'accumulateur une valeur juste, à 256 près. Carry sera levé, ce qui permet d'exploiter le résultat. On teste Carry comme on teste "Z", en déviant le programme. JR C,Suite! JR NC, Retour JP NC,... Call C, .. . etc.Admettons qu'en sortie d'une addition entre accumulateur et une valeur absolue, nous désirions transférer le résultat dans une paire, comme DE. Voici la séquence.ADD A,n Additiion LD D,n Par sécurité, D pouvant contenir une valeur LD E,A Accumulateur pase en E JR NC, Suite Sauter si Carry pas positioné LD D,1 D passe à 1 (inc D aurait fait l'affaire)Deux remarques : LD D,0 et LD E,A n'influencent pas Carry. Le test sur Carry est donc bien placé. Ensuite, dans une addition 8 bits + 8 bits, le positionnement de Carry indique un (et un seul) multiple de 256. Z80 dispose de toute une famille d'instructions d'addition sur 8 bits.ADD A,A Addition de l'accumulateur à lui-même ADD A,n Accumulateur plus une valeur absolue (255 maximum) ADD A,... N'importe lequel des registres pris isolément et non en paire ADD A,(HL) Addition de l'accumulateur à n'importe quai, octet pointé par HLCette dernière instruction est particulièrement intéressante, car elle permet de faire l'économie d'une lecture. Mais attention, le résultat se trouve en accumulateur et... en Carry.ADD A, (IX+d) Addition de l'accumulateur à l'octet pointé par IX, avec éventuel déplacement. Voir IX+150 , IX-3 ADD A, (IX+d) Idem, mais en utilisant le registre IY comme pointeurUne autre propriété remarquable de l'addition retient l'attention. Si, en sortie d'addition, l'accumulateur est à 0 (avec ou sans Carry), le drapeau Z se lève. En combinant les tests sur "C" et sur "Z" il est donc aisé de tester les valeurs stratégiques. Voici une application. ADD A , n JR C,Suit1 ; Résultat supérieur à 255, carry positionné JR Z,Suit2 ; zéro absolu, Carry n'étant pas positinné JR Suit3 ; Résultat entre 1 et 255 Suit1 JR Z,Suit4 ; Carry positionné mais Z, donc résultat 256 ;Séquence.. ;Valeur entre 256+1 et 256+255 ;........... Suit2 ...........Un autre groupe d'instructions porte également sur l'addition 8 bits + 8 bits : ADC addition à travers le report. Ou'est-ce à dire ? L'addition par ADC tient compte d'un report antérieur éventuel, pour l'incorporer dans le résultat. Pour voir exactement comment joue ADC, il suffit de positionner Carry (voir SCF plus bas), de mettre accumulateur à 0 et d'additionner 0. Le résultat est 1, montant du report incorporé. A quoi peut bien servir l'addition par ADC ? Revenons à la base 10. Pour additionner en base 10, vous traitez ensemble les chiffres de même poids, les unités, puis les dizaines, etc. De temps en temps vous avez un report. Il en va de même pour additionner deux chiffres stockés par exemple sur 5 octets. On additionnera les chiffres des deux cases les plus basses, dégageant un report si le résultat est supérieur à 255, puis les deux cases de rang 2, etc. Mettons qu'un chiffre de ce type soit stocké en 9000H, un autre en 9005H. On veut les additionner entre eux, avec résultat en 9005H.LD DE,9000H LD HL.9005H Pointer chaque série d'octets LD A, (DE) Lire premier octet vers A ADD A, (HL) Additionner accumulateur à l'octet pointé par HL. ; Attention ADD et non pas ADC LD (HL),A Ranger le résultat dans l'octet pointé par HL INC DE INC HL ;Décaler les pointeurs LD A,(DE) Lire l'octet suivant ADC A,(HL) Cette fois c'est bien ADC pour tenir compte d'un éventuel report INC DE INC HLOn répétera le dernier bloc encore 2 fois et en sortie, on testera Carry, car il peut y avoir report après la 5e addition. L'important, ici, est de noter que la séquence commence par ADD et se poursuit par ADC. Je vois d'ici le chahuteur de service suggérer que "pour une programmation soi-disant directe et rapide, c'est plutôt laborieux". Effectivement. Tout vient de l'obligation de commencer par ADD, pour être sûr de ne pas embarquer un éventuel "Carry" préexistant, Carry sert en effet à bien autre chose qu'à constater les reports, comme nous le verrons. Il s'en suit que, même si vous n'avez pas encore additionné dans votre programme, vous ne pouvez faire confiance à cet indicateur. La solution existe : il faut "faire tomber Carry". Aucune instruction directe ne permet de gommer "Carry". Par contre une opération OR entre l'accumulateur et lui-même effectue le travail, sans changer le contenu de l'accumulateur. A partir de là les choses se simplifient considérablement : LD DE,9000H LD HL,9005H LD B,5 OR A Pour faire tomber Carry Bcl LD A,(DE) ADC A, (HL) Carry étant gommé, allons y pour ADC dès la première itération LD (HL),A INC DE INC HL DJNZ Bcl ; Test sur Carry en sortieA nouveau, on trouve toute une série d'instructions, strictement parallèles aux instructions ADD citées plus haut. Il est donc inutile de les répéter.Addition 16 bits + 16 bits Tout ce qui vient d'être dit s'applique aux additions 16 bits + 16 bits, à quelques petites nuances près. Jne addition 16 bits + 16 bits admet comme opérantes une aaire de registres, l'accumulateur n'étant plus concerné, /oici les instructions disponibles. ADD HL,BC..........DE...........HL..........SP, résultat en HL et carry éventuel. IX,BC..........DE...........IX..........SP, résultat en IX IY,BC..........DE...........IY..........SP, résultat en IY et Carry éventuel.Les variantes énoncées ici sont les seules disponibles. ADD BC.DE par exemple, n'existe pas. Pour ADC, la gamme est encore plus restreinte. On passe toujours par HL.ADC HL,BC..........DE...........HL..........SP, résultat en HL et Carry éventuel.Dans cette liste figure un nouveau venu, SP, le pointeur de pile.On en discutera plus longuement sous le thème "gérer la pile". Mieux vaut, dans l'immédiat, ne pas faire appel à lui, car si vous faussez le contenu de SP, vous aurez les suprises les plus désagréables au niveau du déroulement de votre programme (retours de sous-programmes intempestifs). S'agissant de registres 8 bits accolés, donc pratiquement de registres 16 bits, le maximum qu'il soit possible de stocker est représenté par 65535 soit FFFFH. Carry se positionne lorsque le résultat de l'addition vient à dépasser ce montant et indique donc un et un seul multiple de 65536, qu'on peut exprimer par 10000H. Il faut surveiller particulièrement la signification du contenu de Carry. Après une addition 8 bits, Carry ne pèse que 256, alors qu'il pèse 65536 après une addition 16 bits. Il faut donc se méfier d'un passage intempestif de l'addition 8 bits à l'addition 16 bits, à travers Carry. Pour finir, une instruction très intéressante, SCF. On va détourner Carry de son objet et s'en servir pour tout autre chose. Imaginez un sous-programme comportant un test et deux traitements différents selon le résultat de cet test. Revenu dans le programme principal, vous voulez suivre un chemin différent dans l'un et dans l'autre cas. En Basic, vous avez la solution de définir une zone en %, que vous lettrez à 0 ou à 1. Revenu dans la programme principal, vous testerez cette zone et vous vous débrancherez en conséquence. La même technique peut être mise en œuvre en assembleur, mais vous perdez un octet ; vous aurez besoin de charger 0 ou 1 dans l'accumulateur, qui contient déjà une valeur signifiante, etc. Vous pouvez très avantageusement jouer avec Carry, que vous positionnerez si vous sortez du sous-programme en X, et que vous ferez tomber si vous sortez en Y. Call SousProg SousProg Test quelconque qui vous fait JH C,Suite continuer en séquence ou aller en SousProgl Séquence SCF RET Retour X, carry positonné SousProg1 OR A RET Retour Y, carry gomméRevenu dans le programme principal, il suffit de tester Carry.MICRONEWS n°12 Julllet/Août 1988 ★ AMSTRAD CPC ★ A voir aussi sur CPCrulez , les sujets suivants pourront vous intéresser... |
CPCrulez[Content Management System] v8.73-desktop/c Page créée en 008 millisecondes et consultée 1980 foisL'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. |
|
|