COURS D'ASSEMBLEUR 68000 SUR ATARI ST
(7)

Nous abordons maintenant le septième cours de la série. La totalité du cours étant en 2 séries (enfin à l'heure où je tape ces lignes c'est ce qui est prévu !), celui-ci est le dernier de la première!
A la fin de celui-ci et si vous avez très attentivement et très scrupuleusement suivi les 6 cours précédents, vous devriez être capable d'afficher des images, sauver des fichiers etc...

Mais tout d'abord revenons à notre pile et à la question du cours précédent. Avez vous trouvé l'erreur ?
Eh bien regardez la valeur de `A7` avant d'y empiler `$12345678` et `$23456`, et comparez à la valeur à la sortie du programme. Malheur ! ce n'est pas la même ! Normal, si nous comptons les empilages et les dépilages, nous nous rendons compte que nous avons empilé 8 octets de plus que nous n'avons dépilé. En effet, comme nous avons récupéré nos 2 nombres en sauvegardant au préalable `A7` dans `A0`, nous n'avons pas touché `A7` au moment de la récupération. Heureusement d'ailleurs car le retour de la routine aurait été modifié !
Partant du principe de dépilage dans l'ordre inverse, il nous faut donc corriger la pile une fois revenu de la subroutine. Comme nous avons empilé en faisant `-(SP)` il faut ajouter pour que la pile redevienne comme avant. Ayant empilé 2 nombres de 4 octets chacuns, nous devons ajouter 8 octets à l'adresse de la pile pour la corriger comme il faut. Nous avons déjà vu comment augmenter une adresse, avec `ADDA`.

Il convient donc de rajouter juste après la ligne `BSR AJOUTE` une addition sur `SP`, en faisant `ADDA.L #8,SP` (qui se lit ADD ADRESS LONG 8 STACK POINTER)

Un appel à une subroutine en lui passant des paramètres sur la pile sera donc typiquement du genre :

      MOVE.W #$1452,-(SP)
      MOVE.L #$54854,-(SP)
      MOVE.L #TRUC,-(SP)
      BSR BIDOUILLE
      ADDA.L #10,SP

Nous passons le word de valeur `$1452` dans la pile (modifiée donc de 2 octets), le long mot de valeur `$54854` dans la pile (modifiée de 4 octets), l'adresse repérée par le label TRUC dans la pile (modifiée de 4 octets) puis nous partons vers notre subroutine. Au retour correction de 2+4+4=10 octets du stack pointer pour revenir à l'état d'origine.

La pile possède une petite particularité. Nous avons vu dans les cours précédents que le 68000 était un micro-processeur 16/32 bits. Il lui est très difficile d'accéder à des adresses impaires. Or si nous commençons à empiler des octets et non plus uniquement des words ou des long words, le Stack Pointer peut très facilement pointer sur une adresse impaire, ce qui risque de planter notre machine.
Taper le programme suivante :

      MOVE.L #$12345678,D0
      MOVE.L D0,-(SP)
      MOVE.B D0,-(SP)
      MOVE.L #$AAAAAAAA,D1

Assemblez puis passez sous MonST et avancez pas à pas en observant bien l'adresse du SP (donc celle visible en `A7`).
Nous constatons que le pointeur de pile se modifie bien de 4 lorsque nous faisons `MOVE.L D0,-(SP)` mais qu'il se modifie de 2 lorsque nous faisons `MOVE.B D0,-(SP)` alors que nous pouvions nous attendre à une modification de 1 ! Les erreurs provoqués par des adresses impaires sont donc écartées avec la pile. Merci Monsieur MOTOROLA !
Note : ceci est une particularité des registres `A7` et `A7'`. Si nous avions travaillé avec `A3` par exemple au lieu de `SP`, celui-ci aurait eu une adresse impaire. C'est le type d'usage qui est fait de la pile qui a conduit les gens de MOTOROLA à créer cette différence.

Abordons maintenant l'ultime chapitre de cette première série :

LES 'TRAP'

