★ CODING ★ HEBDOGICIEL ★ FORMATION A L'ASSEMBLEUR PRATIQUE LANGAGE MACHINE ★ |
La page pédagogique d'hebdogiciel 120: Le Pointeur SP | Coding Hebdogiciel |
AU COMMENCEMENT FUT LA SUITEOù en était-on ? A cet atroce petit programme commenté d'un "devinez" écrit en charabias (non, c'était de l'assembleur). Votre cervelle a dégouliné pendant trois semaines sur le bas de la page de notre dernier cours d'assembleur ? Alors là, je ne suis pas d'accord. Il faut suivre. Surtout qu'on vous a déjà dit que c'était simple... (Solution des Jeux : le programme était destiné à vous montrer la valeur du pointeur de pile SP). PARAGRAPHE A NE PAS LIRE Parce qu'avec un tant soit peu de curiosité et d'envie de programmer comme un Dieu (enfin, mieux que le copain qui vient vous gonfler tous les week-ends avec ses programmes nuls), vous auriez déjà compulsé un bouquin sur les mnémoniques du Z80, et vous y auriez trouvé une dissection complète de la mnémonique "LD". Bon, on vous pardonne. Mais levez les yeux et allez zyeuter le haut de la page. Vous avez remarqué ? Il y a l'adjectif "pratique" la-haut. Ce qui signifie qu'on est complémentaire, voilà tout, complémentaire d'un bon bouquin théorique (exemple : Programmation du 280 par Rodnay Zaks chez Sybex). Notre rôle ne se limitera pas à vous apprendre à bien utiliser, sur votre machine, les mnémoniques que ce genre de bouquin vous aura présentés, mais il devrait. LD SUPER-STAR Alors "LD". qu'est-ce ? Il sagit du début d'un type de mnémonique très Important puisque c'est celui que vous emploierez le plus souvent En effet, LD vient de LoaD, et "load", c'est "charger" en anglais. Oui nuls charger quoi ? Des registres ou des emplacements mômoires, on l'a vu. Un programme, quai que soit son langage, est toujours un processus logique qui déplacera des données (d'un octet de RAM quelconque vers un octet de la RAM de l'écran par exempte) selon un ordre précis. Et un programme, ce n'est que cela. SINTAX : HIC ! (NUL)
RÉ-EXPLICATION PAR L'EXEMPLE LD (HL),A Commentaires : cette mnémonique place le contenu du registre A à l'adresse mémoire précisée par HL Le contenu du registre A est l'opérande source et le contenu de l'adresse HL est l'opérande destination. LD EN FAMILLE Atiention, les descriptions qui vont suivre précisent l'assignation des registres a des fonctions particulières telles que nous l'avions avancé dans notre dernier cours.
— registre 8 bits : rien à dire, H y a des LD pour tous, soit 49 mnémoniques de ce type car le Z80 a 7 registres de travail en 8 bits (A. 8. C. D. E, H et L). — registres 16 bits : restreint, 3 mnémoniques. Un seul opérande destination possible : SP. Les voici : LD SP,HL
On parle d'adressage immédiat lorsque l'opérande source est directement mentionné. L'assemblage des mnémoniques utilisant ce mode d'adressage place l'opérande source à t'adresse suivant immédiatement le code opération. — 8 bits : c'est bon pour les 7 registres de travail. L'opérande source ( &10 dans notre exemple ), bien évidemment, est compris entre 0 et &FF car il doit pouvoir entrer dans le registre et est donc codé sur un octet. LD A,&10 assemblé produira le code machine &3E suivi de &10. On voit que &3E, code opération, est suivi immédïatemment de &10. l'opérande source. — 16 bits : OK pour les 3 paires de registres (HL, DE et BC) principales. mais aussi pour les registres d'index et le pointeur de pile ( IX et IY, SP ). Exemple : LD HL,&1234 ; effectue Rappel : en mémoire, l'octet bas est placé avant l'octet haut. L'assemblage de notre exemple produira tes codes machinée suivants : &21 (pour LD HL.) suivi de &34 puis &12 ( pour &1234 ).
— Avec la valeur de l'adresse source précisée directement : la destination est obligatoirement le registre A. LD A,(&1234) produit A = PEEK (&1234). — Avec les registres BC ou DE comme pointeurs de source : la destination est aussi forcement le registre A. On a : LD A,(BC) et LD A,(DE) et c'est tout. — Pour une destination registre 8 bits quelconque (c'est à dire B, C, D, E, H ou L, et aussi A, mais lui, il peut faire autrement, on vient de le voir) : la source doit être (HL), (IX+d) ou (IY+d), . Exemptes : LD B,(HL) place le contenu de l'adresse pointé par HL dans te registre B. LD C,(HL), JLD E,(HL) : même chose avec C et E. TIENS REVOILA LES REGISTRES D'INDEX Ils sont spéciaux ceux-là. D'abord parce qu on ne doit pas toucher à IY (pour l'instant c'est comme ça puis c'est tout). Puis parce qu'on peut tour ajouter un déplacement 8 bits pour préciser l'adresse effective de l'opérande. Comment ça ? Comme ça ; LD IX,&1200 ; charge IX avec &1200. IX = &1200. Mais attention, ce déplacement est un nombre signé en complément à 2 (positif entre 0 et &7F soit 0 et 127 donc avec le bit 7 à 0, négatif entra SFF et &80 soit -1 et -128, bit 7 à 1). Là vous suivez plus, Ne vous inquiétez pas on reparlera des représentions binaires diverses. De toutes façons vous n'avez pas à tenir compte de ça pour l'indexation, vu que sous assembleur vous écrirez, par exemple, pour un déplacement de -10 octets : LD B,(ix-10). Héhéhé.. — Chargement d'un registre double par deux octets de mémoire en une seule opération : Oui ça existe (c'est presque du 16 bits) et c'est valable pour les 6 registres 16 bits (BC, DE, HL. IX, IY et SP). Exemple : LD BC,(&1000) chargera BC avec les deux octets des adresses &1000 et &1001. C'est l'équivalent Basic de C = PEEK(&1000) :B = PEEK(&1001). On voit encore une fois l'Importance de l'ordre de rangement octet faible/octet fort.
COMMENT ÇA, "SIMPLES", Y EN AURAIT-IL DÉS "COMPLIQUÉS" ? Non. Compliqué, ça n'existe pas. Mais le Z80 profite aussi de LD " à répétition" . Voyons donc comment user d'une instruction à répétition face à la mémoire récalcitrante ils vont obéir ces fourmillants octets ! On va devoir d'abord préciser la sens d'opération de ces supers instructions. On s'explique. On va effectuer une série de LD. Chacun des LD d'une série de ce type enverra le contenu d'une adresse source vers une adresse destination. Entre chaque LD, on fera varier les pointeurs de source et de destination. Oui, mais va-t-on Incrémenter ces pointeurs ( les augmenter de 1 ) OU les décrémenter ( décrémenter est le contraire d'incrémenter ) ? Ceci reste de notre ressort. On le précisera par un D (pour décrément ) ou par 1 ( pour incrément ). Ça, c'est pour le théorique, voyons maintenant le pratique. L'opérande source de ce type d instruction sera toujours pointé par le registre double HL, L'opérande destination sera pointé par DE (on peut, pour s'en rappeler, constater que D et E sont les premières lettres du mot destination). Donc, en combinant LD et I , on obtient LDI, LD et D . LDD. Et LDI et LDD sont effectivement deux mnémoniques du Z80. Si vous nous avez suivis, vous savez déjà que LDI chargera le contenu de l'adresse DE avec le contenu de l'adresse HL, puis incrémentera les registres HL et DE. Traduction en Basic : LDI effectue POKE DE ,PEEK (HL): HL = HL + 1 :DE = DE + 1. Il en est de même pour LDD, mais dans l'autre sens, LDD en Basic : POKE DE,PEEK (HL) :HL = HL - 1 :DE = DE - 1. ET LA RÉPÉTITION DANS TOUT ÇA? Rien de plus simple, un petit R en plus (pour "Répétition") et tout est réglé. Nous voici avec LDIR et LDDR, mnémoniques du 290. Et naturellement, il nous faut déterminer le nombre de répétitions désiré... par te registre BC qui est le registre compteur par excellence Résumé: LDIR envoie l'octet d'adresse HL à l'adresse DE, incrémente HL et DE et recommence tant que BC n'est pas nul. On peut assimiler LDIR à la boucle Basic : FOR I=BC TO 0 STEP-1 : POKE DE, PEEK (HL) : HL=HL+1 : DE = DE + 1 : NEXT ILDDR à la même boucle mais avec HL - HL-1 : DE - DE-1. Hebdogiciel n°120 , Nicolas et Zeev
|