CODING ★ RESTAURATION DE LA MEMOIRE BASIC ★

Basic - Restauration de la Memoire Basic|CPC Revue)

Le manuel du CPC 464 dit ceci à propos de HIMEM : "Avant de redéfinir l'octet le plus haut avec la commande MEMORY, il est souhaitable d'écrire mm = HIMEM. Vous pourrez après retourner à la capacité de mémoire précédente avec la commande MEMORY m."
Le manuel mentionne donc la question de la restauration de la mémoire et c'est bien. Malheureusement, le problème est d'une part mal posé, d'autre part mal résolu.

Nous proposons une procédure tout à fait différente de restauration mémoire. Mais, auparavant, nous devons répondre aux 3 questions suivantes ;

Est-il utile de restaurer la mémoire (autrement que par RESET) ? –   En quoi le problème est-il mal posé dans le manuel ?

Pourquoi est-il mal résolu ?

FAUT-IL RESTAURER LA MEMOIRE ?

Sauf en cas de RESET, tout programme "hérite" de l'organisation mémoire léguée par son prédécesseur. Cette organisation a pu, éventuellement, être modifiée par des commandes en mode direct. Cette "passation de suite" se fait évidemment pour un même programme d'un RUN au RUN suivant. L'erreur bien connue "improper argu ment" intervenant au 2e RUN d'un programme commençant par :

SYMBOL AFTER nnn
MEMORY zzzz

tient au fait que le 2e RUN hérite des zones SYMBOL et MEMORY créées par le 1er et que le BASIC refuse alors de créer une 2° zone SYMBOL. La mémoire BASIC peut être réduite par la réservation des zones suivantes :

SYMBOL AFTER  (0 à 1 zone)
MEMORY        (0 à 3 zones)
FICHIER       (0 à 1 zone)

Nota : s'il existe une zone FICHIER, il existe au moins une zone MEMORY, car nous supposons une pratique sans faille de :

OPENOUT"bidon":MEMORY HIMEM-1: CLOSEOUT

Voici un exemple de configuration à 5 zones qui peut surprendre, mais qui est tout à fait possible.

Il faut, pour la réaliser, commencer par faire SYMBOL AFTER 256 car il ne peut y avoir qu'une seule zone SYMBOL AFTER, comme nous l'avons vu.

  BASIC        BAS
--------------------------
Memory C       (souvent 1 octet)
Fichier        (4096 octets)
Memory B       (B octets)
Symbol         (8 à 2048 octets)
Memory A       (A octets)
Ram Système    HAUT

Il est probable que les petits programmes n'ayant pas de besoins particuliers pour ront s'accommoder d'un tel héritage. Mais pour :

–   les gros programmes,
–   ceux qui ont besoin d'une réservation d'espace à une adresse précise,
–   ceux qui ont besoin d'une zone SYMBOL AFTER plus importante,

il ne peut être question de conserver l'organisation léguée, par le programme précédent.

Par ailleurs, la solution bien connue qui consiste à faire RESET pour réinitialiser la mémoire n'est pas sans inconvénients :

–   effacement des instructions KEY,
–   effacement du programme en cours,
–   pas de possibilité d'écrire RUN et LOAD dans un programme pour appeler le programme suivant.

On peut donc affirmer qu'il est très souhaitable de pouvoir restaurer la mémoire autrement que par RESET.

EN QUOI LE PROBLEME EST-IL MAL POSE ?

Il est mal posé parce qu'il est plus logique de restaurer en DEBUT qu'en FIN de PROGRAMME.

En effet, pour un programme donné, la restauration au début donne la certitude d'avoir une organisation mémoire convenable.

Dans l'autre cas (restauration en fin), cette certitude ne peut s'obtenir qu'en programmant la restauration mémoire dans TOUS les programmes susceptibles de précéder le programme concerné. De plus, il faudrait s'interdire l'utilisation des ordres MEMORY, SYMBOL AFTER et OPEN en mode direct. Pour illustrer le caractère sournois d'un oubli, voici un petit exemple : Supposons   qu'un   programme   hérite d'une zone MEMORY 30000 et qu'il ait besoin d'une zone MEMORY 40000. Le   programmeur  qui   suit  le   Manuel écrira :

mm-HIMEM                  'donc mm- 30000
MEMORY 40000              ' la mémoire monte à 40000
                            (sans problèmes
                            supposons-le)
...............
...............
MEMORY mm                 ' la mémoire
                            baisse à 30000 valeur
                          ' léguée au programme
                            suivant. Bravo !


LA PROCEDURE "mm a HIMEM
" MEMORY mm" DU MANUEL NE MARCHE PAS

Procédons à un certain nombre d'essais

dans les conditions ci-dessous :

a) Par hypothèse, les instructions suivantes font partie de chaque essai :
RESET et SYMBOL   AFTER   256 avant chaque essai.
PRINT HIMEM au tout début et à l'extrême fin de l'essai.
b) Les caractères délimitent les instructions centrales {non écrites si elles sont sans intérêt).

c)  Les résultats sont notés :

OUI si HIMEM fin = HIMEM deb
NON si ERREUR ou si HIMEM différents

Conclusion des essais

Le procédé du manuel est à rejeter pour les raisons suivantes :