Une instruction TRAP est comparable à une instruction `BSR`. Elle agit comme un branchement vers une routine. Cependant, contrairement à l'instruction `BSR` qui demande à être complétée par l'adresse, c'est-à-dire le label permettant de trouver la routine, l'instruction `TRAP` se contente d'un numéro. Ce numéro peut varier de 0 à 15. Lorsque le 68000 rencontre une instruction `TRAP` il regarde son numéro et agit en conséquence. Vous vous rappeler des tout premiers cours, dans lesquels nous avions parlé du principe utilisé par le 68000 lorsqu'il trouvait la bit `T` (mode trace) du `SR` (status register) à 1 ? Saut dans le premier kilo de mémoire (table des vecteurs d'exceptions), recherche de l'adresse `$24`, on regarde dans le tube à cette adresse, on y trouve un long mot, ce long mot c'est l'adresse de la routine et on fonce à cette adresse exécuter cette routine.

Et bien regardez la feuille qui donne la liste des vecteurs d'exceptions, et jetez un coup d'oeil aux vecteurs 32 à 47. Les voilà nos vecteurs `TRAP` !!! Lorsque le 68000 rencontre par exemple l'instruction `TRAP #8`, il fonce à l'adresse `$0A0` pour y trouver l'adresse de la routine qu'il doit exécuter.

A priori cela semble bien compliqué pour pas grand chose ! En effet il faut prévoir sa routine, la mettre en mémoire, puis placer son adresse dans le vecteur. Plus compliqué qu'un `BSR`, surtout que `BSR` REGLAGE_CLAVIER et plus parlant qu'un `TRAP #5` ou un `TRAP #12` !!!

Là, nous retournons encore en arrière (je vous avais bien dit que TOUT était important dans ces cours !!!!!) pour nous souvenir de la notion de mode Utilisateur et de mode Superviseur. Le Superviseur accède à toute la mémoire et à toutes les instructions, pas l'Utilisateur.

S'il s'agit d'interdire à l'Utilisateur des instructions assembleur telles que RESET, notre Utilisateur ne sera pas trop gêné par contre c'est en ce qui concerne la mémoire que tout va très sérieusement se compliquer. Voulez vous connaître la résolution dans laquelle se trouve votre machine ? C'est facile, c'est noté à l'adresse `$FF8260`.

Vous voulez changer la palette de couleur ? Rien de plus simple, elle est notée en `$FF8240`. Imprimer un petit texte ? A l'aise, il suffit d'employer les registres de communications vers l'extérieur du chip son (étonnant n'est ce pas !). C'est situé en `$FF8800` et `$FF8802`.

Pardon ??? Quoi ??? Vous êtes Utilisateur ??? Ah bon.... Parce que c'est gênant... Toutes ces adresses sont situées dans la zone mémoire uniquement accessible au Superviseur.....

L'Utilisateur se trouve bien coincé et les possibilités s'en trou- vent drôlement réduites. Heureusement, les `TRAP` sont là !!! Grâce à ce système l'utilisateur va avoir accès à des zones qui lui sont normalement interdites. Pas directement, bien sûr, mais grâce au superviseur. Le superviseur a, en effet, fabriqué des routines qu'il a placé en mémoire et dont les adresses sont dans les vecteurs `TRAP`. Ces routines sont exécutés en mode superviseur et tapent à tour de bras dans les zones mémoires protégées. Lorsque l'Utilisateur veut les utiliser il les appelle par les `TRAP`. La protection est donc bien assurée car l'Utilisateur ne fait que déclencher une routine dont généralement il ne connaît que les paramètres à lui passer et le type de message qu'il aura en réponse. C'est de cette manière que nous pouvons accéder au système d'exploitation de notre Atari !!!

Petit rappel : qu'est ce qu'un système d'exploitation ?

Le premier qui répond c'est GEM se prend une paire de claques. GEM c'est l'interface utilisateur et pas le système d'exploitation.

Le système d'exploitation (ou Operating System) dans notre cas c'est TOS. La confusion entre interface Utilisateur et système d'exploitation vient du fait que certains systèmes d'exploitation intègrent également un interface utilisateur : c'est par exemple le cas sur PC avec MS DOS. (Note de Rajah : Donc le premier qui dit que Zin00 est un OS se prend une paire de claques, vu que c'est l'équivalent du GEM (façon billou) au niveau des Papier-Culs)

Le système d'exploitation c'est un ensemble de routine permettant d'exploiter la machine. Ces multiples routines permettent par exemple d'afficher un caractère à l'écran d'ouvrir un fichier, de formater une piste de disquette, d'envoyer un octet sur la prise MIDI etc... En fait tous les 'trucs' de base, mais jamais de choses compliquées. Une routine du système d'exploitation ne permettra pas, par exemple, de lire le contenu d'un fichier se trouvant sur la disquette. En effet ceci demande plusieurs opérations avec à chaque fois des tests :

- Ouverture du fichier : existe t-il,
- la disquette n'est elle pas abîmée etc...
- positionnement du pointeur dans le fichier : le positionnement s'est il bien passé ?
- lecture : N'as t-on pas essayé de lire trop d'octets etc, etc....

Il faudra donc bien souvent plusieurs appels à des routines différentes pour réaliser ce que l'on veut.

Il est toujours possible de se passer du système d'exploitation, spécialement lorsque l'on programme en assembleur. En effet l'ensemble des routines de l'OS (abréviation de Operating System) est destiné à un usage commun, tout comme d'ailleurs les routines de l'interface Utilisateur.

Ceci explique bien souvent la ré-écriture de toutes petites parties du système afin de n'utiliser que le strict nécessaire. La routine de gestion souris du GEM par exemple doit s'occuper de la souris mais aussi du clavier, du MIDI et du joystick. Pour un jeu il peut être intéressant de ré-écrire cette routine afin de gérer uniquement le joystick et donc d'avoir une routine qui 'colle' plus au besoin.

Nous verrons beaucoup plus tard comment regarder dans le système d'exploitation afin de pouvoir par la suite réaliser soi-même ses routines. Avant cela, utilisons simplement ce système !

