CODINGANTOINE ★ ASSEMBLEUR Z80 - Les codes spéciaux ★

Z80: Les Codes Speciaux (1/2)Coding Antoine

Eh oui ! Après vous avoir  fait  ch..  en  vous  bassinant  sur  les  codes non-valides du Z80 et en vous refilant une routine dont vous ne saviez que faire et qui de plus etait buggeé, je vais enfin TOUT vous dire sur ces fameux  codes. Tout d'abord il faut que je réponde à une question que vous vous posez surement: Ma qu'est-ce que ça sont que ces codes spéciaux (combien de fois vais-je répéter ce mot ?!) ? Et bien ce sont des codes qui  ne  sont  pas  mentionnés  dans  les  livres classiques tels "l'initiation à l'assembleur" ou "le langage  machine  de l'Amstrad", et qui normalement sont inconnus de  la  plupart  des  programmeurs. Notez qu'à la fin du bouquin  "la  Bible  du  CPC  6128",  les  auteurs  parlent d'"instructions  spéciales  du  type  &CB  (IX+d)"  ;  en  vérité  ce  que  leur désassembleur ne digère pas, ce sont des codes tout à  fait  normaux  comme  SRL (IY+4) - par exemple - rien à voir donc avec ce dont je vais vous parler.

Pour étudier ces codes, il faut un programme de test  qui  est  normalement sur une des deux faces du disk... Quand vous l'exécutez  il  vous  demande  tout d'abord les valeurs à mettre dans les registres avant l'instruction  à  étudier, puis il vous demande le code hexa à étudier (16 octets maxi); cela peut etre  un appel à une routine, si c'est une routine système il faudra prendre les  valeurs système des registres alternatifs, sinon cette option n'est pas indispensable... Voilà pour le prog. de test.

Mais j'en vois qui perdent leur patience et c'est tout à fait normal...donc les codes spéciaux se divisent en fait en 2 catégories:
- les nouveaux codes qui correspondent en fait à des instructions  existant déjà (plus de 230).
- les nouveaux codes qui ont  une  fonction  qui  ne  correspond  à  aucune instruction déjà existante (plus de 340).

C'est bien sur la deuxième catégorie qui est  la  plus  intéressante,  mais nous allons aussi voir la première. Mais plutot que de traiter ces deux  parties indépendamment l'une de l'autre, je préfère séparer les différents thèmes: codes en &CB, codes en &ED, index 8 bits, et enfin index en &CB avec post-transfert... allez c'est parti !!!

CODES EN &CB: Si vous  avez  une  table  des  codes  Z80,  vous  aurez  remarqué qu'il y a une ligne vacante "en-dessous" de SLA, c'est-à-dire de CB 30 à CB 37. En effet ces codes correspondent en  fait  à  une  instruction nommée SLI. Elle fait la meme chose que SLA à une différence  près:  au  lieu de décaler un 0 dans le bit de poids faible, elle y décale un 1...
Vous voyez que ce n'est pas si compliqué... Allez, je vous refile quand meme une petite table au cas où :

CB 30   CB 31   CB 32   CB 33   CB 34   CB 35    CB 36     CB 37
SLI B   SLI C   SLI D   SLI E   SLI H   SLI L   SLI (HL)   SLI A
 DD CB 36 dis      FD CB 36 dis       et n'oubliez pas que 'dis'
 SLI (IX+dis)      SLI (IY+dis)       est un nombre signé...

CODES EN &ED: Rien de compliqué à comprendre ici non plus...  Par  contre  c'est beaucoup plus bordélique (et je reste poli...) ! C'est pourquoi je vais dès maintenant vous refiler une table  et  les  explications  viendront après :

     0       1       2       3       4       5       6       7
4  IN B,    OUT     SBC      LD     NEG     RETN   IM 0   LD I,A
    (C)    (C),B   HL,BC  (ADR),BC
5  IN D,    OUT     SBC      LD     *NEG   *RETN   IM 1   LD A,I
    (C)    (C),D   HL,DE  (ADR),DE
6  IN H,    OUT     SBC      LD     *NEG   *RETN  *RESET    RRD
    (C)    (C),H   HL,HL  (ADR),HL
7  *NOP    *NOP     SBC      LD     *NEG   *RETN   *NOP    *NOP
                    HL,SP  (ADR),SP

8       9       A       B       C       D       E       F

4  IN C,    OUT     ADC      LD     *NEG   RETI   *RESET  LD R,A
    (C)    (C),C   HL,BC  BC,(ADR)
5  IN E,    OUT     ADC      LD     *NEG   *RETI   IM 2   LD A,R
    (C)    (C),E   HL,DE  DE,(ADR)
6  IN L,    OUT     ADC      LD     *NEG  *RESET  *RESET    RLD
    (C)    (C),L   HL,HL  HL,(ADR)
