Programmation Assembleur Z80/Assembler
= Assembler un programme =
Les directives.
Pour pouvoir assembler un programme, il suffit rarement d'écrire les quelques lignes d'assembleur pour avoir un programme fonctionnel. En général, il faut préciser son adresse d'exécution afin de renseigner correctement les sauts absolus ou la localisation des variables mémoire. Il est alors nécessaire d'utiliser des directives, qui ne sont pas des instructions Z80 mais des ordres indicatifs afin que l'assembleur sache exactement quoi faire de notre programme. La plupart des assembleurs utilisent les mêmes directives mais il y aura des adaptations nécessaires selon celui que vous utilisez. Parmi toutes les directives, les plus essentielles sont celles qui permettent de réserver de l'espace en mémoire pour y mettre des variables ou valeurs.
DEFB.
Cette directive est l'abréviation de Define Byte. Elle a pour usage de réserver un ou plusieurs octets. Ces octets peuvent être écrits sous forme texte ou de valeurs litérales.
 DEFB 0 ; un octet de valeur 0
 DEFB 1,2,3 ; trois octets de valeurs respectives 1,2 et 3
 DEFB 'bonjour' ; 7 octets de valeur ascii correspondant aux lettres du mot bonjour. Il n'y a pas de code terminateur ajouté comme dans d'autres langages.
 DEFB 5,'coucou',18 ; on peut mélanger les déclarations
DEFW.
Cette directive déclare un mot (Word) de 16 bits. On ne peut pas utiliser de texte (sauf une lettre unique entre quote) avec cette instruction. Par contre, on peut y mettre la valeur d'un label sans risquer le débordement.
 DEFW 5
 DEFW monlabel
Portée du programme.
Il est impératif de se poser quelques questions avant d'assembler un programme, les voici:
Si le programme est susceptible revenir au système, il est impératif de sauvegarder tous les registres qui seront modifiés et de restaurer les interruptions si celles-ci sont modifiées.
Si le programme ne revient pas au système, il n'y a rien à prévoir.
Si le programme a besoin du système, il est impératif qu'il s'exécute dans une zone mémoire disponible et qu'il n'altère pas les zones système.
Si le programme n'a pas besoin du système ET qu'il n'a pas besoin de rendre la main, alors on peut se positionner où l'on veut en mémoire et écraser toute la mémoire au besoin.
Choisir l'emplacement du programme et des données en mémoire.
ORG.
Le choix de l'adresse d'assemblage se fait avec la directive ORG
 ORG #8000 ; commencer à assembler à l'adresse #8000
 JR $ ; boucle infinie sur lui même
On peut utiliser autant de ORG que l'on veut dans un programme, afin de positionner facilement des données à différents endroits de la mémoire. Dans l'exemple ci-dessous
 ORG #8000
 LD HL,machaine ; charge l'adresse de machaine dans HL
 JR $ ; boucle infinie sur lui même
 ORG #9000
 machaine DEFB 'premier programme'
ALIGN.
Afin de réaliser des optimisations d'accès mémoire, on peut vouloir aligner des données sur des adresses paires, multiples de 16, 32, 55, etc. ou plus pragmatiquement 256. La directive ALIGN va ajouter des octets vides jusqu'à pointer sur une adresse multiple de la valeur d'alignement souhaitée.
 ALIGN 2
 DEFW maroutine1
 DEFW maroutine2
 DEFW maroutine3
L'intérêt de l'alignement est d'utiliser des instructions plus rapides lors de la lecture des données en mémoire. Si on stocke des valeurs 16 bits sur des adresses paires, on sait qu'il n'est pas utile de faire une incrémentation 16 bits du pointeur pour aller chercher le deuxième octet de la valeur, car une incrémentation 8 bits ne débordera jamais.
Macro assemblage.
Les répétitions.
Il est courant d'avoir à répéter des instructions ou déclarations dans un programme. Pour s'éviter de longs et indigestes copié-collés, la directive REPEAT est d'un grand secours.
 REPEAT 32 ; répéter 32 fois la séquence
 PUSH DE ; code à répéter
 REND ; marqueur de fin de boucle de répétition
Les blocs de REPEAT peuvent s'imbriquer. Dans l'exemple ci-dessous on déclarera 256 octets de valeur 2
 REPEAT 8
 REPEAT 8
 DEFB 2
 REND
 REND
Les variables.
Les variables d'assemblage sont des variables ou valeurs qui ne seront pas intégrées au binaire final, bien qu'elles puissent aider à générer ce dernier. Un label est une variable (qui ne change pas au cours de l'assemblage). Le label indique une adresse afin de pouvoir calculer des sauts absolus ou relatifs. Une variable sert à la même chose, à ceci près qu'on peut la faire évoluer dans le temps. Les variables trouvent aussi leur utilité pour réaliser du code modulaire. On peut construire son code à partir de la valeur d'une variable et changer le code en modifiant cette valeur.
Exemple de déclaration d'une table de sinus
 angle=0
 ALIGN 256
 REPEAT 256
 DEFB sin(angle)*127
 angle=angle+360/256
 REND
Les labels locaux.
Dans une boucle de répétition de code, si on écrit un label, l'assemblage tombera en erreur car le label sera déclaré plusieurs fois. Il est possible de déclarer un label local. C'est à dire que ce label ne peut être appelé que lors de l'itération courante de la boucle. Un label local est préfixé par le symbole '@' (Avec l'assembleur de Winape ou RASM).
Par exemple, si on veut factoriser le code suivant avec une boucle REPEAT:
 ADD HL,BC
 JR NC,saut1
 INC DE
 saut1
 ADD HL,BC
 JR NC,saut2
 INC DE
 saut2
Le rôle du label local est exactement de numéroter 1,2,3 le label, mais de façon transparente, c'est à dire qu'au niveau de l'écriture, tout est transparent:
 REPEAT 2
 ADD HL,BC
 JR NC,@saut
 INC DE
 @saut
 REND