Nous allons donc l'appeler grâce aux `TRAP`s. 4 traps sont accessibles 'normalement' dans le ST :

- `TRAP #1` : routines du GEMDOS
- `TRAP #2` : routines du GEM
- `TRAP #13` : routines du BIOS
- `TRAP #14` : routines du BIOS étendu (eXtended Bios donc XBIOS)

GEMDOS = Graphic environment manager disk operating system
GEM = ;Graphic environment manager (se découpe par la suite en AES, VDI etc.. Un chapitre de la seconde série y sera consacrée)
BIOS = Basic Input Output System
XBIOS = Extended Basic Input Output System

Les autres vecteurs `TRAP` (0, 3 à 12 et 15) sont, bien entendu, actifs mais aucune routine n'y est affectée. Nous pouvons les utiliser pour peu que nous y mettions avant nos routines, ce qui sera l'objet du premier cours de la seconde série.

Nous constatons que le `TRAP #1` permet d'appeler le GEMDOS. Or il n'y a pas qu'une routine GEMDOS mais une bonne quantité. De plus ces routines demandent parfois des paramètres. Comment faire pour les transmettre ? Et bien tout simplement par la pile !!!

Taper le programme suivant :

      MOVE.W #65,-(SP)
      MOVE.W #2,-(SP)
      TRAP #1
      ADDQ.L #4,SP

      MOVE.W #7,-(SP)
      TRAP #1
      ADDQ.L #2,SP
      MOVE.W #0,-(SP)
      TRAP #1
      ADDQ.L #2,SP

Assemblez ce programme mais ne le débuggez pas, lancez le par Alternate+X. Vous voyez apparaître un A sur l'écran de votre ST. Appuyer sur une touche et hop vous revenez dans GENST ! Analysons ce que nous avons fait car là de très très nombreuses choses se sont passées, et avouons le, nous n'avons rien vu !!!!!

Tout d'abord nous avons appelé la fonction Cconout() du Gemdos. Nous avons appelé le Gemdos avec le TRAP #1, mais cette instruction nous a envoyé vers un ensemble de routine, toutes appartenant au Gemdos. Pour indiquer à cette routine principale vers quelle subroutine du Gemdos nous désirons aller, nous avons passé le numéro de cette subroutine dans la pile. Partant toujours du principe du dernier entré premier sorti, il est bien évident que ce numéro doit se trouver empilé en dernier afin de pouvoir être dépilé en premier par la routine principale de Gemdos, afin qu'elle puisse s'orienter vers la sous-routine qui nous intéresse. La fonction Cconout ayant le numéro 2, nous avons donc fait `MOVE.W #2,-(SP)` .(voir plus haut pour se rappeler que 2 peut très bien être codé sur un octet mais, comme nous travaillons vers la pile, il sera pris comme un word de toutes façons).

Maintenant le Gemdos ayant trouvé 2 comme paramètre, s'oriente vers cette routine au nom barbare, qui a pour fonction d'afficher un caractère sur l'écran. Une fois rendu vers cette routine, le Gemdos va chercher à savoir quel caractère afficher. C'est pour cela que nous avons placé le code ASCII de ce caractère sur la pile avec `MOVE.W #65,-(SP)`.

Note : Pour l'assembleur, le code ASCII peut être remplacé par la lettre elle-même. Nous aurions donc pu écrire `MOVE.W #"A",-(SP)` sans oublier toutefois les guillemets !

De retour du `TRAP` nous devons corriger la pile, afin d'éviter le problème qui a fait l'objet du début de ce cours. Nous avions empilé un word donc 2 octets et ensuite un autre word soit au total 4 octets. Nous allons donc ajouter 4 au `SP`. Nous profitons ici d'une opération d'addition plus rapide que `ADDA`, `ADDQ` qui se lit add quick. Cette addition est autorisée jusqu'à 8 inclus. Il n'est pas possible par exemple de faire `ADDQ.L #12,D1`.

Ensuite nous recommençons le même genre de chose, avec la fonction 7 du GEMDOS (nommée Crawcin)qui elle n'attend aucun paramètre, c'est pourquoi nous passons juste son numéro sur la pile. Cette fonction attend un appui sur une touche. Ayant passé un paramètre sur un word, nous corrigeons au retour du `TRAP` la pile de 2.

Le programme se termine avec la fonction 0 du GEMDOS (Pterm(0)) qui libère la mémoire occupée par notre programme et le termine pour de bon. Cette routine n'attend pas de paramètre, nous ne passons dans la pile que son numéro donc correction de 2. Note : la correction de pile pour la fonction Ptermo n'est là que par souci pédagogique. Cette fonction terminant le programme, notre dernière instruction `ADDQ.L #2,SP` ne sera jamais atteinte !