– MEMORY ne peut pas récupérer une zone SYMBOL AFTER (seul SYMBOL AFTER 256 peut le faire).
–  MEMORY ne peut pas récupérer une zone FICHIER OUVERTE (seul CLO-SEOUT et/ou CLOSEIN peuvent le faire).
–  MEMORY ne peut récupérer une zone FICHIER FERMEE (du genre OPE-NOUT"bidon") qu'à une seule condition :
Au moment où l'ordre MEMORY va être exécuté, la valeur de HIMEM doit être celle créée par l'ordre OPENOUT lavant le MEMORY HIMEM-1).
C'est ainsi que l'essai n° 4 réussit si l'on remplace MEMORY mm par MEMORY HIMEM + 1 : MEMORY mm

UNE AUTRE SOLUTION

La solution du problème réside dans l'utilisation de 2 adresses gérées par le BASIC.

Ces 2 adresses se trouvent en AE7B/C (il s'agit tout simplement de HIMEM) et le couple d'octets voisin en AE7D/E. Nous appellerons MEMOIRE LIBRE (ou plutôt mémoire libérable par MEMORY) et en abrégé MMLIB cette 2e adresse.

Utilisation de MMLIB et HIMEM

MMLIB est la valeur maximum du paramètre que l'on peut associer à MEMORY. Nous avons toujours MMLIB> = HIMEM
En conséquence : Si HIMEMSi HIMEM-mmlib, MEMORY ne doit plus être utilisé (car l'ordre MEMORY HIMEM n'a aucun effet).
Nous avons alors 2 cas de figure théoriquement possibles :

a)  Nous sommes 1 octet plus bas qu'une zone FICHIER OUVERT.

b)  Nous sommes 1 octet plus bas qu'une zone SYMBOL AFTER.

Puisque nous restaurons en début de programme,  le cas a est éliminé car aucun fichier n'est ouvert en début de programme.

Reste le cas b que l'on traite par SYMBOL AFTER 256.

Ceci se traduit par les 2 lignes de BASIC ci-après :

100 mmlib = PEEK(&AE7D) + 256* PEEK(&AE7E);IF HIMEM < mmlib THEN MEMORY mmlib:GOTO 100
200 hiold = HIMEM: SYMBOL AFTER 256: IF HIMEM>hiold THEN 100

On pourrait, pour arrêter le processus, comparer HIMEM à la valeur MAXI de 42647 (ou 44031 pour les cassettes), au lieu de vérifier que sa valeur reste égale à HIOLD.

Malheureusement,  l'utilisation de certaine(s) routine(s) du système d'exploitation a pour résultat apparent de diminuer le MAXI en le rendant égal à la valeur du HIMEM courant. C'est en effet le regrettable comportement de la routine &BB4E utilisée inconsidérément. Ainsi, le petit programme : RESET SYMBOL AFTER 256

100 PRINT HIMEM '  42747 à la  1ere itération
101   '                           puis  42619  puis 42491 etc.
110 SYMBOL AFTER 240
120 CALL &BB4E
130 SYMBOL AFTER 256 ' ne fait rien (HIMEM non augmenté)
140 GOTO 100

grignotera la mémoire BASIC à raison de 128  octets   à  chaque   itération   avec "memory full" pour HIMEM = 16507. L'explication   peut   être   considérée comme la suivante : Call &BB4E met à zéro l'octet &B295 Cet octet a la valeur 255 lorsqu'une matrice  de  caractères  est  définie,  la valeur 0 après un SYMBOL AFTER 256. Par ailleurs,   l'octet B294 contient le numéro du 1er caractère "utilisateur". Par exemple, on aura :

- Après SYMBOL AFTER 240 : B294-240 et B295 = 255
- Après SYMBOL AFTER 0 : B294-0 et B295-255

Après SYMBOL AFTER 256 : B295 = 0 et B294 = 0 On voit que la valeur de B295 permet de distinguer   SYMBOL   AFTER   256   et SYMBOL AFTER 0 qui sont notés tous deux zéro en &B294. Call   &BB4E   fait   en   quelque   sorte "croire" au système qu'on vient de faire un SYMBOL AFTER 256, alors qu'il n'en est rien.

Sur cette base frauduleuse, le système considère alors que MAXI = HIMEM. Nous n'avons pas trouvé un moyen sûr de contrecarrer les agissements délétères de &BB4E {que cette routine soit appelée à partir du BASIC ou d'une routine machine).

Il y a donc lieu, soit de s'en tenir aux 2 lignes de BASIC précédentes, soit d'ajouter une 3e ligne pour "prévenir". On a alors :
 

100 mmlib = PEEK (&AE7D) + 256*PEEK (&AE7E):IF HIMEM< mmlib THEN MEMORY mmlib:GOTO 100
200 hiold = HIMEM: SYMBOL AFTER 256: IF HIMEM>HIOLD THEN 100
300 MAXI =42747:IF   HIMEMLa valeur de MAXI est bien entendu à remplacer par 44031 pour les systèmes à cassette.

Il est souhaitable de stocker ces 3 lignes sur disque (ou sur cassette! sous format ASCII.

Elles pourront être exécutées par RUN ou intégrées par MERGE aux programmes qui ont besoin d'une restauration mémoire.

Notons que MMLIB, HIOLD sont des variables réelles. Il faudra donc fusionner ces 2 ou 3 lignes avant un ordre DEFINT éventuel.

Les articles suivants, parus dans CPC, précisent certaines questions :

  • Le bug de l'openout (Michel Archambault) : n° 3, p.48.
  • Fichiers (Michel Archambault) : n° 18. p.22.
  • Symbol After (Michel Archambault) : n° 12, p. 44.
  • Test (Patrick Guyon) : n° 19, p. 89.

CPC n°23

★ ANNÉE: ???
★ AUTEUR: BERNARD BESSE

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