« Programmation Assembleur Z80 » : différence entre les versions

Contenu supprimé Contenu ajouté
→‎Les registres : Déplacé en sous-page
→‎Jeu d'instructions : déplacé en sous-page
Ligne 11 :
 
== [[Programmation_Assembleur_Z80/Jeu_d_instructions|Jeu d'instructions]] ==
 
=== Convention pour la définition des instructions ===
 
reg8 : registre 8 bits (sauf I ou R)
reg16 : registre 16 bits (sauf PC,SP,IR)
n : valeur immédiate 8 bits
nn : valeur immédiate 16 bits
(reg16): valeur en mémoire indexée par un registre 16 bits (sauf PC,SP,IR)
(nn) : valeur en mémoire indexée en absolu par une valeur 16 bits
 
=== Valeurs litérales ===
 
Il est important de signaler que les valeurs littérales exprimées ici représentent un consensus global entre assembleurs Z80 mais les assembleurs les plus anciens ne supportent pas toutes les syntaxes.
 
12345 ; valeur décimale
#1234 ; valeur hexadécimale
&1234 ; valeur hexadécimale
$1234 ; valeur hexadécimale
0x1234 ; valeur hexadécimale
%01010 ; valeur binaire
0b1010 ; valeur binaire
@4736 ; valeur octale
 
=== Charger des valeurs ===
 
L'instruction de base pour charger une valeur est LD (contraction de LOAD)<br>
 
On peut utiliser différente combinaisons de LD (cette liste est indicative)
 
LD reg8,im8 ; charger une valeur immédiate 8 bits dans le registre 8 bits
LD reg8,reg8 ; charger reg8 dans reg8
LD A,(nn) ; charger la valeur stockée à l'adresse nn dans A
LD A,(reg16)
LD reg8,(HL) ;sauf XH,XL,YH,YL
LD reg16,nn
LD reg16,(nn)
LD (nn),reg16
LD (nn),A
LD (reg16),A
LD (HL),reg8 ;sauf XH,XL,YH,YL
 
Il n'est pas possible de charger un registre 16 bits dans un autre mais on peut utiliser presque toutes les combinaisons possibles avec les registres 8 bits. Ainsi, pour charger HL dans BC:
LD H,B
LD L,C
 
=== Opérations de modification par bit ===
On peut tester, effacer ou positionner chaque bit individuellement d'un registre ou d'un octet en mémoire avec ces opérations.
BIT n,reg8 ; tester un bit (sauf XH,XL,YH,YL)
BIT n,(reg16) ; tester un bit (sauf BC,DE)
SET n,reg8 ; positionner un bit (sauf XH,XL,YH,YL)
SET n,(reg16) ; positionner un bit (sauf BC,DE)
RES n,reg8 ; effacer un bit (sauf XH,XL,YH,YL)
RES n,(reg16) ; effacer un bit (sauf BC,DE)
 
n est le numéro de bit à traiter, valeur de 0 à 7 avec 0 pour le bit le moins significatif.<br>
Le registre est un registre 8 bits parmi les suivants: A,B,C,D,E,H,L (impossible avec les registres XH,XL,YH,YL)<br>
La mémoire est une valeur indexée: (HL), (IX+n) ou (IY+n) avec n valeur immédiate 8 bits signée de -128 à 127<br><br>
 
=== Opérations de décalage et rotations de bit ===
 
RR
RL
RRA
RLA
RRCA
RLCA
SLA
SLL
SRA
SRL
 
=== Opérations logiques de base ===
Il est possible de modifier la valeur d'un registre avec des opérations. La plupart de ces opérations, cependant, affectent seulement le registre A.
Les instructions a utiliser sont AND, CPL, NEG, OR, et XOR.
Ces instructions ne peuvent être appliquées qu'au registre A. leur syntaxe est:
 
AND A,reg8
AND A,im8
AND A,(reg16) ; sauf BC et DE
OR A,reg8
OR A,im8
OR A,(reg16) ; sauf BC et DE
XOR A,reg8
XOR A,im8
XOR A,(reg16) ; sauf BC et DE
 
CPL ; complément à deux du registre A (inverse tous les bits)
NEG ; A devient A soustrait de zéro (inverse le signe mathématique)
 
 
Ce sont des opérateurs logiques binaires, AND réalise un ET logique de la valeur donnée avec le registre A dans lequel il va stocker le résultat. OR effectue de la même façon un OU logique inclusif. et XOR un OU exclusif. Par exemple:
LD A,32
OR 16
va donner à A la valeur 48, car si on écrit l'opération en binaire:
00100000 =32
00010000 =16
-------- OU
00110000 =48
 
Positionnement des flags:
C et N sont effacés
P/V est la paritée
Le reste est modifié par définition
 
=== Opérations mathématiques de base ===
 
SUB A,im8
SUB A,reg8
SUB (reg16)
 
ADD A,im8
ADD A,reg8
ADD (reg16)
ADD HL,HL | BC | DE | SP ; combinaisons possibles avec HL,BC,DE ou SP
ADD IX,BC | DE | IX | SP
ADD IY,BC | DE | IY | SP
 
ADC et SBC offrent les mêmes combinaisons que ADD avec A, (reg16) et HL
 
=== Opérations de copie mémoire ===
 
Si il est possible de copier la mémoire à partir d'instructions simples, le Z80 offre plusieurs instructions de copie de blocs avec ou sans répétition.
 
LDI ; copie mémoire et incrémentation
LDR ; copie mémoire et décrémentation
LDIR ; copie mémoire et incrémentation (avec répétition)
LDDR ; copie mémoire et décrémentation (avec répétition)
 
Le pseudo-code est le suivant:
copymem
LD A,(HL)
LD (DE),A
INC HL
INC DE
DEC BC
JR NZ,copymem ; note:impossible à faire en vrai car DEC BC ne modifie pas les flags
 
Ces super-instructions ont deux avantages.<BR>
* Le premier est de pouvoir utiliser BC comme compteur 16 bits et de tester si BC est égal à zéro pour la répétition
* Le temps d'exécution de cette super instruction est deux fois plus rapide que de décomposer en instructions simples
 
=== Opérations d'entrée/sortie ===
 
Il est possible de lire ou d'écrire sur un port mémoire. Cette section ne sera pas détaillée car les opérations d'entrée/sortie sont spécifiques au matériel avec lequel est connecté le Z80. Pour la petite anecdote, sur l'Amstrad CPC, les ingénieurs ont inversés les bits de poids fort avec les bits de poids faible du port d'entrée/sortie par économie, rendant inutilisables toutes les fonctions entrée/sortie de répétition qu'offre le Z80. Le processeur Z80 est conçu pour un design qui utilise le port pointé par le registre C alors qu'Amstrad a créé un design qui utilise le registre B pour pointer le port. Comme les instructions de répétition utilisent le registre B comme compteur, il faut pouvoir réajuster le registre B à chaque itération.
 
OUT (C),A ; envoyer la valeur du registre A sur le port C
OUT (C),B
OUT (C),C
OUT (C),D
OUT (C),E
OUT (C),H
OUT (C),L
OUT (C),0 ; envoyer zéro sur le port C
OUT (im8),A ; envoyer A sur le port im8
 
Les instructions suivantes sont des instructions groupées
 
OUTI ; décrementer B*, envoyer la valeur de (HL) sur le port C, incrémenter HL
OUTD ; idem mais avec décrémentation de HL
OTIR ; instruction avec répétition tant que B>0
OTDR ;
 
Il est important de noter que le registre B est décrémenté AVANT d'envoyer la valeur de (HL) sur le port, car comme sur l'Amstrad le port de sortie est le port B, si on veut envoyer une valeur sur le port B, il faut envoyer B+1 comme valeur!<br>
 
== Les flags ==