Plusieurs choses maintenant. D'abord ne soyez pas étonnés des noms bizarres des fonctions du GEMDOS, du Bios ou du Xbios. Ce sont les véritables noms de ces fonctions. En assembleur nous ne les utiliserons pas directement puisque l'appel se fait pas un numéro, mais en C par exemple c'est ainsi que sont appelées ces fonctions. Dans les cours d'assembleur de ST MAG (dont les vertus pédagogiques sont plus que douteuses), nous pouvons lire que les noms de ces fonctions ont été choisis au hasard et que la fonction Malloc() par exemple aurait pu s'appeler Mstroumph(). C'est ridicule ! Chacun des noms est, comme toujours en informatique, l'abréviation d'un expression anglo-saxonne qui indique concrètement le but ou la fonction. Ainsi Malloc signifie Memory Allocation, cette fonction du GEMDOS permet donc de réserver une partie de mémoire !!! Malheureusement de nombreux ouvrages passe sur ce 'détail' et ne fournissent que l'abréviation.

Ceci n'empêche qu'il vous faut impérativement une liste de toutes les fonctions du GEMDOS, du BIOS et du XBIOS. Ces fonctions sont décrites dans le Livre du Développeur, dans la Bible mais également dans les dernières pages de la doc du GFA 3.

Note : dans la doc du GFA, il manque la fonction GEMDOS 32 qui permet de passer en Superviseur. Ce mode n'étant pour le moment que d'un intérêt limité pour vous, pas de panique, nous décrirons tout cela dans la seconde série.

Continuons pour le moment avec des petits exemples. Affichons une phrase sur l'écran à la place d'un lettre. Ceci va se faire avec la programme suivant :

    MOVE.L #MESSAGE,-(SP) adresse du texte
    MOVE.W #9,-(SP) numéro de la fonction
    TRAP #1 appel gemdos
    ADDQ.L #6,SP correction pile

    * attente d'un appui sur une touche

    MOVE.W #7,-(SP) numéro de la fonction
    TRAP #1 appel GEMDOS
    ADDQ.L #2,SP correction pile

    * fin du programme

    MOVE.W #0,-(SP)
    TRAP #1

    SECTION DATA

    MESSAGE DC.B "SALUT",0

Une nouveauté, le passage d'une adresse. En effet la fonction 9 du gemdos demande comme paramètre l'adresse de la chaîne de caractère à afficher. Nous avons donc donné `MESSAGE`, qui est le label, l'étiquette servant à repérer l'emplacement dans le tube où se trouve notre phrase, tout comme nous avions mis une étiquette `AJOUTE` pour repérer notre subroutine, dans le cours précédent.

Ce message est une suite de lettres, toutes codées sur un octets. Pour cette raison nous disons que cette chaîne est une constante constituée d'octet. Nous définissons donc une constante en octets: Define Constant Byte, en abrégé DC.B Attention ceci n'est pas une instruction 68000 ! C'est simplement une notation pour l'assembleur afin de lui dire :
"N'essaye pas d'assembler ça comme du code normal, ce n'est qu'une constante". De même nous définissons une zone.
La fonction 9 du GEMDOS demande à ce que la phrase se termine par 0, ce qui explique sa présence à la fin.
Réalisons maintenant un programme suivant le schéma suivant :

- affichage d'un texte de présentation en inverse vidéo ;
- ce texte demande si on veut quitter ou voir un message
- si on choisit quitter, bye bye
- sinon on affiche 'coucou' et on redemande etc...

Détaillons un peu plus, en traduisant ce programme en pseudo-code. C'est ainsi que l'on nomme la façon de présenter un déroulement d'opération en langage clair mais dont l'organisation se rapproche déjà de la programmation.

AFFICHE "QUITTER (Q) OU VOIR LE MESSAGE (V) ?"
SI REPONSE=Q
VA A QUITTER
SI REPONSE=V
AFFICHE "COUCOU"
RETOURNE A AFFICHE "QUITTER...."
SI REPONSE DIFFERENTE RETOURNE A AFFICHE "QUITTER..."

Par commodité, ce listing se trouve sur une feuille séparée (listing numéro 1 / Cours numéro 7).

Tout d'abord affichage de la phrase qui servira de menu, avec la fonction Gemdos 9. Cette phrase se trouve à l'étiquette MENU, allons la voir pour la détailler. Nous remarquons tout d'abord qu'elle commence par 27. Après avoir regardé dans une table de code ASCII, nous notons qu'il s'agit du code ASCII de la touche Escape. Nous cherchons donc d'abord à afficher Escape. Mais, comme vous le savez sûrement, ce caractère n'est pas imprimable !
Impossible de l'afficher à l'écran!

C'est tout à fait normal! en fait il n'est pas question ici d'afficher réellement un caractère, mais plutôt de faire appel à un ensemble de routines, répondant au nom de VT52. Pour appeler ces routines, il faut afficher Escape. Voyant cela le système se dit : "Tiens, on cherche à afficher Escape, c'est donc en fait que l'on cherche à appeler le VT52".

L'émulateur VT52 réagit donc, mais que doit-il faire ? et bien pour le savoir il va regarder la lettre qui suit Escape. En l'occurrence il s'agit ici de E majuscule. Regardez dans les feuilles annexes à cette série de cours, il y en a une consacrée au VT52. Nous voyons que Escape suivi de E efface l'écran, c'est donc ce qui va se passer ici.
Ensuite il était dit dans le 'cahier des charges' de notre programme, que le MENU devait être affiché en inverse vidéo.

