HP-71C27estFacilePEEKETPOKE
=PEEK$ ET POKE !=
De tous les mots-clé du BASIC du HP-71, les deux qui sont le moins abordés dans le manuel d'utilisation et le manuel de référence sont PEEK$ et POKE. Ce n'est pas surprenant ! Ces deux mots-clé vous permettent de vous promener à travers la mémoire, découvrant ce que HP préférerait voir caché, et même de changer tout ce que vous voulez, n'importe où en mémoire ! Un programmeur sans PEEK$ et POKE qui les découvre soudain est comme un coiffeur qui devient ingénieur
Assez de louanges. Voyons quelques utilisations pratiques de PEEK$ et POKE. Le premier intérêt de PEEK$ est qu'il vous permet d'obtenir certaines valeurs qui autrement seraient inaccessibles. Supposons que votre programme détruit les drapeaux 0 à 63. Vous pourriez les sauvegarder dans 64 variables, mais cela vous prendrait beaucoup de temps et de place mémoire.
PEEK$ à la rescousse. Les drapeaux 0 à 63 se trouvent dans 16 quartets de mémoire à l'adresse hexadécimale 2F6E9. Aussi, pour sauvegarder les 64 drapeaux faîtes juste :
F$=PEEK$("2F6E9",16)
et ils sont tous placés dans la variable F$ en un rien de temps. Quand vous avez fini de jouer avec les drapeaux, il suffit de faire :
POKE "2F6E9",F$
pour restaurer les drapeaux dans leur position initiale ! Le premier usage de POKE est pour le contrôle. Il n'y a simplement aucun moyen de faire certaines choses sans POKEr au bon endroit du HP-71. Supposons que vous voulez qu'un programme s'exécute sans interruption, même si quelqu'un presse la touche [ON]. Le seul moyen est :
POKE "2F441","F"
ce qui empêche la touche [ON] d'interrompre les programmes (elle est revalidée par POKE "2F441","0"). Ce type de contrôle n'est pas accessible autrement.
Bien que les programmes de ce livre contiennent une quantité d'exemples de PEEK$ et POKE, voici une table des adresses hexadécimales primaires qui sont utiles ou intéressantes pour PEEK$ et POKE.
ATTENTION !! POKEr à gauche et à droite sans précautions est imprudent car il peut en résulter un MEMORY LOST (perte de mémoire) ou pire un "plantage" si mauvais que vous devrez envoyer le HP-71 en réparation. Des précautions simples et un peu de bon sens suffisent pour éviter ce genre de problèmes.
Comment fonctionnent PEEK$ et POKE ? Quand vous stockez un nombre en mémoire, disons 1234 dans X, chaque chiffre utilise une partie de la mémoire appelée un "quartet". Alors que la plupart des ordinateurs utilisent des "octets" (8 bits), le HP-71 utilise des quartets (4 bits). Chaque quartet en mémoire a sa propre adresse, de 0 à 1048575. Pour simplifier l'adressage, PEEK$ et POKE ne se réfèrent pas pour l'adresse à des nombres aussi grands. A la place, elles utilisent leur version hexadécimale. Utilisez les fonctions HTD et DTH$ pour voir à quoi ressemble un nombre en hex.
Vous savez déjà que quand vous exécutez la commande CONTRAST, le contraste de l'affichage change. Vous pouvez le régler n'importe comment entre 0 et 15. en hexadécimal cela s'écrit de 0 à F. Ceci suggère que le contraste de l'affichage est stocké quelque part dans un seul quartet, et en fait c'est l'exacte vérité. Il réside dans le quartet dont l'adresse est 189438. en hex (utilisez DTH$ pour le vérifier) ce nombre est 2E3FE. Aussi vous pouvez utiliser PEEK$ et POKE pour voir la valeur du contraste et la changer.
Essayez ceci : CONTRAST 7 pour régler le contraste sur 7. Puis PEEK$("2E3FE",1) et vous verrez 7, le quartet de contraste !
Maintenant essayez CONTRAST 10 et PEEK$ à nouveau (avec la pile de commande). Cette fois vous voyez A. Pourquoi A ? Parce que c'est la notation hexadécimale qui correspond au 10 décimal. Utilisez HTD pour vérifier :
HTD(PEEK$("2E3FE",1))
et voyez 10 !
Nous pouvons aussi utiliser POKE pour changer le quartet de contraste. C'est bête, puisque nous avons la commande CONTRAST pour cela, mais c'est instructif et immédiatement reconnaissable. Essayez ceci :
POKE "2E3FE","4".
remarquez que le contraste change immédiatement pour 4 ! C'est parce que vous avez dit au HP-71 de placer un "4" en mémoire à partir du quartet d'adresse "2E3FE" qui est le quartet de contraste. ATTENTION ! N'essayez pas d'autre adresse, et n'essayez pas de POKEr de choses longues de plus d'un quartet ! Cela désorganiserait la mémoire et risquerait de provoquer un plantage sérieux.
Voici une table partielle d'adresses utiles (en hex). Certaines sont pour regarder seulement avec PEEK$, d'autres pour y écrire avec POKE et quelques-unes pour les deux.
Soyez prudents !
<DL compact> <dt><b></b></dt>
<dd> [adresse(nombre)]sujet
<dt><b></b></dt>
<dd> [2C014 (1)]Présence du lecteur de cartes (0 si il n'est pas présent)
<dt><b></b></dt>
<dd> [2E100 (2)]Annonciateurs de la partie gauche de l'affichage
<dt><b></b></dt>
<dd> [2E34C (2)]Annonciateurs de la partie droite
<dt><b></b></dt>
<dd> [2E350 (16)]Pilotes des rangées de l'afficheur (initialisés par INIT: 1)
<dt><b></b></dt>
<dd> [2E3FE (1)]Contraste de l'affichage
<dt><b></b></dt>
<dd> [2E3FF (1)]Contrôleur de l'affichage (1 = allumé, 2 = éteint)
<dt><b></b></dt>
<dd> [2F438 (4)]Constante de départ à froid (Memory lost si modifié)
<dt><b></b></dt>
<dd> [2F43C (5)]Vecteur d'interruption (Mauvais plantage en cas de modification)
<dt><b></b></dt>
<dd> [2F441 (1)]Invalidation de la touche [ATTN] (0 = Validé)
<dt><b></b></dt>
<dd> [2F443 (1)]Pointeur de tampon de clavier
<dt><b></b></dt>
<dd> [2F444 (15*2)]Tampon de clavier (2 quartets par code de touche)
<dt><b></b></dt>
<dd> [2F471 (2)]Nombre de caractères à gauche de la fenêtre (Window)
<dt><b></b></dt>
<dd> [2F473 (2)]Longueur de la fenêtre moins 1
<dt><b></b></dt>
<dd> [2F47C (2)]Pointeur de tampon sur le premier caractère affiché
<dt><b></b></dt>
<dd> [2F47E (2)]Pointeur de tampon sur le curseur
<dt><b></b></dt>
<dd> [2F480 (96*2)]Tampon d'affichage (2 quartets par caractère)
<dt><b></b></dt>
<dd> [2F540 (96/4)]Masque de lisibilité de l'affichage (1 bit par caractère)
<dt><b></b></dt>
<dd> [2F576 (5)]Adresse du haut de la pile de commande
<dt><b></b></dt>
<dd> [2F58A (5)]Adresse du bas de la pile de commande
<dt><b></b></dt>
<dd> [2F59E (5)]Adresse de la pile FOR/NEXT
<dt><b></b></dt>
<dd> [2F5A3 (5)]Adresse de la pile des GOSUB
<dt><b></b></dt>
<dd> [2F5A8 (5)]Adresse de l'espace Variables actif
<dt><b></b></dt>
<dd> [2F5AD (5)]Adresse de la pile des CALL
<dt><b></b></dt>
<dd> [2F5B2 (5)]Adresse de la fin absolue de la mémoire
<dt><b></b></dt>
<dd> [2F5B7 (5)]Adresse de la Chaîne de paramètres
<dt><b></b></dt>
<dd> [2F5BE (26*7)]Chaînage des variables (7 quartets pour A, 7 pour B...)
<dt><b></b></dt>
<dd> [2F6C6 (5)]Adresse du tampon d'entrée
<dt><b></b></dt>
<dd> [2F6CB (4)]Incrément pour AUTO
<dt><b></b></dt>
<dd> [2F6D9 (64/4)]Drapeaux système (-1 à -64), 1 bit par drapeau
<dt><b></b></dt>
<dd> [2F6E9 (64/4)]Drapeaux utilisateurs (0 à 63), 1 bit par drapeau
<dt><b></b></dt>
<dd> [2F6F9 (5)]Trappes IEEE (INX, UNF, OVF, DVZ, IVL)
<dt><b></b></dt>
<dd> [2F6FE (15)]Graine pour le générateur de nombres aléatoires RND
<dt><b></b></dt>
<dd> [2F761 (2)]Carte des bits des alarmes courantes
<dt><b></b></dt>
<dd> [2F763 (12)]Dérives accumulées de l'horloge
<dt><b></b></dt>
<dd> [2F76F (12)]Heure de la dernière mise à l'heure
<dt><b></b></dt>
<dd> [2F77B (12)]Heure du dernier ajustement du facteur de précision
<dt><b></b></dt>
<dd> [2F787 (6)]Facteur de précision
<dt><b></b></dt>
<dd> [2F7AD (3)]Nom de la matrice statistique
<dt><b></b></dt>
<dd> [2F7B0 (1)]Mode trace (0=off, 2=flow, 4=vars, 6=les deux)
<dt><b></b></dt>
<dd> [2F7B2 (8*2)]Mot de passe de LOCK (2 quartets par caractère)
<dt><b></b></dt>
<dd> [2F7C2 (34)]RES (contient le dernier résultat, même s'il est complexe)
<dt><b></b></dt>
<dd> [2F7E4 (4)]ERRN (numéro d'erreur)
<dt><b></b></dt>
<dd> [2F7E8 (4)]Numéro de ligne courant (d'un programme non en cours d'exécution)
<dt><b></b></dt>
<dd> [2F7EC (4)]ERRL numéro de la dernière ligne où une erreur à eu lieu
<dt><b></b></dt>
<dd> [2F870 (1)]Drapeau de fonction utilisateur multiligne (0= non multi-ligne)
<dt><b></b></dt>
<dd> [2F946 (2)]Vitesse de défilement horizontal (deuxième argument de DELAY)
<dt><b></b></dt>
<dd> [2F948 (2)]Vitesse de défilement vertical (premier argument de DELAY)
<dt><b></b></dt>
<dd> [2F94F (2)]Valeur de WIDTH
<dt><b></b></dt>
<dd> [2F956 (2)]Position courante de la tête d'impression
<dt><b></b></dt>
<dd> [2F958 (2)]Valeur de PWIDTH
<dt><b></b></dt>
<dd> [2F95A (1)]Longueur de la Chaîne ENDLINE (0, 1, 2 ou 3)
<dt><b></b></dt>
<dd> [2F95B (3*2)]Chaîne ENDLINE
<dt><b></b></dt>
<dd> [2F967 (2)]Longueur de la Chaîne de définition de la touche (2 quartets par
octet) <dt><b></b></dt>
<dd> [2F969 (1)]Type de touche
<dt><b></b></dt>
<dd> [2F96A (5)]Adresse de la Chaîne de définition de la touche
<dt><b></b></dt>
<dd> [2F96F (2)]Numéro du canal en cours d'accès
<dt><b></b></dt>
<dd> [2F976 (1)]Nombre d'entrées de la pile de commande -1
<dt><b></b></dt>
<dd> [2F977 (5)]Vitesse de l'horloge /6
<dt><b></b></dt>
<dd> [2F986 (1)]Drapeau d'IMAGE complexe (0= non complexe)
</DL>
Ceci devrait vous suffire pour quelques temps !
Notez qu'un programme peut récupérer tous les drapeaux utilisateurs d'un coup, par exemple :
U$=PEEK$("2F6E9",16)
puis utilisez les drapeaux comme vous le voulez et remettez gentiment en place la configuration d'origine par :
POKE "2F6E9",U$
Cet exemple s'applique aussi aux autres réglages, comme les trappes, largeurs (WIDTH) etc...
Il n'y a aucun moyen normal d'obtenir le nombre aléatoire courant. Chaque fois que vous utilisez RND, il en génère un nouveau. Un moyen de récupérer l'ancien est :
POKE "2F7C2","999"&PEEK$("2F701",12)&"0" @
R=RES
Ceci place la graine courante du nombre aléatoire dans le registre RES et, de là, le récupère dans la variable R.
Notez bien que ces nombres sont stockés dans le HP-71 à l'envers ! Par exemple, tapez PI et récupérez RES par :
PEEK$("2F7C2",16)
vous verrez PI à l'envers : 0009535629514130.
Les trois zéros de tête sont l'exposant et le 0 de la fin est le signe positif (9 serait le signe négatif). La morale est la suivante : Si vous voulez stocker quoi que ce soit dans la mémoire avec POKE, assurez-vous que c'est à l'envers
Ceci peut compliquer les choses.
Supposons que vous vouliez récupérer la vitesse d'horloge, la diviser par 2 et la remettre en mémoire. Vous devez la récupérer (PEEK$), retourner la Chaîne entière, la convertir en nombre avec HTD, la diviser par 2, la changer en hexadécimal par DTH$, retourner à nouveau la Chaîne et finalement la mettre en place avec POKE. Si vous avez REV$ en mémoire, vous pouvez faire :
POKE"2F977",REV$(DTH$(HTD(REV$(PEEK$
("2F977",5)))/2))
Mais vous devez avoir en mémoire un fichier LEX qui vous donne REV$. Par le fait, le résultat de l'opération ci-dessus est que tous les BEEP s'exécutent deux fois plus vite et sonnent deux fois plus haut !
L'usage le plus excitant que j'ai trouvé pour PEEK$ et POKE est la possibilité d'entrer des fichiers LEX à partir du clavier!
HP dit dans le manuel d'utilisation que cela ne peut être fait et dans d'autres documentations ils admettent que c'est possible. Voyez le programme appelé MAKELEX qui vous permet d'ajouter à votre machine REV$ et d'autres fonctions fantastiques en langage machine !