Assembleur Z80 sur RC2014 - épisode 3 - Données en mouvement
Bonsoir à tous,
Voici la suite des découvertes de l'assembleur Z80 sur RC2014 en utilisant SCM (Small Computer Monitor, voir sa configuration), il est possible de faire de l'assembleur directement sur le RC2014-Pro.
Nous continuons le visionnage des vidéos de Matt Heffernan relatif à la programmation Z80 sur Spectrum pour adapter les exemples au RC2014.
Episode 3: données en mouvement
L'épisode 2 sur l'adressage avait déjà abordé la transfert de données entre la mémoire et les registres. Ces points seront forcement revu et complété avec de nouvelles instructions dédiés au transfert de données.
Les registres du Z80
bien que déjà abordé à l'épisode précédent, cette petite révision apportera des éléments complémentaires.
- A <-- transfert 8bits uniquement
- BC, DE, HL <-- transfert 16bits ou 8bits
- SP <-- Stack Pointer: transfert 16bits uniquement
A noter que:
- I: Interrupt Vector peut uniquement être chargé dans A
- R: Memory Refesh Rate peut uniquement être chargé dans A
LD : LOAD
Cette instruction couvre pas moins de 184 opcodes, c'est dire si elle est importante!
LD prend deux opérantes:
- destination
- source
Operands utilisables avec la commande LD (load) |
Il faut noter que A est le seule à pouvoir être chargé avec I et R.
HL ne peut pas être utilisé conjointement avec les registres d'index IX et IY.
Registres 8bits-vers-8bits
ld A, I
ld R, A
Registres 16bits-vers-16bits
ld SP, HL ; charger le stack pointer
ld SP, IX
ld SP, IY
Chargement immédiat
ld A, 42
ld B, 42 -> aussi pour C, D, H, L, IXh, IXl, IYh, IYl
Chargement immédiat en mémoire
ld (HL), 42 -> stocker 42 en mémoire à l'adresse indiquée par HL.
ld (IX+3), 42
ld (IY-9) 42
Chargement immédiat étendu (16 bits)
ld BC, 1234 --> aussi poir DE, HL, IX, IY
Chargement directement depuis la mémoire:
8bits ---vers---> A pour tous les registres 16 bits (BC, DE, HL, IX, IY)
8bits ---vers---> B,C,D, ... pour HL, IX, IY uniquement
ld a, ($A234)
Il est donc impossible de faire un LD B, (DE) .ld DE, ($A234)
ld ($A234), BC
EX : EXCHANGE
Cette instruction permet d'échanger deux registres 16 bits. L'instruction dispose de 5 opcodes!
L'instruction ex af, af' permet d'échanger l'accumulateur et les flags pour les préserver (sans charger la pile/stack)
ex af, af'
L'instruction ex de, hl est utile lorsque l'on utilise hl pour faire du calcul.
ex de, hl
L'instruction ex (sp), hl permet d'échanger la valeur de hl avec la mémoire pointée par le stack pointer. Les opérations sur le stack pointer doivent être envisagés avec prudence (il faut savoir ce que l'on fait.
ex (sp), hl
ex (sp), ix
ex (sp), iy
EXX : EXCHANGE eXtended
Cette instruction permet d'échanger les 3 paires de registres BC <--> BC' , DE <--> DE' , HL <--> HL' en une seule instruction!
LDI : Load Increment
Copie un octet d'un emplacement mémoire (indiqué par le registre HL) à un autre emplacement (indiqué par les registres DE). Puis incrémente la valeur des deux registres.
Le registre BC est également décrémenté de 1. Celui-ci sert de compteur de fin (une fois à 0, on peut arrêter une routine de copie).
Pour résumé:
(DE) <-- (HL)
DE = DE+1
HL = HL+1
BC = BC-1
LDIR : Load Increment Repeat
Copie Nth octets d'un emplacement à un autre à l'aide de la commande LDI.L'opération est répétée jusqu'à ce que BC = 0.
Par exemple, pour copier les 6912 octets de $E000 à $4000, on utilise le code suivant:
ld DE,$4000 ; destin
ld HL,$E000 ; source
ld BC, +6192 ; longueur
ldir
LDD : Load Decrement
Comme LDI, l'instruction LDD permet de copier le contenu d'un emplacement mémoire (pointé par HL) vers un autre emplacement mémoire (pointé par DE). Ensuite HL et DE sont diminué de 1.Le registre BC (compteur) est également diminué de 1. Une fois arrivé à 0, il permet de d'arrêter une boucle de copie.
(DE) <--- (HL)
DE = DE -1
HL = HL -1
BC = BC -1
LDDR : Load Decrement Repeat
Similaire à LDDI avec la seule exception que la copie de fait d'une adresse haute vers une adresse basse (puisqu'il y a des soustractions).Avec des éléments bien organisés en mémoire, il y a moyen de gagner du temps opérationnel (puisqu'on serait déjà au bon emplacement mémoire pour préparer la salve de copie suivante).
Voici comment copier les 6912 bytes de $E000 à $4000.
Destin = $4000 + 6911 = 0x5AFF
Source = $E000 + 6911 = 0xFAFF
Voici le code
ld DE,$5AFF ; destin
ld HL,$FAFF ; source
ld BC, $1b00 ; 6912 bytes
lddr
Lorsque l'exécution est terminée, BC = 0 et l'adresse source (comme la destination) à passée la valeur de fin de 1.
Donc:
- DE (la destination) = $4000-1 = $3FFFF
- HL (la source) = $E000-1 = $DFFF
Exercice
Ecrire un programme en $8000 qui copie la chaine de caractère "RC2014 is awesome! " (stocké en $8500).Préparation de la mémoire
fill 8000 8100 00 fill 8500 8600 00 fill ff00 ffff 00
Copie simple et exécution
8000: 11 FF FF ... LD DE,$FFFF 8003: 21 12 85 !.. LD HL,$8512 8006: 01 13 00 ... LD BC,$0013 8009: ED B8 .. LDDR 800B: C9 . RET 800C: 00 . NOP 800D: 00 . NOP
*g 8000 *m ff80 FF80: ED B0 C9 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ FF90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ FFA0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ FFB0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ FFC0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ FFD0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ FFE0: FF FF FF FF FF FF FF FF FF FF FF FF FF 52 43 32 .............RC2 FFF0: 30 31 34 20 69 73 20 61 77 65 73 6F 6D 65 21 20 014 is awesome!
Écrire un commentaire