APPLICATIONSCOURS DE BIDOUILLAGE ★ TRUCAGES DU CODE BASIC ★

Trucages du Code Basic|Amstar&CPC)Applications Cours De Bidouillage

Voyons comment rendre invisibles certaines parties d'un programme, modifier des numéros de ligne, lister indéfiniment une même ligne...

Pour obtenir tous ces «effets spéciaux». Il faut modifier le code généré par l'Interpréteur BASIC au moyen de PEEK et de POKE.

Il va donc falloir voir comment est codée une valeur sur 2 octets et comment est codée une ligne BASIC pour pouvoir changer ce code.

CODAGE D'UNE VALEUR SUR 2 OCTETS

-  Pour éviter les conversions, nous allons raisonner directement en hexadécimal.
Toute valeur entière supérieure à 255 (&FF) doit être codée sur 2 octets. Ainsi la valeur &B12A est codée par les octets &B1 et &2A. On dit qu'il y a un octet de poids fort (Hl) et un octet de poids faible (Lo).
Dans un grand souci de simplicité, l'interpréteur BASIC code cette valeur sous la forme octet faible, octet fort. Ainsi, si cette valeur est stockée à l'adresse I, nous aurons : PEEK(I) = &2A et PEEKtJ+1) = '&B1. Pour récupérer cette valeur sous la forme décimale,

Il faut donc faire : PRiNT PEEK(1)+256*PEEK(I+1). il faut donc être très vigilant car on oublie souvent d'Inverser les deux octets et c'est !a source de nombreuses erreurs. Pour la valeur précédente. Il ne faut pas par exemple lire &2AB1.

Vous savez maintenant coder une valeur entière comprise entre 0 et 65535 sur 2 octets. Voyons donc comment est codée une ligne BASIC.

CODAGE D'UNE LIGNE BASIC

- L'Interpréteur BASIC code en effet les Instructions que nous lui donnons. Ces Instructions n'apparaissent donc pas en clair dans la mémoire. Les modifications que nous allons apporter ne devront affecter que les 2 premiers paramètres de la ligne : sa longueur et son numéro. Il va donc falloir repérer ces paramètres afin de ne pas dégrader le programme.

Pour cela, nous allons nous faire un «petit éditeur», permettant de visualiser le contenu de la mémoire :

INPUT a:FOR I=a TO HIMEM:PRINT I, PEEK(I), HEX$ (PEEK(I)), CHR$ (32 OR PEEK(I)), PEEK(i)+256 * PEEK(I + 1) :NEXT

Pour ne pas avoir à retaper cette ligne à chaque fols, vous pouvez la placer temporairement au début ou à la fin du programme à modifier et la lancer par RUN ou taper a$= "" et vous n'aurez alors qu'à faire ? a$ et la recopier avec la touche COPY pour pouvoir l'exécuter.

Pour utiliser cet éditeur, vous devrez rentrer l'adresse à partir de laquelle vous voulez lister la mémoire, et vous aurez sur chaque ligne : l'adresse, la valeur stockée à cette adresse, cette même valeur en hexadécimal, le code ASCII correspondant supérieur à 32, et la valeur codée sur l'octet courant et l'octet suivant, sous la forme poids faible, poids fort.

SI vous commencez à éditer le contenu de la mémoire à partir de l'adresse 0, vous verrez des codes, beaucoup de 0, mais rien qui ressemble à votre programme. En effet, le programme ne commence qu'à l'adresse 368 et occupe les adresses suivantes jusqu'à HIMEM.

Les deux premiers paramètres d'une ligne étant sa longueur et son numéro, vous pouvez vérifier que la valeur codée sur les, 2 octets 370 et 371 est bien le numéro de la première ligne de votre programme. Vous pouvez donc le modifier par POKE. Par exemple, pour que la ligne ait le numéro 4235, taper:

POKE 370,139:POKE 371,16


en effet, 16*256 + 139 = 4235.

Vous pouvez aussi faire PRINT HEX$ (4235). Vous obtenez alors : &BB10. Il vous suffit maintenant de taper : POKE 370,&8B:POKE 371,&10

Voyons plus précisément comment est codée une ligne :

Longueur de la ligne, codée sur 2 octets :

Lo
Hi

Numéro de ligne, codé aussi sur 2 octets :

Lo
Hi

Instructions BASIC codées
Signal de fin de ligne (octet 00) : 00

Commençons par le numéro de ligne : Nous l'avons vu, vous pouvez le changer à votre guise. Lors d'un GOTO, l'ordinateur cherche la première ligne ayant un numéro correspondant au paramètre. Néanmoins, si vous mettez 0 comme numéro à la première ligne, vous ne pourrez pas faire GOTO 0 ni lister cette ligne. En faisant POKE 370,0: POKE 371,0 vous rendez ainsi la première ligne de votre programme Invisible et vous ne pourrez l'exécuter que par un RUN,

La longueur de la ligne :

