CODING ★ LES TRANSFERTS ★

Assembleur ACPC n°37 - Les transferts

Si vous étiez des nôtres les mois passés, vous avez remarqué qu'il existe une instruction qui revient à tout va dans les listings Assembleur. C'est le mnémonique «  LD ».

A prononcer « LOAD », cette instruction permettra d'affecter des valeurs à des registres. C'est l'équivalent Basic de « A = 45 ». Vous pourrez également à raide de ce mnémonique, charger vos registres avec des valeurs de la mémoire, comme « A = PEEK(&A000) » et vice versa, l'inverse de l'opposé du contraire, comme « POKE &C000,&BC ». Elle fait partie de la famille des...

INSTRUCTIONS DE CHARGEMENT

Nous allons voir ensemble ces opérations. Comment passer une valeur d'un registre à un autre, transférer une valeur d'un registre en mémoire et lycée de Versailles. Cela n'est pas si simple qu'on l'imagine car tous les coups ne sont pas permis. Pour commencer, prenons un petit exemple:

POKE 30000,12

Si votre source Assembleur commence en 40000, vous conviendrez avec moi que ce dernier ne modifiera en aucun cas la valeur 12 placée en 30000. Vous pouvez, dès lors, récupérer celle-ci à raide de la commande « LD ». Voici la procédure à suivre:

LD A,(30000)

Nous pouvons lire cette instruction comme, « Place dans l'accumulateur le contenu de l'octet 30000 ». Pour le Basic, vous pouvez la comparer à « A=PEEK(30000) ». Il va de soi que suite à cette opération, la valeur 12 sera attribuée à l'accu.

Un point important qu'il faudra graver dans vos petites cellules grises: « En transférant une valeur par l'instruction LD, on ne modifie aucunement la source mais seulement la destination.» Dans le cas de l'exemple donné plus haut l'accumulateur contient, après l'opération, la valeur 12 et la case mémoire 30000 garde toujours cette valeur sans être modifiée. Ne vous occupez pas non plus de ce qui a pu advenir du contenu de l'accumulateur. Il a simplement et irrémédiablement été jeté à la poubelle. La valeur 12 a pris sa place et ce qu'il y avait en dessous a été bêtement écrasé.

C'est maintenant que nous pouvons constater l'importance de l'accumulateur. En effet, ne comptez pas transférer une valeur de la mémoire en passant par un autre registre ( pour connaître la liste quasi complète, référez-vous aux divers (ver) docs foumis avec la rubrique.

TROIS POUR TOUS TOUS POUR UN

Sachez qu'il existe trois types de chargement. Le transfert entre deux registres, entre une valeur fixe et un registre, et celui effectué entre un registre et un octet de la mémoire. Prenons les choses une par une et développons séparément ces trois types de chargement.

Pour commencer, examinons ce qu'il y a de plus simple. Les transferts directs pour les registres. Nous pouvons considérer cela comme des initialisations directes. Pour rester dans l'équivalent Basic, cela revient à des «  A= 12, BC=543, etc.  ». Tous les registres peuvent béneficier de ce mode de transfert.

LD A, 12
LD B,15
LD H,13
LD L,45
LD D,5
LD E,255
LD BC,1000
LD DE,600
LD HL,0

Si vous êtes un peu plus avancé que notre initiation, vous constaterez que l'on garde bien au chaud. quelques registres, comme IX, IV, SP et d'autres. La raison de cette omission est, bien sûr, volontaire. Ne vous prenez donc pas le chou avec ces registres qui dans l'immédiat ne nous seront d'aucune utilité. Cela dit revenons à nos moutons, voici les transferts...

ENTRE REGISTRE ET MÉMOIRE

Contrairement à la première catégorie, vous ne pouvez pas charger tous les registres à partir de la mémoire. En effet, cela ne pose aucun problème avec l'accumulateur et les registres 16 bits; par contre essayez « LD B,(1234) » et vous m'en donnerez des nouvelles.

Comme vous le constatâtes en amont de ces lignes, nous pouvons adresser les registres en utilisant la mémoire de l'ordinateur (l'adresse mémoire est mise entre parenthèses). Nous retrouvons l'application de l'instruction PEEK de notre cher Basic.

Dès lors, rien ne nous empêche de placer la valeur d'un registre en mémoire « POKE )) ou plus simplement récupérer un octet (voire deux) dans un registre « PEEK».

Les transferts registre-mémoire peuvent être de deux natures selon le registre utilisé. Si vous avez affaire à un registre simple, ce ne peut être que l'accumulateur:

LD (ADRESSE),A

Comme POKE ADRESSE,A

ou

LD A,(ADRESSE)

Comme A = PEEK(ADRESSE)

En littéral, nous dirions:

Comme vous le voyez, il est plus simple de dire LOAD.

Le premier exemple place la valeur de l'accumulateur dans l'octet ADRESSE, alors que le deuxième exemple ne fait que le contraire. Comme je le disais plus haut, vous ne pouvez utiliser les autres registres 8 bits comme (B,C,D.E,H et L). Par contre, vous pouvez utiliser ces dernier sous forme de registre 16 bits.

DEUX OCTETS SEIZE BITS QUELLE NUIT...