7  IN A,    OUT     ADC      LD     *NEG  *RESET  *RESET   *NOP
    (C)    (C),A   HL,SP  SP,(ADR)


Vous aurez remarqué qu'en abscisse est porté le quartet faible  et en ordonnée le quartet fort de l'instruction...ainsi l'instruction  ADC HL,SP a pour code ED 7A... Les instructions précédées  d'un  astérisque  sont les nouveaux codes. Ils correspondent tous à des instructions déjà existantes, sauf une que l'on va donc approfondir: l'instruction RESET.
Comme son nom l'indique elle effectue un reset  du  Z80.  Mais  me direz-vous cela correspond alors à RST  0  ?  Non  car  cette  dernière effectue simplement un saut à l'adresse &0000 comme un CALL  0.  Tandis  que RESET fait une  sorte  de  reset  hard  de  notre  bon  vieux  Z80,  c'est-à-dire que le PC passe à 0, que les interruptions sont  inhibées, que le mode d'interruption IM  0  est  activé  et  que  l'exécution  du  programme  reprend  en  &0000...  Par  contre  le  contenu  des  autres  registres est conservé...

Pour mettre tout ceci en évidence voici une petite routine :

       ORG &A500
DEBUT  LD  A,&C3
       LD  (0),A
       LD  HL,INIT
       LD  (1),HL
       DB  &ED,&66 ;=RESET
INIT   IM  1
       JP  &A0A3


Assemblez  cette  mini-routine et lancez le prog. de test. Sélectionnez les valeurs que vous voulez pour les registres puis entrez comme code  C3 00 A5  (=JP  &A500).  Vous  voyez  que  tout  fonctionne normalement. Maintenant remplacez tour à tour dans la routine IM 1  par un NOP, et DB &ED,&66 par un RST 0... Vous notez les résultats suivants:

              RESET (=DB &ED,&66)          RST 0
IM 1             marche                marche
NOP             plante !!              marche...


Ce tableau parle de lui-meme !! A noter quand meme qu'ED 66  et ED 4E sont des valeurs garanties pour l'instruction RESET,  les  autres moins... C'est-à-dire que je n'ai pas fini mes études sur ces codes  en &ED et donc la table des codes que je vous ai fournie n'est pas sure  à 100 %.

INDEX 8 BITS: C'est la partie la plus connue de ces codes spéciaux... Il  s'agit de codes permettant aux registres IX et IY, de pouvoir  etre  manipulés par 8 bits...c'est-à-dire d'adresser indépendamment l'octet  faible  et l'octet fort...Pour cela, je ne vais pas vous  mettre  de  tables  mais plutot essayer d'éclaircir la logique de décodage des codes par le Z80. En effet, lorsque le Z80  rencontre  une  instruction  portant  au départ sur HL, et que celle-ci est précédée de DD ou FD, il remplace HL par IX ou IY; idem pour  (HL)  qui  devient respectivement  (IX+d)  ou (IY+d), tout ceci à l'exception des codes en &ED et de EX  DE,HL,  mais vous devriez normalement déjà le savoir...

Maintenant, si l'instruction en question ne porte ni  sur  HL,  ni sur (HL), le Z80 fait de meme avec H et L...ce qui permet de  manipuler les 2 octets des regs. d'index indépendamment l'un de l'autre. En effet si l'instruction porte sur H ou L, c'est-à-dire  en  fait  sur  l'octet high ou low du reg. double HL, il le remplace par l'octet correspondant du reg. d'index sélectionné. Par exemple:

 le code 4C correspond à   LD C,H ... donc le code FD 4C fait  de  meme,  mais  en  remplaçant  H  par l'octet High de IY.

Les conventions d'écriture sont :

IYH=octet High du reg. IY
IYL =   "   Low  "   "   "
IXH = octet High du reg. IX
IXL =   "   Low  "   "   "
Les instructions obtenues modifient les flags de la meme façon que leurs homologues...Attention cependant car  l'adressage  index  8  bits n'existe qu'avec les instructions qui ont un code d'instruction sur  un octet; en clair celles qui ne commencent ni par &ED, ni par  &CB.  Cela donne donc la liste de mnémoniques suivante:
LD reg,valeur ; INC reg. ; DEC reg. ; LD reg.objet,reg.source
ADD A,reg. ; ADC A,reg. ; SUB reg. ; SBC A,reg.
AND reg. ; XOR reg. ; OR reg. ; CP reg.

Attention également car il n'y aura jamais de  trucs  du  type  LD (IX+d),IXH ou encore moins  LD  (HL),IYL.  En  effet  ces  instructions portent tout d'abord sur le reg. double (HL)  et  le  Z80  se  contente d'appliquer la règle normale des index 16 bits.