La longueur de la ligne est donc codée sur 2 octets au début de la ligne. SI vous ajoutez cette valeur à la valeur de l'adresse du premier octet sur lequel elle est codée, vous trouverez l'adresse du début de la ligne suivante. Cette valeur (la longueur de la ligne) sert lors de l'appel des Instructions : GOTO, GOSUB, RUN, EDIT, LIST... Pour exécuter ces fonctions, l'ordinateur part de la première ligne du programme et lit le début de chaque ligne jusqu'à ce que le numéro de la ligne soit égal à la valeur demandée, Par exemple, lors de l'éxecution de l'Instruction GOTO 3, l'AMS-TRAD part de la première ligne ; si celle-ci n'a pas le numéro 3, Il additionne la valeur de l'adresse où se trouve la longueur de cette ligne (368) et la longueur de cette ligne. Il trouve alors l'adresse du début de la ligne suivante et regarde si son numéro est égal au numéro demandé, et si ce n'est pas le cas. Il essaye pour la ligne suivante et ainsi de suite.

Si vous changez la longueur d'une ligne et que vous lui mettez comme valeur la valeur actuelle, augmentée de la longueur de la ligne suivante, vous «masquez» donc ta ligne suivante. Pour un GOTO, un GOSUB... et même un LIST, la ligne suivant la ligne modifiée sera donc inexistante. Voyons tout ceci sur un exemple. Tapez le petit programme suivant :

10 PRINT "Bonjour"
20 PRINT "Nous allons masquer cette ligne"
30 PRINT "Nous allons changer le numéro de cette ligne"
40 ' FIN DU PROGRAMME
50 ' BOUCLE LORS DU LISTING SUR LA LIGNE 40
60 PRINT "La ligne 60 peut tout de même être exécutée !"

Maintenant, rentrez le «petit éditeur» dans la variable a$.
Vous pouvez visualiser le programme.

Cherchons les adresses importantes :

Les premières sont les adresses de la longueur et du numéro de la première ligne : de 368 à 371, Nous obtenons :

La longueur de cette première ligne est donc de 16 octets et son numéro. 10.
La seconde ligne commence donc à l'adresse : 368+ 16 = 384 Nous lisons ;


Nous vérifions que le numéro de ligne correspond bien : 20. De même, la ligne suivante commence en 384 +40 = 424 et ainsi de suite...

- Pour masquer la ligne 20, Il nous suffit maintenant d'augmenter la longueur de la ligne 10 de la valeur de la longueur de ligne 20. Ces 2 longueurs étant 16 pour la ligne 10 et 40 pour la ligne 20, nous obtenons 16 + 40 = 56, Il suffit donc de faire POKE 368,56.

Vous pouvez vérifier que ligne 20 n'apparaît plus lors du listing, mais qu'elle est toujours exécutée.

- Changeons maintenant le numéro de la ligne 30 (codée en 426, 427). Remplaçons le par exemple par6128. 6128 étant supérieur à 256. nous devons passer par les hexadécimales. ? HEXS (6128) nous donne : 17F0. Pour placer cette valeur à la place choisie, nous devons donc faire : POKE 426,&F0;POKE 427,8:17 (Attention de ne pas oublier le & et de bien mettre la valeur sous la forme Lo.HI).

- Nous voulons maintenant faire boucler la ligne 50 sur la ligne 40. Pour cela, nous allons donner à la longueur de la ligne 50, l'opposé de la longueur de la ligne 40 (25), soit -25. Là encore, le nombre étant Inférieur à 0, nous devons passer par les hexadécimales. ? HEXS(25) donne: FFE7. I! faut donc faire POKE 502, 8;E7:POKE 503, &FF.

La fonction LIST nous donne bien maintenant :

10 PRINT "Bonjour"
6128 PRINT "Nous allons changer le numéro de cette ligne"
40 ' FIN DU PROGRAMME
50 ' BOUCLE LORS DU LISTING SUR LA LIGNE 40
40 ' FIN DU PROGRAMME.
50 ' BOUCLE LORS DU LISTING SUR LA LIGNE 40
40 ' FIN DU PROGRAMME.
50 ' BOUCLE LORS DU LISTING SUR LA LIGNE 40

QUELQUES MOTS SUR LE CODE DE LA LIGNE

-  Nous n'avons en effet parlé jusqu'ici que des paramètres de la ligne, mais pas du code en lui-même. Vous avez sûrement déjà remarqué que le programme n'est pas Inscrit en toutes lettres dans la mémoire. Il est codé, et n'y figurent «en clair» que les phrases entre guillemets et une partie des noms de variables. En effet, lorsque l'on entre une ligne BASIC, les «mots clés» sont remplacés par un «token». Le token est une espèce très répandue chez les Amstrabasicophiles. C'est un octet qui a la valeur du mot clé.

Pour ne pas confondre un token et un caractère ASCII standard faisant partie d'une variable, ou autre, on fait généralement précéder le token de l'octet &FF.
Le séparateur d'instruction, le «:» est codé par l'octet &01. Après les Instructions GOTO, GOSUB, RUN... on trouve le token &1E puis le numéro de la ligne cible, stocké sur 2 octets, de la même façon Lo, Hi.

Voilà, avec ces petits renseignements, vous allez pouvoir vous lancer dans les modifications de vos programmes BASIC... mais n'oubliez pas de garder une (ou deux) copie de sauvegarde car sinon, vous risquez de perdre... à jamais votre programme.

Sylvain VIEUJOT , AMSTAR CPC n°29

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