En ce qui concerne les registres 16 bits, ils ne réagissent pas tout à fait de la même manière que leurs moitiés. En effet, si l'accumulateur se retrouve chargé avec l'octet souhaité, il n'en va pas de même avec les registres doubles. Mais voyons cela plus en détail. avec ces quelques exemples.

LD BC,(ADRESSE)
LD DE,(ADRESSE)
LD HL,(ADRESSE) et
LD (ADRESSE),BC
LD (ADRESSE),DE
LD (ADRESSE),HL

Cela paraît simple mais ATTENTION. Le transfert, lorsque vous utilisez un registre 16 bits, ne se fait plus sur un octet de la mémoire mais sur deux. Tachons de nous faire mieux comprendre.

LD BC,(ADRESSE)

Revient à :

LD C,(ADRESSE)

Suivi de :

LD B,(ADRESSE+ 1)

Je vous préviens tout de suite, les deux dernières instructions n'existent pas. Nous les donnons pour une meilleure compréhension des transferts 16 bits ( lisez le dernier paragraphe pour tout comprendre ).
Si vous donnez l'adresse en valeur fixe, cela ne pose aucun problème si ce n'est qu'il sera quasiment impossible de la modifier au cours du programme, mais en utilisant le registre HL, nous pouvons créer d'une certaine manière, le principe des variables.

LD A,(HL)
LD B,(HL)
LD C,(HL)
LD D,(HL)
LD E,(HL)
LD H,(HL)
LD L,(HL)

Nous pouvons donc écrire:

LD A,( 10000 )

ou

LD HL,10000
LD A,(HL)

LES REGISTRES ENTRE EUX!

Il n'existe aucune interdiction pour attribuer la valeur d'un registre simple (8 bits) à un autre. Vous pouvez, à votre guise, faire tous les mélanges possibles. En voici tout de même la liste:

LD A,A
LD B,A
LD C,A
LD A,B
LD B,B
LD C,B
LD A,C
LD B,C
LD C,C
LD A,D
LD B,D
LD C,D
LD A,E
LD B,E
LD C,E
LD A,H
LD B,H
LD C,H
LD A,L
LD B,L
LD C,L
LD D,A
LD E,A
LD H,A
LD H,B
LD H,C
LD H,D
LD H,E
LD H,H
LD H,L
LD D,B
LD D,C
LD D,D
LD D,E
LD D,H
LD D,L
LD E,B
LD E,C
LD E,D
LD E,E
LD E,H
LD E,L
LD L,A
LD L,B
LD L,C
LD L,D
LD L,E
LD L,H
LD L,L

Pour les registres doubles c'est égaiement très simple. Vous ne pouvez absolument pas attribuer à un registre 16 bits la valeur d'uri autre registre 16 bits. Bien sûr, rien ne vous empêche de remplacer les instructions inexistantes comme:

LD HL,BC

par:

LD H,B
LD L,C

Je pense qu'il est bon de faire une pause pour vous toucher deux mots sur le mode de fonctionnement des registres 16 bits. Alors, sans plus tarder...

DEUX FOIS HUIT EGALE SEIZE ?

Voici un tout petit programme:

ORG 40000
LD HL,1234
LD A,H
LD (10000),A
LD A,L
LD (10010),A
LD (10020),HL
RET

Encodez ce programme et lancez-le. A partir du Basic vous pouvez à l'aide de « PEEK » lire les octets 10000, 10010,10020 et 10021.

Voici le résultat :

10000 = 4
10010 = 210
10020 = 210
10021 = 4

Mais où est passé notre 1234 ? Seul moyen de le retrouver, faire l'opération suivante: ' 4 * 256 + 210 = 1234

Nous devons faire intervenir la notion de poids faible et poids fort des registres 16 bits. Prenons comme d'habitude un exemple simple pour mieux nous faire comprendre, celui des chiffres décimaux. Vous savez tous qu'un registre 8 bits ne peut contenir une valeur supérieure à 255. C'est le tas du registre « L ». Imaginez dans notre système décimal, les chiffres ne pouvant dépasser 99. Exemple L=99 (c'est le poids faible). Si j'incrémente cette variable, elle passera automatiquement à zéro si elle avait le malheur de se balader seule dans les parages. Si elle se faisait accompagner par son grand frère, la variable « H ») \( lui, c'est le poids fort), elle passerait toujours à zéro mais donnerait le mot à son frangin qui, lui, s'incrémenterait. Nous pourrons dès lors en comptant la valeur de « H ), savoir combien de fois « L ) fut débordé. En d'autres termes, si l'on multiplie par 100 la valeur de « H )) et que l'on ajoute à l'ensemble la valeur de « L », on obtient la somme totale de l'ensemble.

Il en va de même pour les registres 16 bits. La seule nuance est que le débordement ne se fait pas sur 100 mais 256.

Cela vous paraît dur à comprendre? Imbitable, voire incompréhensible? Ne vous en faites pas. Relisez ces pages, essayez d'autres exemples et cela vous paraîtra d'une simplicité à n'en pas croire vos doigts de pieds. Que dis-je, d'une limpidité à faire des jaloux chez les poissons d'eau douce. Gloups.

Sined et Poum, ACPC n°37, p42-43

Page précédente : Bidouilles ACPC n°36 - Direct disk Access

CPCrulez[Content Management System] v8.7-desktop/cache
Page créée en 144 millisecondes et consultée 1149 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.