CODINGCLASSEURS WEKA ★ Comment exploiter toutes les ressources et augmenter les performances de votre AMSTRAD CPC ★

4/1.6.2 - L'instruction CALL et les RSX en BasicCoding Classeurs Weka
4/0 - Langages du CPC

4/1.6 - Basic approfondi

4/1.6.2 - L'instruction CALL et les RSX en Basic

Introduction

Nous allons, dans ce chapitre, nous consacrer à la réalisation d'instructions supplémentaires au Basic des AMSTRAD-CPC.

Nous procéderons par étapes successives, qui vous permettront d'accéder à la personnalisation du jeu d'instructions, en y introduisant vos propres commandes, au nom que vous aurez choisi, et qui appellent bien sûr, des routines en langage machine permettant de les traiter.

Quelques exemples vous permettront de créer vos premières instructions simples sans grandes connaissances en langage machine.

Vous devrez, ensuite, connaître un minimum de programmation en assembleur, afin de créer des routines plus élaborées ; mais une lecture assidue de votre ouvrage, vous ouvrira les portes du microprocesseur Z80 (on se reportera avec intérêt à la Partie 4, chapitre 2).
Certes, la puissance de l'interpréteur Basic de l'Amstrad vous permet de créer des fonctions élaborées (voir l'instruction DEF FN, si souvent ignorée des programmeurs en Basic), mais rien n'égalera la rapidité et le gain de place en mémoire RAM fournis par le code machine.
Entrons donc sans tarder, mais progressivement, dans la personnalisation de vos instructions.

I - L'instruction CALL

PREMIERS PAS AVEC L'INSTRUCTION CALL

Vous aurez déjà remarqué dans certains programmes de votre ouvrage, l'appel à des routines en langage machine grâce à l'instruction Basic:

CALL adresse

Cette instruction lance l'exécution d'une routine en langage machine située à partir de l'adresse spécifiée, et, ce, en général, dans la mémoire vive de votre CPC.

Cette adresse peut être décrite en décimal, signé ou non, (par exemple CALL 47878 ou CALL - 17658), éventuellement en binaire (CALL &X1011101100000110, mais trop complexe pour être utilisée), ou, le plus souvent, en hexadécimal (par exemple CALL &BB06).

Il est même possible d'appeler une routine dont l'adresse est contenue dans une variable numérique (CALL A ; A contenant l'adresse de la routine à appeler).

Dans les exemples indiqués ci-dessus, les adresses données sont rigoureusement identiques, et provoquent donc l'appel à une même routine, qui est un vecteur appelant une routine en ROM attendant l'appui sur une touche du clavier (voir Partie 4, chapitre 2.7 page 3).
A titre d'exemple, nous allons créer notre propre programme qui affichera le nom de WEKA sur l'écran, par un CALL adresse tout simplement.

Les explications seront données de façon à ce que vous puissiez modifier le programme, et inscrire votre propre nom à la place de celui de WEKA.

Il faut tout d'abord savoir que pour afficher des caractères sur l'écran, l'AMSTRAD ne comprend que les codes ASCII de ces caractères (codes hexadécimauxl.
Notre message, qui sera stocké en mémoire vive, sera donc créé ainsi :

PRINT CHR$(&57) ; CHR$(&45) ;CHR$(&4B) ; CHR$(&41)
;W ; E K ; A

Nous indiquerons la fin du message par le nombre hexadécimal &FF qui ne correspond à aucun caractère alphanumérique.

AFFICHAGE DU MESSAGE SUR LECRAN

Attaquer l'écran pixel par pixel, en allumant chacun des pixels des caractères dans la mémoire écran, demanderait une programmation fastidieuse (mais pas impossible sur le CPC).
En examinant de plus près la liste des vecteurs du système d'exploitation inscrits en RAM (voir Partie 4, chapitre 2.7.), nous y découvrons le vecteur TXT-OUTPUT (Partie 4, chapitre 2.7 p. 12) situé à l'adresse &BB5A, qui affiche la caractère dont le code ASCII est chargé dans le registre A.

Remarque :

La routine TXT-WR CHAR située en &BB5D aurait aussi pu nous convenir, car nous n'utiliserons pas de caractères de contrôle.

Il nous suffira donc de lire chacun des caractères du message dans le registre A, puis d'appeler la routine TXT-OUTPUT, qui les affichera.

L'algorithme du programme s'écrira ainsi :

DEBUT

Pointer la première lettre du message è afficher
TANT QUE le caractère lu n'est pas le caractère de fin de message (&FF)
Lire le caractère pointé
Pointer le caractère suivant
PROCEDURE afficher le caractère (TXT-OUTPUTJ
FIN TANT QUE
FIN

L'assembleur ne possédant pas l'instruction évoluée permettant de créer une boucle du type TANT QUE ... FIN TANT QUE, nous devrons la simuler par un test qui nous fera sortir de la boucle de lecture et d'affichage de caractère des que le nombre &FF est rencontré.
L'ordinogramme se traduira ainsi :

Vous trouverez ci-après le listing d'assemblage largement commenté afin que vous puissiez l'analyser en fonction de l'algorithme et de l'ordinogramme présentés plus haut.

  • Lignes 24 à 34 : programme principal.
  • Ligne 30 : le test sur le caractère de fin &FF qui permet le retour en cas d'égalité (ligne 31) – retour au Basic, si la routine a été appelée depuis le Basic.
  • Ligne 43 : message que vous pouvez modifier comme bon vous semble. Il faudra obligatoirement ajouter l'octet &FF après le message pour signaler la fin (ligne 44).

Vous trouverez ci-après le listing du chargeur Basic des codes machine.

Vous pouvez modifier la tigne de données du message (ligne 340) afin d'inscrire votre message. Le tableau des codes ASCII vous aidera à inscrire votre propre message, en y prenant les codes hexadécimaux des caractères désirés. Vous pouvez insérer autant de lignes de DATAs que vous voulez (donc un message aussi long que vous voulez).
Seules les lignes 370 et 400 doivent obligatoirement être les dernières lignes du programme.
Cette première approche de l'instruction CALL est relativement simple, puisqu'elle ne demande qu'un appel direct et effectue des traitements simples.

POUR ALLER PLUS LOIN AVEC CALL

Les routines machine peuvent, et sont plus souvent utillisées pour traiter des chiffres souvent différents, aussi faut-il pouvoir les transmettre au programme, et pourquoi pas, récupérer le résultat. La première idée qui vient à l'esprit est d'utiliser les instructions qui vont de pair avec CALL, PEEK et POKE.

POKE adresse, valeur permet de sauvegarder une valeur à une adresse précise en mémoire vive, que le programme en langage machine récupère à cette adresse.
Après traitement, il est possible de récupérer un résultat mémorisé à une adresse {par la routine) grâce à l'instruction PEEK adresse.

Cette méthode de programmation peut être intéressante lors du développement et de la mise au point des routines, mais devient vite lourde à gérer quand il faut transmettre et récupérer plusieurs paramètres à la routine.

Il est possible d'éviter cette façon de procéder en fournissant directement les valeurs avec l'instruction CALL. On appelle cela le passage de paramètre.

LE PASSAGE DE VALEURS FIXES ENTIÈRES

Nous allons, dans un premier temps étudier la manière de fournir des valeurs entières.
M est en effet possible d'écrire l'instruction CALL sous fa syntaxe suivante :

CALL adresse,valeur1,valeur2, .... valeurn

Trente deux valeurs peuvent être fournies de cette façon à la routine en assembleur.

Récupération des paramètres dans la routine

Il faut d'abord savoir que lors de l'exécution de ce type d'instruction, l'interpréteur Basic considère que les valeurs fournies sont codées sur 16 bits (donc des chiffres compris entre 0 et 65535 ou -32768 et + 32767).

Il empile ensuite ces valeurs en mémoire RAM (chacun occupera donc deux cases mémoire). L'endroit où sont empilées ces valeurs peut être connu grâce au registre d'index IX du Z80, on appelle cette adresse : adresse de base des paramètres. Le nombre de paramètres peut lui aussi être connu : il est inscrit dans le registre accumulateur A.

LE PASSAGE DUNE SEULE VALEUR NUMERIQUE

Nous considérerons dans un premier temps une instruction ne comportant qu'un paramètre de la forme :

CALL adresse,valeur

Après exécution, dans le programme en langage machine, nous pourrons vérifier qu'un seul paramètre a été envoyé en testant le registre A.
Pour obtenir la valeur transmise, il suffira de lire le contenu de IX + 00H pour avoir l'octet bas, la contenu de IX+ 01H nous donnera l'octet haut.

Exemple :

  • CALL adresse,3425 placera &A1 à l'adresse IX + 00h et &0D à l'adresse IX + 01H (car 3425 decimal = 0DA1 hexa).
  • CALL adresse,36 placera &24 en IX + 00H et &00 en IX + 01H.

Nous vous proposons le programme ci-dessous afin d'illustrer les explications ci-dessus. Ce programme exécutera un scrolling vertical d'une ligne de caractères (huit pixels} dans le sens que vous aurez précisé : sens montant si on transmet le paramètre 1, sens descendant si vous placez un paramètre différent {on prendra -1).
Le programme se trouvera à l'adresse &A000, ce qui donnera donc les instructions suivantes :

– CALL &A000,1 pour un scrolling montant,

– CALL &A000,-1 pour un scrolling descendant. Voici dans un premier temps l'algorithme du programme :

DEBUT
SI le nombre de paramètres est différent de 1
ALORS
Retourner au Basic
FIN SI
Récupérer l'octet bas du paramètre
SI sa valeur est 1
ALORS
; – Indiquer un scrolling haut
SINON
; – Indiquer un scrolling bas
– FIN SI
– Effectuer le scrolling
– FIN

Pour effectuer ce scrolling, il sera intéressant d'utiliser le vecteur SCR-HW-ROLL situé à l'adresse &BC4D, qui requiert dans le registre B le sens du scrolling, et dans A le numéro d'encre qui remplira la nouvelle ligne ainsi créée (on se reportera Partie 4, Chap. 2.7, page 36).
Le listing assemblé donne donc :

Le chargeur Basic est donné ci-dessous :

LE PASSAGE DE PLUSIEURS VALEURS NUMERIQUES

Dans le cas où plusieurs valeurs numériques sont fournies à la routine ,. en langage Machine, ces valeurs sont empilées dans l'ordre de frappe de l'instruction.

En exécutant l'instruction générale :

CALL adresse,valeur1,valeur2, ... valeur n-1,valeur n ces valeurs seront empilées ainsi :

IX + 2*(n-1)+1 octet haut de valeur 1
IX + 2*(n-1) ;octet bas de valeur 1
IX + 2*(n-1-1) + 1 octet haut de valeur 2
IX + 2*(n-1-1) octet bas de valeur 2

...

IX + 03H ; octet haut de valeur n -1
IX + 02H ; octet bas de valeur n - 1
IX + 01H ; octet haut de valeur n
IX + 00H ; octet bas de valeur n

La dernière valeur de l'instruction étant toujours à la base de IX.
Par exemple: CALL &adresse,1,2 place en :

IX + 00H ; la valeur 02
IX + 01H ; la valeur 00
IX + 02H ; la valeur 01
IX + 03H ; la valeur 00

LE PASSAGE D'UNE VARIABLE NUMÉRIQUE ENTIÈRE

Il est possible de transmettre à une routine en langage machine des valeurs entières contenues dans des variables numériques entières, c'est-à-dire des variables du type A% ou définies par l'instruction DEFINT variable.

En fait ce ne sont pas les valeurs contenues dans ces variables qui sont transmises, mais les adresses où ces valeurs sont sauvegardées en mémoire vive.
La syntaxe d'appel de la routine devra donc être la suivante :

CALL adresse,@variable%

qui transmet l'adresse du contenu de cette variable. Il faut remarquer que l'utilisation de cette séquence doit absolument être précédée d'une utilisation de la variable sous peine de générer un message d'erreur.

Sitôt dans la routine, il sera possible alors de récupérer l'adresse de l'octet faible de la valeur dans le registre Hl_, en général, puis d'accéder à la valeur, si elle est sur un octet, lisant le contenu de HL dans le registre accumulateur A.

Nous prendrons comme exemple le programme suivant :

Dans ce programme, IX + 00H contient la partie basse de l'adresse de la variable, il suffit de la lire dans le registre L (LD L, (IX + 00H)), puis on lit la partie haute dans le registre H (LD H,IX + 01H), enfin le contenu de cette adresse est lu dans le registre A (LD A,(HD) et est envoyé dans la routine moniteur d'impression (&BB5A).

Lors de l'exécution des instructions suivantes :

A% = &41 : CALL &A000,@A%

on obtient l'impression du caractère A (&41 = code ASCII de A) ; en fait, l'exécution de cette routine, pour tout autre valeur de A% provoque l'affichage du caractère correspondant au code ASCII contenu dans la variable [équivalent Basic : PRINT CHR$(A%)].

Il est, comme lors du passage de valeurs numériques entières, possible de passer plusieurs variables numériques entières sous la forme d'une instruction :

CALL &adresse,@variable1,@variable2, .... @variablen

Ce sont cette fois-ci les adresses de ces variables qui sont empilées l'une après l'autre et que l'on récupérera grâce au registre IX.

LE PASSAGE DE CHAINES DE CARACTERES

Il est aussi possible de passer une chaîne de caractères dans une instruction :

CALL &adresse,« CHAINE DE CARACTERE »

Cette syntaxe est prévue pour fonctionner sans problème sur le CPC-6128, nous verrons ultérieurement l'adaptation nécessaire aux modèles CPC-664 et CPC-464.

Lors de l'arrivée dans la routine machine, l'interpréteur Basic aura empilé l'adresse où se trouvent uniquement les caractéristiques de la chaîne de caractères.
A cette adresse se trouvent le nombre de caractères contenus dans la chaîne. A l'adresse immédiatement supérieure se trouve l'octet bas de l'adresse du premier caractère de la chaîne, puis à l'adresse supérieure, l'octet haut.

Pour récupérer la chaîne de caractères, il suffira donc de lire l'adresse contenue en IX+ 01H et IX + 00H, qui nous donnera l'adresse des caractéristiques de la chaîne. A cette adresse, on lira le nombre de caractères de la chaîne (pour le traitement, on place généralement ce nombre dans le registre B, car il existe une instruction en assembleur Z80 de test sur B qui permet un comptage : DJNZ ), on récupère ensuite l'adresse de la chaîne (aux octets supérieurs, en général dans un registre double HL ou DE).

Pour exemple, nous vous proposons un programme effectuant un scrol-ling horizontal du texte de la dernière ligne de l'écran grâce à une instruction de la forme :

CALL &A000,« MESSAGE »

Dans ce programme nous aurons besoin de positionner le message à afficher en toute dernière ligne. Il est possible de faire cela à l'aide des vecteurs en RAM (TXT-SET-CURSOR à l'adresse &BB75), mais il existe aussi certains caractères de contrôle qui sont pris en compte par la routine TXT-OUTPUT. Nous vous proposons ci-dessous la liste des codes correspondants et leur effet.

Tous les caractères présentés ci-après sont accessibles à partir du Basic par la commande

PRINT CHR$(caractère)<éventuellement CHR$(complément)>
HexaDécimalFonction
000Caractère nul - aucune action.
011Visualise sur l'écran les caractères de contrôle. Par exemple en Basic PRINT CHR$(1 );CHR$(10) affiche une flèche vers le bas.
022Permet de ne pas visualiser le curseur en mode programme (lors d'un INPUT par exemple).
033Rétablit le curseur.
044Change le mode graphique, comme l'instruction MODE.

Exemple : PRINT CHR$(4) ; CHR$(2) passe en MODE 2.

055Ecrit un caractère à l'emplacement du curseur graphique.
066Annule la commande de masquage sur écran (voir le code 21 décimal)
077Emet le BIP de la cloche.
088Effectue un déplacement d'un caractère vers la gauche.
099Effectue un déplacement d'un caractère vers la droite.
0A10Effectue un déplacement d'un caractère vers le bas.
0B11Effectue un déplacement d'un caractère vers le haut.
0C12Efface la fenêtre courante (équivalent de CLS du Basic).
0D13Retour Chariot : place le curseur à la gauche de la ligne courante.
0E14Equivalent à l'instruction PAPER PRINT CHR$(14);CHR$(2), place la couleur du fond de l'écran à la couleur de l'encre 2.
0F15Equivalent à l'instruction PEN.
1016Equivalent de la fonction effectuée par la touche < CRL > : efface le caractère sous le curseur.
1117Efface tous les caractères précédant le curseur dans la ligne courante.
1218Efface tous les caractères suivant le curseur dans la ligne courante.
1319Efface tous les caractères depuis le début de la fenêtre courante jusqu'au curseur.
1420Efface tous les caractères depuis le curseur jusqu'à la fin de la fenêtre courante.
1521En relation avec le code 06 : interdit l'affichage à l'écran.
1622Permet d'écrire des caractères en mode transparence, c'est-à-dire d'écrire sur un caractère déjà affiché :

PRINT CHR$(22);CHRS$1 : mode transparent,

PRINT CHR$(22);CHR$(0) : mode normal.

1723Modifie le mode graphique (accompagné de CHR$(1 ) ; CHR$(2) ; CHR$(3) ; CHR$(4).
1824Fonctionne en bascule pour établir ou annuler l'inversion vidéo.
1925Equivalent de la commande SYMBOL en Basic. Ce code nécessite d'être suivi de 9 paramètres (le numéro du caractère puis les 8 valeurs le définissant).
1A26Equivalent de la commande WINDOW en Basic, mais uniquement avec les quatre chiffres définissant la fenêtre.
1B27Caractère d'échappement (ESCAPE), utile pour la communication, avec un Minitel par exemple, ou l'imprimante.
1C28Equivalent à la fonction INK du Basic mais demande à être suivie obligatoirement des trois chiffres (numéro d'encre, couleur 1, couleur 2).
1D29Equivalent à BORDER avec deux couleurs obligatoirement.
1E30Place le curseur à la position originelle de la fenêtre.
1F31Equivalent de LOCATE Basic, donc suivi de deux caractères.


La méthode retenue est de déplacer tous les pixels un à un d'une position.
Il faut savoir que ces pixels sont inscrits en RAM ECRAN entre les adresses &C000 et &FFFF. Voici la carte de ta mémoire écran suite à une initialisation du CPC ou après une instruction MODE n:

Organisation des adresses écran des CPC après l'instruction MODE.

On trouvera donc les pixels de la dernière ligne de caractères entre les adresses &C780-&C7CF, &CF80-&CFCF.....&FF80-&FFCF. Lorsqu'on lira une de ces adresses (grâce à PEEK (adresse)) on obtiendra la valeur hexadécimale de huit pixels de cette adresse.
Notre méthode de décalage consistera à lire l'adresse la plus à droite d'une ligne de pixel, décaler ces pixels un à un, récupérer le pixel de gauche, l'inscrire en tant que pixel de droite lors du décalage des pixels de l'adresse immédiatement à gauche,... etc., jusqu'à l'adresse la plus à gauche. Il ne faudra pas oublier ensuite de replacer le pixel décalé le plus à gauche à la place du pixel le plus à droite 30us peine de perdre un pixel à chaque décalage, ce qui ferait disparaître notre message. Les décalages sur une ligne de pixels étant effectués, il faudra passer à la ligne suivante, et ainsi de suite.
Deux petits problèmes se posent tout de même : d'une part la mémoire écran ne contient pas seulement l'état allumé ou non des pixels, d'autre part elle ne se trouve pas toujours aux mêmes adresses. Certaines restrictions d'utilisation nous seront donc imposées : appeler toujours cette routine suite à une instruction MODE fi (car un scrolling décale toute la mémoire écran), de préférence en MODE 2 car dans les autres modes, les couleurs sont inscrites dans les adresses écran (bien que l'effet ne soit pas désagréable en MODE 1 : on obtient un passage dans les différentes couleurs du message).

Nous vous proposons maintenant l'ordinogramme du scrolling horizontal :



On remarquera dans cet ordinogramme l'appel de la routine &BB09 qui va contrôler si un caractère a été frappé sans l'attendre (équivalent de INKEY$ du Basic), pour nous permettre de quitter la routine de décalage.

Le programme assembleur commenté sera donc :


On retrouve la routine d'affichage de caractères aux adresses &A006-&A00F qui positionne le curseur en ligne 25 colonne 1, ainsi qu'aux adresses &A01D-&A022 pour afficher le message.

A l'adresse &A024, le nombre hexadécimal &800 chargé dans le double registre DE correspond au nombre d'adresses à ajouter pour passer à la ligne de pixels suivante.

A l'adresse &A02F, le chargement dans B de la valeur &50 correspond au nombre d'adresses d'une ligne (&50 = 80 decimal),

Pour ceux qui ne possèdent pas d'assembleur, mais que ce programme intéresse, nous vous soumettons le chargeur Basic des instructions ci-dessous :


L'appel de l'instruction se fera sous la forme :

CALL &A000,"MESSAGE"

si vous possédez un CPC-6128.

Les possesseurs d'un CPC-464 devront ruser pour faire digérer cette instruction à leur ordinateur. Ils devront en effet passer par l'intermédiaire d'une variable alphanumérique, la routine sera donc appelée en deux temps :

A$ = "MESSAGE"

CALL &A000,@A$

Ce qui ne change rien aux explications données plus haut, c'est cette fois le pointeur de la variable A$ qui est transmis aux travers des adresses IX + OOH et IX + 01 H.
Tout comme pour le passage des variables numériques entières, il est possible de passer à la routine plusieurs chaînes de caractères par les instructions :

CALL &A000, « CHAINE1 », « CHAINE2 ».....« CHAINEn »

ou CALL &A000,@A1$,@2$, ... @An$

LA RECUPERATION DES VARIABLES NUMERIQUES

S'il est possible de transmettre à la routine des variables, il est inversement possible de récupérer des résultats suite à un traitement, dans une variable.
Il suffit en effet de passer à la routine le pointeur d'une variable pour qu'elle aille y sauvegarder des valeurs, que l'on pourra relire sous Basic dans la variable.
Pour passer le pointeur d'une variable numérique, il suffit qu'elle existe, elle sera donc créée par l'instruction VARIABLE% = 0 par exemple.
Lors de l'appel de la routine il suffira d'y adjoindre son pointeur @VARIABLE%, qui sera lu dans la pile pointée par IX, l'adresse sera ensuite connue et les éventuels résultats rangés à cette adresse.

LA RECUPERATION DES VARIABLES ALPHANUMERIQUES

Il est également possible de récupérer des chaînes de caractères traitées dans une routine en langage machine.
Pour une seule chaîne de caractères, il suffit de créer une variable par A$ = SPACES(n), n étant généralement le nombre de caractères maximal que pourra contenir la chaîne, puis on transmet le pointeur de cette chaîne par l'instruction :

CALL &adresse,@A$

Dans la routine il suffira de récupérer l'adresse de la variable à l'aide du pointeur, et de la traiter, en n'oubliant pas de spécifier le nombre de caractères la composant.
Nous allons prendre à titre d'exemple une routine permettant de convertir une chaîne de caractères contenant un message, en une autre chaîne contenant la conversion ASCII de tous ces caractères. Cette routine pourra vous être utile pour modifier le programme d'affichage d'un message.

Nous nous proposons d'appeler la routine sous la forme :

A$ = "CHAINE DE CARACTERES"
B$ = SPACES (254)
CALL &A000,@A$,@B$

où A$ contient la chaîne à convertir, et B$ la conversion de tous les caractères.

Il faut d'abord savoir qu'une chaîne de caractères peut contenir au maximum 255 caractères, or, comme la conversion d'un caractère alphanumérique se traduit en deux chiffres hexadécimaux, 8$ ne pouvant ainsi contenir qu'au maximum 254 caractères, A n'en contiendra pas plus de 127.

Voici l'ordinogramme de conversion proposé :



L'ordinogramme d'affichage du message d'erreur n'est pas ici explicité car déjà vu précédemment.

On retrouve la lecture des deux pointeurs des variables qui sont traités afin de lire la chaîne de caractères et d'inscrire la chaîne convertie aux adresses correspondantes.
Le sous-programme de conversion est intéressant, car très rapide dans son exécution, et doit être retenu pour d'éventuelles utilisations ultérieures (procédures de communications, par exemple). Ce type de traitement provient d'une réflexion mathématique sur les différents codes ASCII des caractères. Il impose malheureusement une limitation aux caractères alphabétiques de A à F et aux chiffres de 0 à 9 (hexadécimal oblige).

Le programme en langage d'assemblage qui en découle est le suivant :



A l'adresse &A010 le test du nombre de caractères est effectué sur le bit le plus à gauche du nombre, car celui-ci passe à 1 dès que ce nombre est supérieur ou égal à 128.
On retiendra la partie de programme entre les adresses &A019 et &A01B qui consiste à mettre dans DE le contenu des adresses pointées par HL et HL+ 1. Si l'on y ajoute l'instruction EXG, DE, HL, on obtient un résultat correspondant à HL - (HL+1MLH).
Le listing du chargeur Basic est donné ci-après .

II - Les RSX

(Sur ce sujet reportez-vous également à la Partie 4, Chap. 2.9).
Après avoir étudié différentes façon de transmettre des paramètres à une routine en langage Machine, nous pouvons nous lancer dans la création des RSX.

QU'EST-CE QU'UNE RSX ?

Mot bien souvent magique, qui rebute beaucoup de programmeurs Basic, mais qui va être sans secret pour vous d'ici quelques instants.
RSX vient de la contraction du terme Résident System extension, qui, mot à mot veut dire extension résidente dans le système. Ces extensions sont dans notre cas des commandes Basic qui sont intégrées aux commandes déjà existantes, à la seule particularité qu'elles doivent être précédées du caractère ù (ou la barre verticale I) de code ASCII 124).

POURQUOI LES RSX ?

Oui, pourquoi créer de nouveaux noms d'instructions alors que pour appeler une routine en langage Machine, il suffit d'effectuer un appel à cette routine par CALL ?
Imaginez un Basic uniquement composé d'instructions CALL à différentes adresses, quelle mémoire devrez-vous posséder avant d'utiliser celle de votre ordinateur ! Il est bien plus simple de retenir une instruction par un nom que par un numéro, qui plus est hexadécimal !

COMMENT CREER UNE RSX ?

La création d'une RSX est très simple, maintenant que vous savez manier l'instruction CALL.
Un vecteur du système d'exploitation Basic est spécialement implanté pour cela :

KL-LOG-EXT

(voir Partie 4, Chap. 2.7 page 54).

Ce vecteur s'utilise dans une petite routine en langage machine qui définit la ou les extensions à intégrer au Basic.
Il requiert différents paramètres qui sont :

  • l'adresse de la table des instructions,
  • l'adresse d'une zone libre de quatre octets.

La routine de liaison des RSX se présentera toujours sous la forme de l'algorithme suivant :

– DEBUT
– Charger HL avec l'adresse de la zone de quatre octets
– Charger BC avec l'adresse de la table des instructions
– PROCEDURE KL-LOG-EXT
– Placer le code de RET au début de la routine
– FIN

Ce qui nous donne en langage d'assemblage :

DEBUT LD HL,KERNEL
LD BC,VECTEU
CALL 0BCD1H
LD A,0C9H
LD (DEBUT),A
RET

Le chargement du code RET à l'adresse de début de la routine de définition des instructions n'est pas obligatoire, mais il est vivement recommandé, car un deuxième appel à cette routine provoquerait un plantage du microprocesseur, et bien souvent l'obligation d'effectuer un RESET et de perdre toutes les données, pour reprendre la main.

Il faudra ensuite faire suivre cette routine des différents vecteurs et table
des instructions, de la façon suivante :

VECTEU DEFW TABLE
JP INSTRUCTION1
JP INSTRUCTION2
; ...
JP INSTRUCTION
TABLE DEFB "INSTRUCTION! moins la dernière lettre"
DEFB 080H + "dernière lettre de l'instruction 1"
DEFB "INSTRUCTIONn moins la dernière lettre"
DEFB 080H + "dernière lettre de l'instruction n"
DEFB 00H
KERNEL DEFS 4

Nous trouvons dans cette partie de la routine à l'étiquette VECTEU la définition de l'adresse de la table des instructions, suivie de la table des sauts au traitement des instructions. Par exemple JP INSTRUCTION1, effectue un saut à la routine de traitement de l'instruction 1, ce traitement sera identique au traitement par l'instruction CALL.

Vient ensuite la table des instructions, qui doit être dans l'ordre de la table de saut des instructions. Dans cette table, les noms des instructions devront être obligatoirement écrits en MAJUSCULE, avec, de plus, le nombre hexadécimal &80 ajouté au dernier caractère, ceci pour que le moniteur reconnaisse ta fin de l'instruction.
On trouve en tout dernier la réservation de quatre octets pour la routine.

Il sera possible d'installer, après cette routine les différents traitements prévus.

Prenons un exemple simple : notre première instruction consistera à inscrire le nom de ùWEKA ou IWEKA, et à obtenir un message. Pour ceux qui ne posséderaient pas encore d'assembleur, nous vous donnerons le chargeur Basic, ainsi que toutes les explications pour modifier cette routine.

Le programme de traitement de cette instruction ne sera pas très différent du programme des premiers pas effectués avec l'instruction CALL, si ce n'est la définition de cette instruction. Aussi, nous vous donnons ci-dessous, directement, le listing assembleur ;



A l'adresse A014, nous trouvons les trois premières lettres de l'instruction WEK, puis, la lettre A à laquelle on ajoute &80 à l'adresse A017.

Le programme de traitement est identique à tous les programmes d'affichage de chaîne de caractères et de caractères de contrôle vus plus haut.
Après sauvegarde et assemblage, on procède à l'initialisation de l'instruction par les commandes :

MEMORY &9FFF
CALL &A000

Vous trouverez ci-dessous le listing Basic du chargeur de cette instruction :


Une fois sauvegardé, le programme sera exécuté par RUN, puis installé par :

MEMORY &9FFF
CALL &A000

Il sera ensuite possible d'effacer le chargeur Basic par NEW, et d'appeler l'instruction ùWEKA (ou |WEKA).
Ceux d'entre vous qui possèdent un assembleur n'auront aucun mal pour adapter l'instruction à leur nom par exemple, par contre voici les explications pour la modifier dans le chargeur Basic :

En lignes 390 à 410, il est réservé 21 octets pour le nom de l'instruction. Il vous suffira de modifier les quatre premiers octets, puis de remplacer les 00 par les codes ASCII de noms que vous désirez inscrire. Vous obtiendrez les codes ASCII du nom grâce à la table de conversion donnée plus haut, il vous suffira de frapper la commande :

PRINT HEX$ (&dernieroctet + &80) pour obtenir la valeur du dernier caractère du nom à inscrire.

Attention :

Le nombre d'octets de ces trois lignes doit impérativement être égal à 21 (les zéros compris).

Vous pourrez modifier ensuite le message entre les lignes 510 et 620. Vous pourrez cette fois-ci inscrire autant d'octets ASCII que vous désirez à la condition que les deux dernières valeurs en DATA (lignes 650 et 690) soient, dans l'ordre FF et XX.

Page précédente : 4/1.6.1 - SYMBOL et SYMBOL AFTER
Je participe au site:

» Vous avez remarqué une erreur dans ce texte ?
» Aidez-nous à améliorer cette page : en nous contactant via le forum ou par email.

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