Consultons donc la feuille sur le VT52. Nous y trouvons : Escape et 'p' minuscule = passe en écriture inverse vidéo. Juste ce qu'il nous faut! Nous remettons donc 27,"p" dans notre phrase.

Trois remarques :

- Tout d'abord il faut remettre à chaque fois Escape. Faire 27,"E","p" aurait effacé l'écran puis aurait affiché p.
- Seconde remarque, il faut bien faire la différence entre les let- tres majuscules et les lettres minuscules. Escape+E efface l'écran mais Escape+e active le curseur!!!
- Troisième remarque, on peut représenter dans le listing une lettre par son 'caractère' ou bien par son code ASCII.

  Ainsi si on veut afficher Salut, on peut écrire le listing comme ceci :

        TXT DC.B Salut",0

  ou bien comme cela :

        TXT DC.B 83,97,108,117,116,0

  Il est de même possible de mélanger les données en décimal, en binaire, en hexadécimal et les codes ASCII. Par exemple ceci :

        TXT DC.B 65,$42,%1000011,"D",0

  affichera ABCD si on utilise cette "phrase" avec Gemdos 9.

  Ceci vous sera bien utile lorsque vous chercherez à afficher des lettres difficiles à trouver sur le clavier. Pour le 'o' tréma, il est possible de faire :

        TXT DC.B "A bient",147,"t les amis.",0

  Note : J'espère que depuis le début, il n'y en a pas un seul à avoir lu DC.B "décébé" !!!! Je vous rappelle que cela se lit Define Constant Byte.

  Continuons l'exploration de notre programme. Notre phrase efface donc l'écran puis passe en inverse vidéo. Viens ensuite le texte lui-même :
  QUITTER (Q) OU VOIR LE MESSAGE (V) ?

  Ensuite une nouvelle commande VT52 pour repasser en vidéo normale, puis 2 codes ASCII qui, eux non plus, ne sont pas imprimables. Ce sont les codes de retour chariot. Le curseur va donc se retrouver tout à gauche de l'écran, une ligne plus bas. Enfin le 0 indiquant la fin de la phrase.

  Une fois le 'menu' affiché, nous attendons un appui sur une touche avec la fonction Gemdos numéro 7. Cette fonction renvoi dans D0 un résultat. Ce résultat est codé sur un long mot, comme ceci :

  Bits 0 à 7 code ASCII de la touche
  Bits 8 à 15 mis à zéro
  Bits 16 à 23 code clavier
  Bits 24 à 31 Indication des touches de commutation du clavier (shifts..)
  Dans notre cas nous ne nous intéresserons qu'au code ASCII de la touche enfoncée. Nous allons donc comparer le word de D0 avec chacun des codes ASCII que nous attendons, c'est à dire Q, q, V et v. Cette comparaison va se faire avec une nouvelle instruction : Compare (`CMP`). Comme nous comparons un word nous notons `CMP.W`, que nous lisons COMPARE WORD. Nous comparons Q avec `D0` (nous aurions pu marquer `CMP.W #81,D0` puisque 81 est le code ASCII de Q).

  Cette comparaison effectuée, il faut la tester. Nous abordons ici les possibilités de branchement dépendant d'une condition, c'est-à-dire les branchements conditionnels.

  Chacune de ces instructions commence par la lettre B, signifiant BRANCH. En clair, ces instructions peuvent être lues comme :

  Va à tel endroit si...

  Mais si quoi ???

  Eh bien plusieurs conditions sont disponibles, que l'on peut regrouper en 3 catégories :

  D'abord une catégorie qui réagit à l'état d'un des bits du Status Register :

  `BCC` Branch if carry clear (bit de retenue à 0)
  `BCS` Branch if carry set (bit de retenue à 1)
  `BNE` Branch if not equal (bit de zéro à 0)
  `BEQ` Branch if equal (bit de zéro à 1)
  `BVC` Branch if overflow clear (bit de dépassement à 0)
  `BVS` Branch if overflow set (bit de dépassement à 1)
  `BPL` Branch if plus (bit négatif à 0)
  `BMI` Branch if minus (bit négatif à 1)
  Une seconde catégorie, réagissant à la comparaison de nombres sans signe.
  `BHI` Branch if higher (branche si supérieur à)
  `BLS` Branch if lower or same (inférieur ou égal)
  (on peut aussi remettre `BEQ` et `BNE` dans cette catégorie)
  UNe troisième catégorie, réagissant à la comparaison de nombres avec signe.
  `BGT` Branch if greater than (si supérieur à)
  `BGE` Branch if greater or equal (si supérieur ou égal à)
  `BLT` Branch if lower than (si plus petit que)
  `BLE` Branch if lower or equal (si plus petit ou égal)
  (on peut encore remettre `BEQ` et `BNE` !!!)
  Je suis profondément désolé pour les gens de MICRO-APPLICATION (Le Langage Machine sur ST, la Bible, le Livre du GEM etc...) ainsi que pour le journaliste qui écrit les cours d'assembleur dans STMAG, mais les branchements `BHS` et `BLO`, malgré le fait qu'ils soient acceptés par de nombreux assembleurs, N'EXISTENT PAS !!!!!
  Il est donc impossible de les trouver dans un listing assemblé, l'assembleur les convertissant ou bien les rejetant.

  Cet ensemble de branchement conditionnel constitue un ensemble de commande du type Bcc (branch conditionnaly)

  Poursuivons notre lente progression dans le listing... La comparaison est effectuée, testons la :

        CMP.W #"Q",D0     est-ce la lettre 'Q' ?
        BEQ QUITTER       branch if equal 'quitter'

  C'est à dire, si c'est égal, sauter à l'étiquette QUITTER. Si ce n'est pas égal, le programme continue comme si de rien n'était, et tombe sur un nouveau test :

        CMP.W #"q",D0     est-ce q minuscule ?
        BEQ QUITTER       branch if equal quitter

  Nous comparons ensuite à 'V' majuscule et en cas d'égalité, nous sautons à `AFFICHAGE`. Viens ensuite le test avec 'v' minuscule. Là, c'est l'inverse: Si ce n'est pas égal, retour au début puisque toutes les possibilités ont été vues. Par contre, si c'est 'v' qui a été appuyé, le programme continuera sans remonter à `DEBUT`, et tombera de lui même sur `AFFICHAGE`.

  L'affichage se fait classiquement avec Gemdos 9. Cet affichage terminé, il faut remonter au début. Ici, pas besoin de test car il faut absolument remonter. Nous utilisons donc un ordre de branche- ment sans condition (inconditionnel) qui se lit BRANCH ALWAYS (branchement toujours)et qui s'écrit `BRA`.

  En cas de choix 'Q' ou 'q', il y a saut à `QUITTER` et donc à la fonction Gemdos 0 qui termine le programme.

  N'hésitez pas à modifier ce programme, à essayer d'autres tests, à jouer avec le VT52, avant de passer au suivant.

  ("Quelques heures passent..." In ('Le manoir de Mortevielle') acte 2 scène III)

  Prenons maintenant le listing numéro 3. Nous étudierons le numéro 2 en dernier à cause de sa longueur un peu supérieure.

  Le but de ce listing est de réaliser un affichage un peu comparable à celui des horaires dans les gares ou les aéroports : chaque lettre n'est pas affichée d'un coup mais 'cherchée' dans l'alphabet.
  D'abord effacement de l'écran en affichant Escape et 'E' avec Gemdos 9 : rien que du classique pour vous maintenant !

  Ensuite cela se complique. Nous plaçons l'adresse de `TXT_FINAL` dans `A6`. Regardons ce qu'il y a à cette étiquette `'TXT_FINAL'` : nous y trouvons la phrase à afficher.

  Observons maintenant TRES attentivement ce qui se trouve à l'adresse `TXT`. Nous y voyons 27,"Y",42 . En regardant notre feuille du VT52 nous voyons que cela correspond à une fonction plaçant le curseur à un endroit précis de l'écran. Nous constatons aussi 2 choses :

  1. La commande est incomplète
  2. Une phrase affichée par exemple avec gemdos 9, doit se terminer par 0, ce qui ici n'est pas le cas !
  En effet, la phrase est incomplète si on se contente de lire cette ligne. Jetons un coup d'oeil sur la ligne suivante. Nous y trouvons 42, qui est peut être la suite de la commande (nous avons donc escape+Y+42+42), et une ligne encore plus bas nous trouvons deux zéros. Nous pouvons remarquer également que si la phrase commence à l'étiquette `TXT`, la seconde ligne possède également une étiquette (`'COLONNE'`) ainsi que la troisième ligne (`'LETTRE'`).

  Imaginons maintenant que nous ayons une lettre à la place du premier zéro en face de l'étiquette LETTRE. Si nous affichons cette phrase nous verrons s'afficher cette lettre sur la 10ème colonne de la 10ème ligne (révisez la commande Escape+Y sur la feuille du VT52).

  Imaginons ensuite que nous ajoutions 1 au chiffre se trouvant à l'étiquette `COLONNE` et que nous recommencions l'affichage. Nous verrions notre lettre toujours 10ème ligne, mais maintenant 11ème colonne !
  C'est ce que nous allons faire, en compliquant d'avantage. Plaçons le code ASCII 255 (c'est le code maximale autorisé puisque les co- des ASCII sont codés sur un byte) à la place du premier zéro de l'étiquette LETTRE. Nous faisons cela par `MOVE.B #255,LETTRE`. Ajoutons 1 ensuite au chiffre des colonnes avec `ADD.B #1,COLONNE` ensuite posons nous la question suivante : la lettre que je vais afficher (actuellement de code ASCII 255), est-ce la même que celle de la phrase finale ? Pour le savoir il faut prélever cette lettre de cette phrase. Comme nous avons placé l'adresse de cette phrase dans A6, nous prélevons tout en faisant avancer A6 pour pointer sur la seconde lettre : `MOVE.B (A6)+,D6`.

  Et si la lettre que nous venons de prélever était le code ASCII 0 ? Cela voudrais donc dire que nous sommes à la fin de la phrase et donc qu'il faut s'en aller !!! Nous comparons donc D6 qui contient le code ASCII de la lettre, avec 0.

      CMP.B #0,D6
      BEQ FIN        si c'est égal, bye bye!

  Ouf ! Ce n'est pas la dernière lettre ; nous pouvons donc afficher notre phrase. Cela se fait avec Gemdos 9, en lui passant l'adresse du début de la phrase dans la pile. Cette adresse c'est `TXT` et le Gemdos affichera jusqu'à ce qu'il rencontre 0. Il affichera donc 27,"Y",42,43,255,0. Ceci étant fait, comparons la lettre que nous venons d'afficher, et qui se trouve en face de l'étiquette LETTRE avec celle qui se trouve dans `D6` et qui a été prélevée dans la phrase modèle.

  Si c'est la même, nous remontons jusqu'à l'étiquette PROCHAINE, nous changeons de colonne, nous prélevons la lettre suivante dans la phrase modèle et nous recommençons. Mais si ce n'est pas la même lettre ?

  Et bien nous diminuons de 1 le code ASCII de 'LETTRE' (`SUB.B #1,LETTRE`) et nous ré-affichons notre phrase qui est maintenant 27,"Y",42,43,254,0 .
  C'est compris ?
  La aussi c'est une bonne étude qui vous permettra de vous en sortir.

  N'abandonner pas ce listing en disant "oh ça va j'ai à peu près compris".
  il faut PARFAITEMENT COMPRENDRE. N'hésitez pas à vous servir de MONST pour aller voir à l'adresse de LETTRE ce qui s'y passe. Pour avoir les adresses des étiquettes, taper L quand vous êtes sous MONST. Il est tout à fait possible de demander à ce que la fenêtre mémoire (la 3) pointe sur une partie vous montrant LETTRE et COLONE, puis de revenir sur la fenêtre 2 pour faire avancer pas à pas le programme. Ceci vous permettra de voir le contenu de la mémoire se modifier tout en regardant les instructions s'exécuter.

  Il reste un petit point à éclaircir, concernant le mot `EVEN` qui est situé dans la section data. Nous avons déjà compris (du moins j'espère) que l'assembleur ne faisait que traduire en chiffres des instructions, afin que ces ordres soient compris par la machine. Nous avons vu également que le 68000 n'aimait pas les adresses impaires (du moins nous ne l'avons pas encore vu, et ce n'est pas plus mal...). Lorsque l'assembleur traduit en chiffre les mnémoniques, il n'y a pas de souci à se faire, celles-ci sont toujours traduites en un nombre pair d'octets.

  Malheureusement ce n'est pas forcément le cas avec les datas. En l'occurrence ici, le label `CLS` commence à une adresse paire (car avant lui il n'y a que des mnémoniques) mais à l'adresse `CLS` on ne trouve que 3 octets. Nous en déduisons que le label `TXT` va se trouver à une adresse impaire. Pour éviter cela, l'assembleur met à notre disposition une instruction qui permet d'imposer une adresse paire pour le label suivant, EVEN signifiant pair en Anglais.

  Note : Tout comme `SECTION DATA`, `DC.B`, `DC.W` ou `DC.L`, `EVEN` n'est pas une instruction du 68000. C'est un ordre qui sera compris par l'assembleur.

  Généralement ces ordres sont compris par beaucoup d'assembleurs mais il existe parfois des variantes. Ainsi certains assembleurs demandent à avoir `.DATA` ou bien `DATA` et non pas `SECTION DATA`. De même pour certains assembleurs, les labels (étiquettes) doivent être impérativement suivis de 2 points. Il faut chercher dans la doc de son assembleur et faire avec, c'est la seule solution ! Notez cependant que ceci ne change en rien les mnémoniques !

  Passons maintenant au dernier listing de ce cours, le numéro 2.

  Ce listing affiche une image Degas dont le nom est inscrit en section data, à l'étiquette `NOM_FICHIER`. Il est bien évident que ce nom ne doit pas contenir de c cédille mais plutôt une barre oblique inversée, que mon imprimante a refusée d'imprimer !

  Seules 2 ou 3 petites choses vous sont inconnues. Tout d'abord l'instruction `TST.W` (juste après l'ouverture du fichier image) Cette instruction se lit Test et donc ici on lit : Test word D0.
  Cela revient tout simplement à faire `CMP.W #0,D0`.

  Seconde chose qui vous est encore inconnue, la `SECTION BSS`.

  Nous avons vu dans les précédents que les variables initialisées étaient mises dans une `SECTION DATA`. Et bien les variables non initialisées sont mises dans une section nommée `SECTION BSS`. Cette section possède une particularité intéressante : les données y figurant ne prennent pas de place sur disque !

  Ainsi si vous avez un programme de 3 kiloctets mais que dans ce programme vous désirez réserver 30 kilo pour pouvoir par la suite y charger différentes choses, si vous réservez en faisant `TRUC DC.B 30000` votre programme, une fois sur disquette fera 33000 octets. Par contre si vous réservez par `TRUC DS.B 30000`, votre programme n'occupera que 3 Ko sur le disque.

  Ces directives placées en section `BSS` sont assez différentes de celles placés en section data.

  - `TRUC DC.W 16` réserve de la place pour 1 word qui est initialisé avec la valeur 16.
  - `TRUC DS.W` 16 réserve de la place pour 16 words.
  Il faut bien faire attention à cela, car c'est une faute d'étourderie peu fréquente mais ça arrive ! Si on note en section `BSS` :

      TRUC DS.W 0
      MACHIN DS.W 3

  Lorsque l'on cherchera le label `TRUC` et que l'on écrira des données dedans, ces données ne pourront pas aller DANS truc puisque cette étiquette ne correspond à rien (0 word de réservé) et donc nous écrirons dans `MACHIN`, en écrasant par exemple ce que nous y avions placé auparavant.

  Bon, normalement vous devez en savoir assez long pour utiliser le Gemdos, le Bios et le Xbios (je vous rappelle que le Bios s'appelle par le Trap #13, exactement de la même manière que le Gemdos ou le Xbios).
  Vous devez donc être capable de réaliser les programmes suivants :

  - Demande du nom d'une image. On tape le nom au clavier, puis le programme lit l'image sur la disquette et l'affiche. Prévient et redemande un autre nom si l'image n'est pas trouvée. Si on tape X, c'est la fin et on quitte le programme.

  - Lecture du premier secteur de la première piste de la disquette. Si le premier octet de ce secteur est égale à `$61` (c'est le code de l'instruction `BRA`), faire cling cling cling en affichant le code ASCII 7 (clochette), afficher "disquette infectée", attendre un appui sur une touche et bye bye. Si disquette non infectée, afficher "je remercie le Féroce Lapin pour ses excellents cours d'assembleur, super bien faits à que d'abord c'est lui le meilleur" et quitter.

  - Vous pouvez aussi tenter la vaccination, en effaçant carrément le premier octet (mettre à 0 par exemple).

  Autre exemple assez intéressant à programmer. Vous avez vu dans le listing 3 comment prélever des données situées les unes après les autres dans une chaîne : `D6` contient bien d'abord F puis E puis R etc... Imaginez que vous ayez 3 chaînes : la première contient des chiffres correspondant à la colonne d'affichage, la seconde des chiffres correspondant à la ligne et la troisième des chiffres correspondant à la couleurs, ces 3 données au format VT52. (regardez Escape+'Y' et Escape+'b' ou Escape+'c'). On met un registre d'adresse pour chacune de ces listes, on lit un chiffre de chaque, on place ce chiffre dans une phrase :

  (27,"Y",X1,X2,27,"b",X3,"*",0)

  X1 étant le chiffre prélevé dans la liste 1
  X2 étant le chiffre prélevé dans la liste 2
  X3 étant le chiffre prélevé dans la liste 3
  p On affiche donc à différentes positions une étoile, de couleur différente suivant les affichages.

  Conseil : Essayez de faire le maximum de petits programmes, afin de bien comprendre l'utilisation du VT52, du Gemdos, du Bios et du Xbios. Cela vous permettra également de vous habituer à commenter vos programmes, à les ordonner, à chasser l'erreur sournoise.

  Scrutez attentivement vos programmes à l'aide de MONST. Pour le moment les erreurs seront encore très faciles à trouver, il est donc impératif de très très bien vous entraîner !!!

  Si un de vos programmes ne tourne pas, prenez votre temps et réfléchissez. C'est souvent une erreur ENORME qui est juste devant vous : notez sur papier les valeurs des registres, faites avancer pas à pas le programme sous MONST, repensez bien au principe de la pile avec ses avantages mais aussi ses inconvénients. Utilisez le principe des subroutines en y passant des paramètres afin de très bien maîtriser ce principe.

  La suite dans le prochain numero du STimulus. Cela vous laisse le temps de bosser. Surtout approfondissez, et résistez à la tentation de désassembler des programmes pour essayez d'y comprendre quelque chose, ou à la tentation de prendre de gros sources en croyant y trouver des choses fantastiques. Ce n'est pas du tout la bonne solution, au contraire !!!

  Si vraiment vous voulez faire tout de suite un gros trucs, alors faite un traitement de texte. Avec le VT52, le Gemdos et le Bios, c'est tout à fait possible. Bien sûr, il n'y aura pas la souris et il faudra taper le nom du fichier au lieu de cliquer dans le sélecteur, mais imaginez la tête de votre voisin qui frime avec son scrolling en comprenant 1 instruction sur 50 quand vous lui annoncerez "Le scrolling c'est pour les petits... moi je fais un traitement de texte !!"

Le Féroce Lapin