Maintenant que  nous  avons  vu  les  instructions  qui  acceptent l'adressage index 8 bits, que deviennent les autres codes précédés d'un code d'index DD ou FD ?? Et bien ils se divisent en 3 groupes:

  • soit c'est une instruction qui a  un  code  d'opération  sur  un octet et qui ne porte ni sur HL, ni sur H, ni sur L. Dans ce cas elle a la meme fonction que si on ne l'avait pas  précédée  d'un code d'index.
  • soit c'est une instruction commençant par &ED et c'est  la  meme chose que ci-dessus. C'est pourquoi il n'y a pas de SBC IX,DE ou encore de OUT (C),IYH.
  • soit c'est une instruction commençant par &CB et  qui  ne  porte pas sur (HL),  et  c'est  justement  ce  que  nous  allons  voir maintenant...

INDEX EN &CB AVEC POST-TRANSFERT INDEXE: et c'est là que ça commence  à  devenir compliqué... Rien que le nom déjà a un je-ne-sais-quoi  d'effrayant  !! Allez je le répète  pour  vous  achever  complètement:  codes  spéciaux d'index en &CB avec  post-transfert  indexé...  Remarquez  que  ce  nom horrible, c'est moi qui l'ai inventé, alors...
Et puis tiens pour commencer on va le décortiquer un peu  ce  nom, pour savoir à quoi on a affaire...voyons voyons...  Déjà  on  voit  les mots  'index  en  &CB'  et  'transfert  indexé'.  Ce  sont   donc   des instructions de la forme: FD/DD   CB   dis   cod  .  Où  'dis'  est  la distance de l'adressage indexé (8 bits signés...)  et  'cod'  le   code d'opération. Oui bon d'accord mais pour l'instant ça nous avance pas  à grand-chose.

Pour comprendre parfaitement ce dont il s'agit, il faut encore une fois expliquer le décodage par le Z80... Quand le Z80 rencontre un code en &CB précédé d'un code d'index: codXY_CB_dis_code , il effectue l'instruction correspondante  en  adressage  indexé,  c'est-à-dire  sur (XY+dis). Mais ensuite, comme  l'indique  l'expression  "post-transfert indexé",  il  charge  le  résultat  de  l'opération  dans  le  registre normalement concerné s'il n'y avait pas eu de code d'index...

Par exemple le code FD CB 08 13 correspond à RL (IY+8) suivi de LD E,(IY+8). En effet CB 13 est le code de RL E et FD 08 fait pointer  sur l'adresse (IY+8).  Cette  instruction  sera  notée  par  convention  RL (IY+8)/E. Cette notation fait à mon avis  bien  apparaitre  l'adressage indexé et la notion de post-transfert, c'est pourquoi je l'ai choisie.

A  noter  que  l'instruction  SLI  vue  plus  haut  permet   aussi l'adressage indexé avec post-transfert. Par contre,  l'instruction  BIT n'effectue JAMAIS de post-transfert, les codes spéciaux  correspondront en fait à un adressage indexé normal, du type BIT (IX+d) ou BIT (IY+d).

Et vi c'est enfin fini !! Hein ? Quoi ??!?  Vous  voulez  savoir  de  quelle couleur sont les rasters de la Zebig Megademo ?? Incroyable...Y'en a qui suivent l'article  depuis  le  début  et  qui  n'ont  pas  encore  compris  de  quoi  ça parlait...vraiment lamentable !! Bon pour quand meme finir sur quelque chose  de sérieux, je dirai que le débat sur les instructions spéciales n'est pas clos, et qu'il tout à fait possible de le reprendre une prochaine fois, notamment si vous n'avez pas tout compris, et si vous me le dites, paske je  peux  pas  savoir  si vous me le signalez pas, je m'appelle pas 36 15 Madame Irma...

Sinon, vous devriez normalement avoir droit, le mois prochain,  à  un  petit cours assembleur sur les instructions dont on parle  moins:  DAA,  RLD  et  RRD, etc... D'ailleurs vous pouvez parfaitement allonger  cette  liste,  vous  n'avez qu'à m'écrire... Ah bien sur, ce ne sera pas aussi long que ce mois-ci, mais  là c'était parce que j'avais pris du retard... Allez mijotez-bien  sur  toutes  ces nouvelles instructions et n'oubliez pas de vous aider du prog. de  test  que  je vous  ai  mis  sur  le  disk...ça  vous  aidera  à  comprendre   comment  elles fonctionnent...

Lire le correctif de MM&PF numéro°7

Antoine / POW pour MM&PF

★ ANNÉE: ???
★ AUTEUR: ANTOINE

CPCrulez[Content Management System] v8.75-desktop/c
Page créée en 087 millisecondes et consultée 1353 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.