SansTitre

HP-Arena.com

 
HOME
News
Tests JEUX
Tests +
Programmation
Docs +
Team HP49G
Les Liens
Download
Decouvrez ! HPWorms
The VialleSOFT Network
Programmation
L'ASM 49

[-HP-49G : 1_Introduction a l'ASM - ] 
                         Un des principal avantage de la
                         HP est que la programmation
                         Assembleur est tres bien suivie
                         par rapport a TI ou Casio ou c'est
                         le BASIC qui prime.
                         BASIC : Facile + tres tres tres
                         lent
                         ASM : tres peu d'instructions mais
                         necessite des connaissances en
                         programmation + tres tres tres
                         rapide
                         Pourquoi l'assembleur est si
                         rapide ? Parce qu'il est tres
                         proche du processeur (le SATURN
                         sur Hp49) : il faut savoir que le
                         processeur lit vos programmes
                         avec des 0 et des 1 (notation
                         binaire) et que l'ASM est
                         justement tres proche des 0 et
                         des 1 alors que le BASIC rajoute
                         plein de 0 et de 1 inutiles qui
                         ralentissent votre programme car
                         il ne sait pas exactement ce que
                         vous voulez. 
                                                             Par exemple : pour afficher une ligne
                                                             : en BASIC : Line(x,y,xx,yx)
                                                             en ASM : ecrire un 1 dans la
                                                             memoire de l'ecran pour chaque
                                                             point de ma ligne
                                                             -> Resultat : vous avez ecrit
                                                             vous-meme votre ligne a l'ecran au
                                                             lieu d'ordonner a quelqu'un d'autre
                                                             de le faire. 
                         AVERTISSEMENT: J'utilise des notions que je n'expliquerais pas parce
                         qu'elles ont deja ete expliquees : la notation hexadecimale, les
                         boucles ..
                         vous pouvez vous referer a ces textes : 
                         Asm.zip de HpMd
                         manuelASM.zip de Sebastien Munch (BBossByll)
                         beaucoup d'autres traīnent sur le net 
                         La base de l'ASM sur HP, c'est en
                         gros:
                           les variables 20 bits : A, B, C
                           les pointeurs d'adresse : D0, D1
                           les pointeurs de memoire :
                         DAT0, DAT1
                         par exemple, si vous voulez ecrire
                         F (notation hexadecimale bien
                         sur) a l'adresse memoire 1A2EF :
                         D0=1A2EF ; stock l'adresse 1A2F
                         dans le pointeur
                         DAT0=F ; maintenant que le
                         pointeur pointe sur notre adresse
                         mem, on stock FF a cet
                         emplacement
                         En realite, ce programme ne
                         marcherait pas car vous ne
                         pouvez pas utiliser certaines
                         instructions, le vrai programme
                         serait :
                         D0=1A2EF
                         LC F ; je fait une transition en
                         stockant F dans C (LC:LoadC)
                         DAT0=C B ; je copie le contenu
                         de C (cad F) en 1A2EF 
                         ** Le B signifie 'Byte' et s'appelle
                         un champs (j'expliquerais les
                         champs au fur et a mesure) 
                                                             Vous allez me dire : C'est bien joli
                                                             tout ‚a mais ‚a sert a quoi d'ecrire
                                                             des 0 et des 1 dans la memoire de
                                                             ma HP ?
                                                             Et bien en fait, tous les jeux de
                                                             votre HP peuvent etre resumes a des
                                                             affichages de pixels donc a des
                                                             ecritures dans la memoire de l'ecran
                                                             Bien sur, si vous voulez afficher une
                                                             ligne, vous n'allez pas ecrire 100 fois
                                                             'afficher pixel' mais faire un boucle.
                                                             XsFl00d - 30/10/99
                                                             Pour tout commentaire etc ...
                                                             n'hesitez pas a ecrire :
                                                             p4x@hotmail.com 

[-HP-49G : 2_Petit programme de base - ] 
                                                      "GOSBVL
                                                      SAVPTR
                                                      GOSBVL
                                                      GETPTRLOOP
                                                      @
                                                      "
                         Tout d'abord, ce programme doit etre compile avec MASD et EXTABLE
                         installe sur votre HP: MASD est fourni avec la rom 1.14-2 et EXTABLE
                         est telechargeable ici 
                         pour compiler ce programme, vous devez mettre la source sur la pile et
                         taper : 257 ATTACH [enter] ASM [enter]
                         et si la compilation a marche vous obtenez 'Code' sur la pile, vous
                         devez alors taper : EVAL
                         Ce qui a lance votre programme. Et vous constatez que rien ne s'est
                         passe ! Maintenant, regardez les explications:
                         GOSBVL : instruction qui permet de lancer un sous-programme.
                         SAVPTR : grāce a extable, nous avons pu taper SAVPTR au lieu de
                         0679B. 0679B est l'adresse ou est situe le sous programme. Il est
                         situe en ROM (a nous evite d'avoir a le reecrire) et il fait les
                         sauvegardes qui permettrons de retourner a l'affichage normal de la HP
                         avec :
                         GETPTRLOOP : mme genre que SAVPTR sauf que celui-ci nous permet
                         de restaurer ce que nous avons sauvegarde tout a l'heure (adresse rom
                         : 05143). Essayez de compiler le prog sans GOSBVL GETPTRLOOP : 
                         ca va faire un beau bordel !(tapez ON-C pour rebooter)
                         @ : tout programme compile avec MASD doit se terminer avec ce
                         symbole
                         " : le programme doit se trouver entre guillemets (car c'est un 'string') 
                         Il est normal que ce programme ne fasse rien : il se lance puis s'arrete.
                         Vous avez donc compris que si je veux compliquer, il suffit de rajouter
                         des instructions entre GOSBVL SAVPTR et GOSBVL GETPTRLOOP.
                         Si quelque chose vous semble obscur, ecrivez-moi. 
                         Recuperez les sources sans les commentaires : ex1
                                                             XsFl00d - 30/10/99
                                                             Pour tout commentaire etc ...
                                                             n'hesitez pas a ecrire :
                                                             p4x@hotmail.com 
[-HP-49G : 3_Programme plus complet - ] 
                         J'ai subdivise ce programme en plusieurs parties pour pouvoir en
                         reutiliser certaines dans un futur prog. 
                         source principale:
                         "GOSBVL SAVPTR; fait une sauvegarde du systeme en cours
                         'SCREEN ; cf. source suivante : permet de mettre ce qui se trouve dans
                         'SCREEN' a la place de cette instruction
                         *Boucle; je cree un label
                         GOTO Boucle ; je fais une boucle sans fin pour que vous puissiez voir
                         le resultat (sinon, ce serait trop rapide) !
                         'UNSCREEN; cf. plus bas
                         GOSBVL GETPTRLOOP ; restaure les sauvegardes du systeme
                         @" ; fin de la source. 
                         SCREEN:
                         "LC 881 ; met 880 (=2176 en decimal -> la taille de l'ecran en pixels)
                         dans C + 1 au cas ou l'adresse soit impaire (cf. plus bas)
                         GOSBVL MAKE$N ; cet appel en rom permet de reserver un espace 
pour
                         l'ecran dans la memoire de la HP49 (adresse rom : 05B7D)
                         CD0EX ; D0 contient maintenant l'adresse de l'ecran que je viens de
                         reserver. et j'echange les contenus de C et de D0. Donc maintenant :
                         D0=880 et C contient l'adresse de l'ecran
                         ?CBIT=0 0 ; si le 1er bit de C est a 0 (donc si l'adresse est paire) -->
                         cf. plus bas pour voir pkoi cette adresse doit etre paire
                         GOYES Paire ; alors je saute au label 'Paire' (un label commence par
                         *)
                         C=C+1 A ; sinon, si l'adresse est impaire, je lui ajoute 1 pour la rendre
                         paire
                         *Paire ; voila mon label. maintenant que je suis sur que l'adresse est
                         paire, je peux continuer ..
                         D0=00120 ; je charge l'adresse 00120 dans D0 (c'est la que je dois
                         ecrire l'adresse de mon ecran pour que la HP sache que c'est cette
                         portion de memoire et pas une autre qu'elle doit afficher)
                         DAT0=C A ; j'utilise DAT0 pour ecrire a l'adresse pointee par D0
                         l'adresse de mon ecran a moi. 'A' signifie que cette adresse comporte 5
                         chiffres (toutes les adresses sont de 5 chiffres : ex : 039BE; 00120;
                         0679B; l'adresse de mon ecran etc.)
                         D0=C ; maintenant D0 pointe sur mon ecran : je vais enfin pouvoir
                         ecrire des pixels!
                         B=C A ; je fais une sauvegarde de l'adresse de l'ecran en B pour
                         pouvoir la reutiliser dans mon prog principal. 'A' car l'adresse a 5
                         chiffres!
                         LC 87 ; la, je mets 87 (135 en decimal) dans C. J'ai dans l'idee
                         d'utiliser C comme compteur ..
                         A=0 W ; je mets 16 zeros dans A car 'W' correspond a 16 chiffres
                         *Efface ; je mets un label ici car je vais devoir repeter les expressions
                         qui suivent plusieurs fois
                         DAT0=A W ; D0 contient l'adresse de mon ecran donc DAT0=A W ecris
                         16 zeros dans l'ecran (cad eteint les pixels) (W : 16 chiffres!)
                         D0=D0+16 ; j'ajoute 16 a l'adresse de l'ecran pour pouvoir effacer les
                         16 pixels suivants
                         C=C-1 B ; je decremente mon compteur car l'ecran doit etre efface en
                         16*136 fois. 16*136=2176 : c'est exactement la taille de l'ecran en
                         quartets (portions de 4 bits)! 
                         GONC Efface ; GONC=GoifNotCarry : en gros ca veut dire que je dois
                         continuer a eteindre des pixels tant que C est different de zero (C est
                         utilise comme compteur et je lui enleve 1 a chaque tour)
                         D0=00128 ; adresse ou on peut ecrire la taille de la barre de menu du
                         bas
                         LC 3F ; 3F correspond a un menu de taille 0 donc invisible ! La taille
                         normale est 37
                         DAT0=C B ; j'ecris la nouvelle taille en 00128. 'B' correspond a un
                         nombre de 2 chiffres (B=Byte=octet=8bits=2chiffres hexadecimaux)
                         @" ; la source de ce fichier est finie 
                         Quelques precisions :
                         ** Un ecran est une portion de memoire qui ne peut commencer a une
                         adresse impaire, d'ou le test avant de donner a la HP mon adresse
                         d'ecran.
                         ** L'ecran est divise en 2 parties : le menu et l'ecran lui-mme. Mme
                         apres avoir efface tout l'ecran il faut encore que je baisse le menu pour
                         avoir un ecran totalement vierge. Essayez le mme programme en
                         changeant la taille du menu entre 37 (taille normale) et 3F (taille 0).
                         ** vous avez peut-etre remarque que 87 = 135 en decimal et que
                         bizarrement, je vous dit que la boucle va s'executer 136 fois.. C'est d
                         au fait que mme lorsque C=0, la boucle va s'executer puisque le test
                         sur C n'a lieu qu'a la fin : j'ai donc : 135+1=136 
                         UNSCREEN:
                         "D0=8068D ; A cette adresse, je peux trouver l'emplacement de l'ecran
                         normal de la HP49, cad avant que mon programme ait change l'adresse
                         en 00120. Mais alors, me direz-vous, on aurait pu lire l'adresse stockee
                         en 00120 avant de la changer au debut, puis la restaurer ! Non ! Car
                         00120 n'est accessible qu'en ecriture, vous n'y trouverez pas l'adresse
                         de votre ecran.
                         C=DAT0 A ; je recupere l'adresse de l'ecran normal.
                         D0=00120 ; je pointe en 00120 
                         DAT0=C A ; et j'ecris l'adresse recuperee en 8068D pour dire a la HP
                         d'afficher l'ecran habituel
                         D0=00128 ; adresse de la hauteur du menu (accessible aussi qu'en
                         ecriture)
                         LC 37 ; je mets la taille habituelle du menu dans C
                         DAT0=C B ; et je mets la nouvelle taille en 00128
                         @" 
                         ** Vous n'avez plus qu'a compiler et lancer tout ‚a comme indique
                         dans la section 'programme de base' ou regarder dans le fichier ABOUT
                         (rom 1.14-2 et extable necessaires).
                         ** Ha oui !! Pour arreter le programme: faites ON-C pour redemarrer la
                         HP49. Sinon, voici un petit exercice pour voir si vous avez compris :
                         Au lieu de faire une boucle infinie, vous allez initialiser un compteur
                         avant le label et dans la boucle, vous decrementerez le compteur et
                         verifierez si le compteur est 0. Pour cela, vous utiliserez une technique
                         identique celle de l'effa‚able de l'ecran (conseil : initialisez le compteur
                         AAAAA et utilisez un champs A pour la decrementation).
                         ** Vous avez peut etre note que dans le programme principal, les
                         instructions 'UNSCREEN et GOSBVL GETPTRLOOP ne servent rien
                         puisque je vous oblige le quitter en appuyant sur ON-C donc ces
                         instructions ne sont pas executees (on quitte pendant la boucle).. Si
                         vous enlevez la boucle infinie et la remplacez avec l'exercice ci-dessus,
                         vous pourrez voir leur utilite.
                                              XsFl00d - 30/10/99
                                              Pour tout commentaire etc. n'hesitez pas a ecrire
                                              : p4x@hotmail.com 
                                                               
[-HP-49G : 4_Affichage d'un grob - ] 
 Pour compiler ce programme, vous aurez besoin de SCREEN et UNSCREEN vus dans 
le programme precedent.
 Il vous permet d'afficher un grob que vous aurez stocke dans le fichier GROB1 
(precisions sous la source) 
 source
 principale: 
             "GOSBVL SAVPTR ; fait une sauvegarde du systeme en cours
             'SCREEN ; inclus le fichier SCREEN (creation d'un ecran et mise zero de celui-
ci)
             C=B A ; recuperation de l'adresse de l'ecran (stockee en B par SCREEN)
             D0=C ; D0 pointe sur l'ecran
             C=PC ; PC (ou Program Counter) pointe sur la prochaine instruction a executer
             GOINA grob1 ; GOINA renvoie la difference entre l'emplacement de 
l'instruction et le label
             A=A+C A ; resultat : avec mon addition, je recupere l'adresse de mon image 
(GROB=GRaphicOBject) car
             adresse_image = l'emplacement_actuel + distance_entre 
l'image_et_emplacement_actuel
             D1=A ; donc D1 contient l'adresse de l'image
             LC 87F ; taille de l'ecran (et de l'image) en quartets 87Fh+1=880h=2176 et 
2176*4=8704 (un quartet = 4
             pixels)
             *Recop ; label qui va me permettre de recopier mon dessin par quartets (cad 4 
pixels par boucle)
             A=DAT1 P ; A contient 4 pixels du dessin (P = Pointeur de registre : couvre 1 
quartet)
             DAT0=A P ; recopie les 4 pixels sur l'ecran
             D0=D0+1 ; je passe au quartet suivant sur l'ecran
             D1=D1+1 ; idem mais pour l'image
             C=C-1 X ; decrementation du compteur (champs X : 3 quartets)
             GONC Recop ; recommence jusqu'a ce que l'image soit recopiee totalement 
(apres 880 fois) 
             LC AAAAA ; charge un compteur (pour que le programme s'arrete apres 
quelques secondes)
             *Boucle ; je cree un label
             C=C-1 A ; decrementation du compteur
             GONC Boucle ; si le compteur n'est pas zero, je reboucle, sinon, le programme 
s'arrete
             'UNSCREEN ; inclus UNSCREEN (restauration de l'ecran original de la HP)
             GOSBVL GETPTRLOOP ; restaure les sauvegardes du systeme
             *grob1 ; ce label permet de faire GOINA sur l'adresse de l'image
             'GROB1 ; mets les donnees de l'image ici (cf GROB1)
             @" ; fin de la source 
 ** PC (ou program counter) contient l'adresse de la prochaine instruction a executer. Si 
vous changez sa valeur, ‚a
 revient a faire un saut.
 ** Au cas ou vous n'ayez pas tres bien suivi l'histoire des quartets : 4 bits = 1 quartets ; 8 
bits = 2 quartets = 1
 octet (1 byte en anglais)
 ** Le champs P (ou pointeur de registre ) est utilise pour 1 quartet. 
 ** Le champs A (Adresse) est utilise pour 5 quartets : sur HP, les adresses sont de 5 
quartets (20 bits)
 ** Le champs B (Byte) est utilise pour 2 quartets (1 octet) : il peut tre utilise pour des 
compteurs a 2 chiffres
 hexadecimaux (FF par exemple)
 ** Le champs W (Wide) est utilise pour 16 quartets (64 bits) : c'est le champs le plus 
grand et il generalement utilise
 pour des copies de memoire (j'aurai pu l'utiliser pour recopier le dessin -> tiens ! j'y 
pense ! Pour le prochain cours,
 vous allez recopier le dessin en utilisant le champs W :)
 ** Le champs X (eXposant) est utilise pour 3 quartets.
 ** Si vous avez vraiment bien compris, je peux vous compliquer le truc : la position de 
P est variable et le champs
 WP depend de sa position. Par exemple : si P=A, alors P couvre le 10eme quartet et WP 
couvre les quartets 0 a 10
 (donc 11 quartets).
 ** Il existe d'autres champs que j'expliquerais quand on en aura besoin.
 ** Vous avez pu remarquer que j'utilise non plus une boucle infinie mais une boucle qui 
dure quelques secondes :
 c'est la reponse de l'exercice du cours precedent. 
 GROB1: 
             
"$000000000000000000000000000000000000000000000000000000000000000000000
000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000
000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000
000000000000000
00000000000000000200000010000000000000000EFFF30000040000080000000000000
000020000000004
00000400000000000000000200000000080000040000000000000000020000000000100
0020000000000000
00002000000000020000100000000000000000200000000002000800000000000000000
0200000000004000
40000000000000000002000000000080004000000000000000000200000000000100200
0000000000000000
2000000000001001EF34008F00000000002000000000002080200400603000FFF700EF
FF70000000404020
04001040000404000000400000004040200408008083040C10000040000000802020040
800806C04001000
004000000001102004040001280400300000400000000A00E1040400011014002000004
000000006002004
0400011014002000004000000004002004040001101400200000400000000A002004040
001280400200000
40000000090020040800806C04002000004000000080102004080080830400200000400
000004020200400
104000040020000040000000404020040060300004003000004000000020402004008F0
000040810000040
0000001080000CF30000000408000000400000080001000000000000EFFF0000004000
000400020000000
00000000000000040000004000200000000000000000000004000000200040000000000
000000000000400
00001000800000000000000000000004000008000080000000000000000000000400000
400000100000000
00000000000004000004000002000000000000000000000400000200000400000000000
000000000040000
010000040000000000000000000004000000000008000000000008FFFFFFFFF7000000
000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000
000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000
000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000
000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000
000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000
000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000
000000000000000
             000000000000000000000000000
             @"
 ** Un GROB est en fait une suite de chiffres hexadecimaux (donc de quartets, donc de 4 
pixels). Par exemple 'F' en
 binaire , s'ecrit : 1111 donc F dans le grob va se traduire par une ligne de 4 pixels sur 
mon dessin.
 ** Si vous voulez mettre vos propres images, vous devez la dessiner sur la HP, puis la 
stocker dans un grob .
 Seulement vous n'avez pas acces a la suite de chiffres donc vous devez mettre : "" dans 
le niveaux 2 de la pile et
 votre grob dans le niveaux 1 puis faire + . Ca vous donne votre grob mais avec un 
prologue qui va ressembler a ‚a :
 GROB 131 64 vous n'avez qu'a le virer pour obtenir ce dont vous avez besoin. 
              XsFl00d - 30/10/99
             Pour tout commentaire etc ... n'hesitez pas a ecrire : p4x@hotmail.com 
[-HP-49G : 5_Gestion des touches - ] 
       attention : desormais je vais utiliser la syntaxe MASD bien pratique.. Il vous faut 
donc une ROM recente
       et EXTABLE pour compiler les programmes
       source principale: 
                                    "
                                    SAVE ; MASD le remplace par GOSBVL SAVPTR
                                    LC 3F D0=00128 DAT0=C.B ; Baisse le menu
                                    *Touches
                                    LC 001 GOSBVL OUTCINRTN ; la valeur 001 correspond aux 
                                    tests des touches
                                    de la premiere colonne du clavier a droite (pareil pour ENTER, 
                                    TAN etc ..) -> cf
                                    la table des correspondances
                                    ?CBIT=1 6 GOYES Exit ; si le 6eme bit de C est a 1, alors c'est 
                                    que DROP a
                                    ete appuyee, on va donc arreter le programme
                                    GOTO Touches ; Si DROP n'a pas ete appuyee on continue a 
                                     tester les touches
                                    *Exit
                                    LC 37 D0=00128 DAT0=C.B ; Je remonte le menu
                                    GOSBVL Flush ; Je vide le buffer du clavier
                                    LOADRPL ; et je quitte le programmme (MASD le remplace par 
                                     GOSBVL
                                    GETPTRLOOP)
                                    @" ; fin de la source 
       ** pour la detection des touches, le systeme agit ainsi : il va faire un OUT=001, c'est 
a dire envoyer du
       courant sur la colonne de droite du clavier. Quand une touche est appuyee, il se cree 
une sorte de cours
       circuit detecte par C=IN . Ainsi, suivant les valeurs de C, on pourra determiner 
quelle touche a ete tapee.
       ** A la fin, on vide le buffer du clavier car quand vous appuyez sur plusieurs 
touches les unes a la suite
       des autres, le systeme cree une sorte de liste d'attente qui permettra aux touches 
d'etre traitees dans le
       bon ordre . Pour eviter qu'a la sortie du programme, le systeme veuille s'occuper des 
touches appuyees
       durant son execution, on vide cette liste d'attente.

       Table de correspondance
       des touches :
       (en partie recuperee dans
       smhp49 de SunHP)
                                        TOUCHES
                                                         OUT (LC
                                                            ???)
                                                                                      IN (CBIT=1 ?)
                                         [ENTER]
                                                            001
                                                                                            0
                                           [+]
                                                            001
                                                                                            1
                                            [-]
                                                            001
                                                                                            2
                                            [*]
                                                            001
                                                                                            3
                                            [/]
                                                            001
                                                                                            4
                                           [U]
                                                            001
                                                                                            5
                                         [DROP]
                                                            001
                                                                                            6
                                            [L]
                                                            001
                                                                                            7
                                         [SPACE]
                                                            002
                                                                                            0
                                            [3]
                                                            002
                                                                                            1
                                            [6]
                                                            002
                                                                                            2
                                            [9]
                                                            002
                                                                                            3
                                            [Y]
                                                            002
                                                                                            4
                                            [T]
                                                            002
                                                                                            5
                                            [P]
                                                            002
                                                                                            6
                                            [K]
                                                            002
                                                                                            7
                                            [.]
                                                            004
                                                                                            0
                                            [2]
                                                            004
                                                                                            1
                                            [5]
                                                            004
                                                                                            2
                                            [8]
                                                            004
                                                                                            3
                                            [X]
                                                            004
                                                                                            4
                                            [S]
                                                            004
                                                                                            5
                                           [O]
                                                            004
                                                                                            6
                                            [J]
                                                            004
                                                                                            7
                                            [0]
                                                            008
                                                                                            0
                                            [1]
                                                            008
                                                                                            1
                                            [4]
                                                            008
                                                                                            2
                                            [7]
                                                            008
                                                                                            3
                                           [W]
                                                            008
                                                                                            4
                                            [R]
                                                            008
                                                                                            5
                                           [N]
                                                            008
                                                                                            6
                                            [I]
                                                            008
                                                                                            7
                                            [V]
                                                            010
                                                                                            4
                                           [Q]
                                                            010
                                                                                            5
                                           [M]
                                                            010
                                                                                            6
                                           [H]
                                                            010
                                                                                            7
                                           [G]
                                                            020
                                                                                            7
                                         [ALPHA]
                                                            080
                                                                                            3
                                       [Left Shift]
                                                            080
                                                                                            2
                                       [Right Shift]
                                                            080
                                                                                            1
                                         DROITE
                                                            040
                                                                                            0
                                           BAS
                                                            040
                                                                                            1
                                         GAUCHE
                                                            040
                                                                                            2
                                          HAUT
                                                            040
                                                                                            3

                                    XsFl00d - 21/12/99
                                    Pour tout commentaire etc ... n'hesitez pas a ecrire : 
p4x@hotmail.com 
                                                               
[-HP-49G : 6_Petit jeu - ] 
       Bon, il est temps de compliquer un peu les choses.
       Tout d'abord, le programme ne va pas etre ecrit de maniere lineaire mais avec des 
sous-programmes, cad
       des petits bouts de codes que l'on peut appeler dans la boucle principale.
       Ensuite, la syntaxe MASD nous permet de nous rapprocher du C avec des structures 
IF ELSE etc ... ce qui
       est bien pratique..
       Et maintenant, que va faire ce petit jeu ?
         Deux vaisseaux s'affichent a l'ecran. Chaque joueur peut le deplacer dans n'importe 
quel sens avec ses
       touches. On designe un joueur qui doit toucher le vaisseau de l'autre, si il y a 
collision, alors le jeu
       s'arrete
       Comment va-t-on programmer ‚a ?
       1 j'initialise des constantes (par exemple chaque occurence a 00128 sera remplacee 
par "setmenu")
       2 je sauvegarde le systeme et je fais differentes tāches qui lui sont relatives
       3 je recupere un ecran et sauvegarde son adresse
       4 je sauvegarde l'adresse de l'image des vaisseau (du sprite)
       5 je sauvegarde les coordonnees initiales des 2 vaisseaux
       6 j'efface l'ecran, baisse le menu et affiche l'ecran
       7 j'execute ma boucle principale jusqu'a ce que la touche DROP soit appuyee. Dans 
la boucle :
          1 j'affiche les deux sprites aux coordonnees sauvegardees
          2 je detecte si des touches ont ete appuyees (et je mets a jour les coordonnees si les 
touches de
       direction ont ete detectees)
          3 je detecte si il y a eu collision entre les 2 vaisseaux. si oui, je passe en 8, sinon, je 
continue la
       boucle.
          4 je met une petite boucle d'attente car l'ASM est tres rapide.
          5 j'efface mes deux vaisseaux pour les reafficher a un autre endroit. Puis je 
retourne en 7-1 pour les
       afficher aux nouvelles coordonnees
       8 Je reaffiche l'ecran normal de la calto et je rends la main au systeme
                          1 
                                               "
                                               CP=822B2 ; en 822B2, il y a de l'espace libre ou je peux 
stocker
                                               mes constantes
                                               DCCP 5 ECRAN ; je reserve 5 quartets a cet endroit pour y 
mettre
                                               l'adresse de mon ecran. DCCP est genial car il fait
                                               automatiquement 822B2+5
                                               DCCP 5 GROB ; en 822B7 : je reserve 5 quartets pour 
stocker
                                               l'adresse de mon GROB
                                               DCCP 2 X1 ; en 822BC : 2 quartets pour l'abscisse du 1er 
vaisseau
                                               DCCP 2 Y1 ; en 822BE : "              "         l'ordonnee  "              
"
                                               DCCP 2 X2 ; en 822C0 : "              "        l'abscisse du 2eme
                                               vaisseau
                                               DCCP 2 Y2 ; en 822C2 :  "             "       l'ordonnee    "              
"
                                               DC setecran 00120 ; la je dis a MASD qu'a chaque fois qu'il
                                               rencontre "setecran", il le remplace par l'adresse 00120
                                               DC setmenu 00128 ; meme chose pour l'adresse de la taille 
du
                                               menu
                                               ST=1 0 ; Program Status Bit. Il y en a 16. Seuls les 11 
premiers
                                               sont utilisables par le coder. Ils representent un etat (1 : 
TRUE ;0 :
                                               FALSE). Ici, j'utilise le ST 0 et je le met a 1. Je vais 
l'utiliser pour
                                               savoir si mes sprites ont change de position depuis la 
derniere
                                               Boucle. (si j'avais voulu utiliser le ST 5, j'aurai ecrit : ST=1 
5 ). Je
                                               le met initialement a 1 pour la premiere execution de la 
boucle.
       ** un petit schema pour mieux comprendre l'instruction DCCP :
           |----ECRAN----|----GROB----|----X1-----|----Y1----|---X2-----|----Y2---|
          822B2<--5-->822B7<--5-->822BC<-2->822BE<-2->822C0<-2->822C2<-2-
>822C3
                          2
                                               SAVE ; GOSBVL SAVPTR
                                               INTOFF2 ; ha ! Les fameuses interruptions ! Je vais ici 
simplement
                                               vous dire que je les desactive et vous expliquer plus bas ce 
que
                                               c'est.
                                               ST=0 15 ; un des Status bit que le programmeur ne peut pas
                                               utiliser. Celui-ci est utilise par le systeme pour savoir s'il 
doit gerer
                                               les interruptions clavier.
       ** Les interruptions sont en fait les evenements que doit gerer la HP comme l'appui 
d'une touche, la mise
       a jour de l'horloge, le refresh de l'ecran.
       Pour tester, essayez de compiler ce programme sans les 2 instructions qui desactivent 
les interruptions et
       essayez de taper ON-C, votre calto va rebooter. Maintenant, essayez la meme chose 
mais en ayant
       desactive les inter. , la calto ne bouge pas d'un poil.
       Il ne faudra surtout pas oublier de reactiver les interruptions a la fin du prog, donc 
faites-y moi penser.
       note : vous entendrez souvent les programmeurs poser la question : "Comment je fais 
pour detourner les
       interruptions ?". Je fais parti de ceux-la donc des que je sais faire, je vous explique :). 
Mais en gros, ‚a
       correspondrait a dire vous-meme quand l'ecran doit se raffraichir ou a augmenter les 
secondes de
       l'horloge vous-memes donc vous voyez comme c'est puissant !
                          3
                                               LC 00881 ; je veux un ecran de 880 quartets (881 au cas ou
                                               l'adresse de depart soit impaire)
                                               RES.STR ; MASD le remplace par GOSBVL MAKE$N
                                               LA(5)ECRAN ; je mets en A l'endroit ou je vais stocker 
l'adr de
                                               l'ecran (822B2)
                                               AD0EX ; j'echange les contenus de A et de D0. Maintenant,
                                               D0=ECRAN et A=adr de l'ecran
                                               ?ABIT=0.0 {A+1.A } ; voila un exemple de syntaxe propre 
a MASD
                                               (avec les accolades). Ici, si le premier bit (bit n°0) de A est 
a 0,
                                               c'est que l'adresse est paire (souvenez-vous, on est en 
binaire).
                                               SINON, alors executer ce qui est entre {}
                                               DAT0=A.A ; j'ecris en 822B2 l'adresse (maintenant 
forcement paire)
                                               de notre ecran sur un champs A.
         
                          4
                                               A=PC ; PC (program counter) contient l'adr de la prochaine
                                               instruction a executer
                                               GOINC Grob ; GOINC met en C le nombre de quartets qui 
le separe
                                               du label "Grob" (‚a nous permet de mettre les donnees du 
grob a la
                                               fin de la source a l'aide d'un label)
                                               A=A+C.A ; en additionnant les 2 valeurs, j'obtiens l'adresse 
du
                                               GROB
                                               D0=(5)GROB ; je la met en 822B7
                                               DAT0=A.A ; j'ecris l'adresse avec un champs A
         
                          5
                                               D0=(2)X1 LA 0A DAT0=A.B ; j'ecris l'abscisse du premier 
sprite sur
                                               2 quartets (champs B) en 822BC
                                               D0=(2)Y1 DAT0=A.B ; j'ecris son ordonnee. 
Sprite1(0A;0A)
                                               D0=(2)X2 LA 1A DAT0=A.B ; les coordonnees du 2e 
vaisseau
                                               D0=(2)Y2 DAT0=A.B ; Sprite2(1A;1A)
         
                          6
                                               %Efface l'ecran ; un commentaire en style MASD
                                               A=0.W D1=(5)ECRAN C=DAT1.A D0=C LC 87 ; D0 : adr 
ecran
                                               {DAT0=A.W D0+16 C-1.B UPNC} ; Encore une structure 
MASD.
                                               UPNC correspond a GONC (cf exemples precedents), cad : 
tant que
                                               C est plus grand ou egal a zero, j'execute ce qui est entre
                                               accolades.
                                               %Baisse le menu
                                               D0=00128 LC 3F DAT0=C.B ; vous etes cense savoir faire 
(sinon cf
                                               ex precedents)
                                               %Affiche Ecran
                                               D0=(2)setecran D1=(5)ECRAN C=DAT1.A DAT0=C.A ; 
lit la
                                               sauvegarde de l'adr de l'ecran pour l'ecrire en 00120
         
                          7
                                               *Main
                                               ?ST=0 0 SKIPYES ; est-ce que mes sprites ont change de 
place ? Si
                                               oui, alors mon ST est a 1 et je dois executer ce qui est entres
                                               accolades, sinon, je passe directement a la suite
                                               {GOSUBL Sprite1 ; affichage du premier sprite aux 
nouvelles
                                               coordonnees
                                               GOSUBL Sprite2 } ; id pour le second sprite
                                               GOSUBL Touches ; test des touches et mise a jour des
                                               coordonnees des vaisseaux
                                               GOSUBL Collision ; detecte si il y a eu collision
                                               GOSUBL Wait ; une petite boucle d'attente pour ne pas que 
les
                                               sprites se redessinent trop vite
                                               ?ST=0 0 SKIPYES ; si les coordonnees n'ont pas bouge, il 
n'y a pas
                                               de raison d'effacer l'ecran puisque je ne vais pas redessiner 
mes
                                               sprites
                                               {GOSUBL Clrscr } ; efface l'ecran
                                               GOTO Main ; ma boucle principale s'arrete la, je la relance.
         
                         7-1
                                               *Sprite1
                                               D0=(5)ECRAN A=DAT0.A ; A : adr ecran
                                               D0=(5)X1 C=0.A C=DAT0.B A=A+C.A D0=A ; C : 
abscisse (C est
                                               mis a 0 sur A car on ne le charge que sur un champs B et on 
fait un
                                               addition sur un champs A, il faut donc etre sūr que les 3 
quartets
                                               de forte valeur soient a 0 car leur valeur est indeterminee, 
on aura
                                               donc : 000X1 au lieu de ???X1). Pour que D0 pointe sur 
l'abscisse
                                               du vaisseau, je dois additionner l'abscisse et l'adresse de 
debut de
                                               l'ecran (comme si on faisait un changement de repere) (cf
                                               diagramme de l'ecran)
                                               D1=(5)Y1 C=DAT1.B {D0+34 C-1.B UPNC} D0-34; C : 
ordonnee.
                                               j'incremente D0 d'une ligne autant de fois que son ordonnee 
(cf
                                               schema). D0-34 car cette boucle s'execute C+1 fois (j'aurai 
pu
                                               ecrire C-1.B C=DAT1.B et ensuite executer la boucle sans 
faire la
                                               soustraction a la fin).
                                               D1=(5)GROB C=DAT1.A D1=C LC 07 {A=DAT1.B 
D1+2 DAT0=A.B
                                               D0+34 C-1.B UPNC} ; Recopie le GROB en commen‚ant a 
l'adresse
                                               pointee par D0 qui correspond aux coordonnees de Sprite1 
(grob de
                                               8 lignes de 8 pixels (2 quartets) donc je copie 2 quartets 
avant de
                                               passer a la ligne suivante)
                                               RTN ; Retourne dans la boucle principale
                                               *Sprite2 ; Fonctionnement identique a Sprite1
                                               D0=(5)ECRAN A=DAT0.A
                                               D0=(5)X2 C=0.A C=DAT0.B A=A+C.A D0=A
                                               D1=(5)Y2 C=DAT1.B {D0+34 C-1.B UPNC} D0-34
                                               D1=(5)GROB C=DAT1.A D1=C LC 07 {A=DAT1.B 
D1+2 DAT0=A.B
                                               D0+34 C-1.B UPNC}
                                               RTN ; retourne dans la boucle principale
         

         
                         7-2
                                               *Touches
                                               ST=0 0 ; je mets ST 0 a zero puisque son etat est 
susceptible
                                               d'etre modifie pendant cette routine.
                                               %Player 1
                                               LC 040 GOSBVL 0020F ?CBIT=0 3 SKIPYES ; touche 
HAUT. SKIPYES
                                               en syntaxe MASD permet d'ignorer ce qu'il y a entre 
accolades si la
                                               touche n'a pas ete pressee
                                               {D1=(5)Y1 A=DAT1.B ?A=0.B EXIT A-1.B DAT1=A.B 
ST=1 0} ; si la
                                               touche a ete appuyee, je reduit l'ordonnee et je mets ST 0 a 
1 pour
                                               que le sprite soit affiche a sa nouvelle position par Sprite1. 
En
                                               plus, je detecte si le sprite est tout en haut de l'ecran 
(ordonnee
                                               de 0), si oui, je passe a la touche suivante sans toucher a ses
                                               coordonnees (EXIT).
                                               ?CBIT=0 1 SKIPYES ;touche BAS
                                               {D1=(5)Y1 A=DAT1.B B=A.B LA 37 ?A=B.B EXIT 
A=B.B A+1.B
                                               DAT1=A.B ST=1 0} ; augmente l'ordonnee en regardant si 
il est
                                               tout en bas (ordonnee de 37 et ?A=37.B n'existe pas donc je
                                               transite par le registre B).
                                               ?CBIT=0 2 SKIPYES ; touche GAUCHE
                                               {D1=(5)X1 A=DAT1.B ?A=0.B EXIT A-1.B DAT1=A.B 
ST=1 0} ; si
                                               pas a gauche alors je reduit son abscisse
                                               ?CBIT=0 0 SKIPYES ; touche DROITE
                                               {D1=(5)X1 A=DAT1.B B=A.B LA 1F ?A=B.B EXIT 
A=B.B A+1.B
                                               DAT1=A.B ST=1 0} ;si pas a droite (abscisse 1F), alors 
augmente
                                               son abscisse
                                               %Player 2 ; cf Player1 mais avec des touches differentes
                                               LC 008 GOSBVL 0020F ?CBIT=0 0 SKIPYES ; touche 0
                                               {D1=(5)Y2 A=DAT1.B B=A.B LA 37 ?A=B.B EXIT 
A=B.B A+1.B
                                               DAT1=A.B ST=1 0}
                                               ?CBIT=0 1 SKIPYES ; touche 1
                                               {D1=(5)X2 A=DAT1.B B=A.B LA 1F ?A=B.B EXIT 
A=B.B A+1.B
                                               DAT1=A.B ST=1 0}
                                               ?CBIT=0 2 SKIPYES ; touche 4
                                               {D1=(5)Y2 A=DAT1.B ?A=0.B EXIT A-1.B DAT1=A.B 
ST=1 0}
                                               LC 080 GOSBVL 0020F ?CBIT=0 1 SKIPYES ; touche 
RightShift
                                               {D1=(5)X2 A=DAT1.B ?A=0.B EXIT A-1.B DAT1=A.B 
ST=1 0}
                                               %Exit ; DROP a-t-il ete appuye ?
                                               LC 001 GOSBVL 0020F ?CBIT=0 6 SKIPYES ; touche 
DROP
                                               {GOSUBL Restore } ; si oui, alors je quitte le programme 
                                               RTN ; sinon, je retourne dans la boucle principale avec mes
                                               nouvelles coordonnees sauvegardees est pretes a etre 
utilisees
                                               dans Sprite1 et Sprite2
                         7-3
                                               *Collision ; Un point assez complique mais en gros, ‚a se 
passe
                                               comme ‚a : si la difference des abscisses de mes vaisseaux 
est
                                               plus grande ou egale a deux, alors il n'y a pas de probleme. 
Dans
                                               le cas contraire, je verifie leurs ordonnees et si leur 
difference est
                                               plus grande ou egale a 8, alors c'est OK, sinon je quitte le
                                               programme. J'ai pris la peine de vous faire un schema plus 
bas ..
                                               D0=(5)X1 A=DAT0.B D1=(5)X2 C=DAT1.B ?A>C.B 
SKIPYES ; je ne
                                               veux pas que la soustraction me sorte un chiffre negatif 
donc je
                                               regarde quel est la plus grande abscisse. Ce qui me permet
                                               d'utiliser une structure IF (=SKIPYES) ELSE (=SKELSE) 
specifique a
                                               MASD
                                               {C-A.B LA 02 ?C>=A.B -> {RTN} } ; je retourne dans la 
boucle
                                               principale si les abscisses sont OK (C-A.B est identique a 
C=C-A.B
                                               et A-C.B est identique a A=A-C.B)
                                               SKELSE {C=A-C.B LA 02 ?C>=A.B -> {RTN} }
                                               D0=(5)Y1 A=DAT0.B D1=(5)Y2 C=DAT1.B ?A>C.B 
SKIPYES ; meme
                                               principe
                                               {C-A.B LA 08 ?C>=A.B -> {RTN} }
                                               SKELSE {C=A-C.B LA 08 ?C>=A.B -> {RTN} }
                                               GOSUBL Restore RTN ; si les abscisses ET les ordonnees 
revelent
                                               une collision, alors je quitte le programme. Note : le dernier 
RTN
                                               est inutile puisque Restore arrete l'execution du prog. 
         

         
                         7-4
                                               *Clrscr ; Ca fait du bien de retrouver des choses qu'on sait 
faire !!
                                               A=0.W D0=(5)ECRAN C=DAT0.A D0=C LC 87
                                               {DAT0=A.W D0+16 C-1.B UPNC}
                                               RTN
         
                         7-5
                                               *Wait 
                                               LC FFF {C-1.X UPNC} ; cette boucle va s'executer FFF+1 
fois
                                               RTN
         
                          8
                                               *Restore
                                               D1=8068D C=DAT1.A D0=(5)setecran DAT0=C.A ; 
affiche l'ecran
                                               normal
                                               D0=(5)setmenu LC 37 DAT0=C.B ; remonte le menu
                                               GOSBVL Flush INTON2 ST=1 15 ; vide le buffer clavier, 
remet les
                                               interruptions (MASD remplace INTON2 par GOSBVL 
AllowIntr
                                               (GOSBVL 26767) )
                                               LOADRPL ; rend la main au systeme
                                               RTN ; inutile car la boucle principale ne sera plus jamais 
executee,
                                               Sniff :(
                                               @"
         
       **Quelques notes :
         vous avez remarque que pour chaque GOSBVL, je vous donne l'adresse 
correspondante. En fait, c'est
       extable qui se charge de remplacer les noms par les adresses pour MASD. Les 
correspondances sont dans
       le fichier des entries 49 certainement dispo sur hpcalc.org.
         Ce programme peut certainement etre optimise, j'ai evite quelques complications 
mais si vous avez des
       idees, envoyez-les et je ferai une petite rubrique sur l'optimisation.
         Je pense que pour bien comprendre cet exemple, vous devriez programmer un jeu 
du meme style et
       quand vous avez du mal, pompez sur ces sources, c'est le seul moyen (a mon avis).
         Pour les betes de l'asm, n'hesitez pas a m'insulter si je code des aberrations vu que 
c'est mon premier
       "vrai" jeu (si on peut appeler ‚a un jeu)
         Jetez un coup d'oeil sur les programmes qui sortent avec les sources (doom49, 
terminaltor, puzzle
       bobble)
         A moins qu'on me dise le contraire, je vais eviter de donner des programmes 
complets en exemples, ‚a
       me semble trop complique de suivre le raisonnement du coder sur plusieurs dizaines 
de lignes.
         il se peut que j'ai ecrit des betises, si vous n'etes pas sūr, alors lisez la source 
fournie dans l'archive, je
       suis sūr qu'elle est compilable et qu'elle marche.
         Si le democoding vous interesse, il faut absolument m'ecrire, j'avais dans l'idee de 
faire des effets genre
       plasma et fire mais je ne m'y connais pas assez.
     
       Vous avez de la chance, je vous donne les sources avec des italiques et du soulignage 
pour bien
       comprendre (je les dorlotte mes lecteurs, moi). L'executable est fourni avec : 
Vessel.zip
                                               XsFl00d - 21/12/99
                                               Pour tout commentaire etc ... n'hesitez pas a ecrire :
                                               p4x@hotmail.com 
                                                               
[-HP-49G : 7_La pile- ] 
       Cette fois nous allons etudier la gestion de la pile (stack en anglais)..
       On va commencer par expliquer comment elle fonctionne puis programmer les 
foncions usuelles comme DUP, DROP, etc ..
       Qu'est-ce que la pile ?
       Imaginez que vous allez dans une cafeteria. Vous arrivez, vous prenez un plateau sur 
la pile, vous mangez des trucs degueux et vous remettez le
       plateau sur le dessus de la pile. Donc la prochaine personne qui va arriver va prendre 
le plateau que vous venez de poser : c'est donc une structure
       LIFO (Last In First Out = dernier arrive premier parti).
       Rien de nouveau pour le moment si vous n'utilisez pas le mode algebrique (je 
l'espere pour vous !). Ce qu'il y a sur la pile (par exemple un GROB)
       n'est pas le GROB lui-meme mais l'adresse de ce GROB en memoire. Ainsi, chaque 
niveau utilise 5 quartets (cad la taille d'une adresse). Le
       niveau le plus haut est la ligne de commande, ensuite c'est le dernier niveau, l'avant 
dernier et enfin le niveau 1.
       Pour monter d'un niveau, on incremente l'adresse du pointeur de 5 quartets.
       Pour trouver l'adresse du niveau 1, il faut savoir que la HP utilise un registre qui 
contient l'adresse de ce niveau : D1. C'est d'ailleurs pour ‚a qu'on
       fait un SAVE et un LOADRPL : si on a modifie D1 dans notre programme, il faut le 
reinitialiser a la valeur qu'il avait avant le lancement de notre
       soft. Bien sūr, si on veut que la HP ne retourne pas a l'etat initial pour par exemple 
changer quelque chose a la pile, il ne faut pas faire de
       LOADRPL.
       Regardez plutļt le schema.
                                 NIVEAU
                                                                               EXEMPLE
                                                                                                      ADRESSE
                                                                                                      RELATIVE
                             Ligne de commande
                                                                        FFF3C (a trouver en 806FD)
                                                                                                         +15
                                 Niveau 3
                                                                                 FFF37
                                                                                                         +10
                                 Niveau 2
                                                                                 FFF32
                                                                                                         +5
                                 Niveau 1
                                                                   FFF2D (D1 pointe dessus au debut du soft) 
                                                                                                          0


               DROP (efface le niveau 1 de la pile)
                                                  D1+5 ; D1 contient l'adresse du niveau 1 de la pile. DROP 
consiste a ce que le niveau 
                                                  2 devienne le niveau 1. Donc je fais pointer D1 5 quartets 
plus loin. 
                                                  D+1.A ; D contient le nombre de blocs de 5 quartets libres 
dans la pile. Vu que j'elimine
                                                  un niveau, j'ai libere 5 quartets, d'ou D+1.A
                                                  RPL ; equivalent a A=DAT0.A D0+5 PC=(A)
                                                  @ 
       ** Voila ce que nous avons fait:
       En debut de programme, D1 contient l'adresse du niveau 1 de la pile. Augmenter D1 
de 5 signifie que le premier niveau va correspondre a l'ancien
       niveau 2. Ainsi, le niveau 1 est parti aux oubliettes. D1+10 aurait correspondu a 2 
DROP, D1+15 a 3 DROP etc ...
       Ici, nous ne faisons pas de test pour savoir si la pile contient quelque chose dans le 
niveau que l'on veut dropper mais la HP en fait un elle.
       ** A part D1, la HP utilise d'autres registres qui doivent etre sauvegardes et restaures 
si vous les modifiez dans votre code :
       D0 : pointe l'adresse du prochain objet a executer
       D1 : le pointeur de pile
       B : pointeur de la pile de retours (return stack)
       D : nombre de blocs de 5 quartets libres.
       Donc A et C sont libres. Si vous n'utilisez qu'eux, vous pouvez vous dispenser de 
SAVE et LOAD mais RPL est toujours necessaire (cf
       explication de RPL plus loin).
       ** RPL (ou LOOP)
       A=DAT0.A ; D0 pointe sur l'adresse du prochain objet a executer. Donc je recupere 
en A cette adresse.
       D0+5 ; On fait pointer D0 sur ce qu'il faut lancer apres ce qui va etre execute par 
PC=(A)
       PC=(A) ; Program Counter : l'instruction a executer (ce qui etait en D0 avant le 
lancement de notre programme). C'est cette instruction qui permet
       a la HP de faire comme si rien n'avait change depuis qu'on l'a pertubee en lan‚ant 
notre code.
       ** Si vous avez compile le code, que vous obtenez Code sur la pile et que vous faites 
EVAL pour l'executer, sachez qu'il n'entre pas en compte
       dans le decompte des niveaux (dans ce cas, niveau2=niveau1 a l'ecran). Ceux qui se 
sont poses la question me comprennent, sinon, tout est OK.
          SWAP (echange les contenus des niveaux 1 et 2)
                                                  A=DAT1.A ; A : adr de l'objet du niveau 1
                                                  D1+5 ; je passe au niveau 2
                                                  C=DAT1.A ; C : adr de l'objet du niveau 2
                                                  DAT1=A.A ; je copie l'adr de l'objet du niveau 1 sur le 
niveau 2
                                                  D1-5 ; retourne au niveau 1
                                                  DAT1=C.A ; copie l'ancienne adr de l'objet du niveau 2 
sur le niveau 1 
                                                  RPL ; rend la main au systeme
                                                  @ 
         
       ** Il serait tres facile de faire un echange des niveaux 1 et 3 par exemple en 
rempla‚ant D1+5 par D1+10 et D1-5 par D1-10.
       Les autres operations de la pile comme ROT qui ne necessitent pas la creation d'un 
nouveau niveau 1 seraient un bon entrainement (envoyez-moi
       vos sources et je les inclurerais dans cette partie).
       Maintenant, nous allons voir la modification du contenu d'un niveau, puis l'ajout d'un 
nouvel objet dans la pile (sans destruction de l'objet du niveau
       1).
         
       MODIFICATION DU CONTENU D'UN NIVEAU
                                                  Avant tout, vous allez recuperer l'adresse d'un fichier de 
votre HP (un fichier texte par
                                                  exemple) en le mettant dans la pile et en utilisant la 
commande ->A du menu 256 (tapez
                                                  256 MENU pour y acceder). Il vous retourne une adresse 
que vous allez noter (‚a va
                                                  etre du genre #FFF3C par exemple).
                                                  Stockez ce que vous voulez dans le niveau 1 de la pile.
                                                  LC FFF3C ; on suppose que le fichier est a cette adresse 
en RAM
                                                  DAT1=C.A ; je veux que le niveau 1 affiche le contenu de 
ce fichier
                                                  RPL ; rend la main au systeme
                                                  @ 
         
        AJOUT D'UN NOUVEL OBJET DANS LA PILE
                                                  LC FFF3C ; le fichier a mettre au niveau 1 est a cette 
adresse (cf exemple precedent)
                                                  D1-5 ; je fait pointer le niveau 1 5 quartets sous le niveau 
1 actuel (qui devient le niveau
                                                  2).
                                                  D-1.A ; 5 quartets en moins sont disponibles
                                                  DAT1=C.A ; Maintenant que j'ai insere un nouveau 
niveau et que j'ai decale les autres,
                                                  je peux lui dire ce qu'il doit contenir
                                                  RPL
                                                  @ 
         
       ** Voila, j'ai fini pour ce qui est de la gestion de la pile mais je voudrais expliquer 
quelque chose qui pourrait vous etre utile : Creer un nouveau
       fichier texte, lui ajouter des caracteres, et l'afficher au niveau 1 de la pile. Ca peut 
vous etre utile pour donner le score a la fin d'un jeu. 
       Pour cela, il faut reserver en memoire un espace pour y mettre le fichier tout 
simplement en utilisant la meme methode que pour reserver un ecran.
       Puis on va lui ajouter des caracteres et enfin l'afficher au niveau 1 de la pile.
       Un STRING (fichier texte) est constitue :
       D'un prologue qui tient sur 5 quartets. Chaque type d'objets (repertoire, programme 
etc..) a son propre prologue qui permet a la HP de savoir en
       quoi consiste l'objet. Pour un string : 02A2C
       De 5 quartets contenant sa taille (prologue non-inclu ; 5 quartets de la taille inclu).
       De nombres hexadecimaux. Chaque caractere est code par 2 chiffres. La commande 
S->H du menu 256 permet de voir la chaine hexadecimale
       correspondant a la chaīne de caracteres.
         
              AFFICHAGE D'UNE CHAINE DE
                      CARACTERES
                                                  SAVE ; sauvegarde des registres (ils vont etre alteres dans 
la suite)
                                                  LC 00018 ; Taille de la chaine : 5 (prologue) + 5 (taille) + 
14 (7 chars * 2) = 18h
                                                  RES.STR ; reserve 18 quartets en memoire
                                                  LC 02A2C ; prologue d'un string
                                                  DAT0=C.A ; je l'ecris sur 5 quartets
                                                  LC 00013 ; taille : 5 + 14 = 13h
                                                  D0+5 ; saute le prologue
                                                  DAT0=C.A ; ecrit la taille
                                                  LCASC(7) XsFl0oD ; LCASC permet d'entrer 
directement sa chaine de caracteres au
                                                  lieu de taper les nombres hexadecimaux. Le chiffre entre 
parentheses est le nombre de
                                                  caracteres.
                                                  D0+5 ; saute la taille
                                                  DAT0=C.14 ; ecrit mes caracteres (7 caracteres donc 14 
chiffres hexadecimaux)
                                                  D0-10 ; retourne au debut de l'objet
                                                  D1-5 ; cree un nouveau niveau 1 dans la pile
                                                  D-1.A ; 5 quartets en moins de disponibles
                                                  A=D0 ; A : adresse du string
                                                  DAT1=A.A ; le niveau 1 affiche le string
                                                  A=D1 ; sauvegarde de D1 pour l'actualiser apres la 
restauration des registres
                                                  LOAD ; restaure les sauvegardes (meme D1)
                                                  D1=A ; mais dit a la HP d'afficher mon nouveau niveau 1
                                                  RPL ; rend la main au systeme
                                                  @ 
       ** Un truc de derniere minute pour debugger vos programmes : MASD contient une 
fonction qui s'appelle DISPKEY. Il suffit de l'integrer dans
       votre source et elle vous affichera les valeurs de tous les registres, les variables etc... 
Il suffit alors d'appuyer sur une touche pour continuer le
       deroulement du programme.
         
         Voili voilou. Bon, il faut qu'on parle d'hommes a hommes. J'ai un grand service a 
vous demander. Je m'explique : une societe vous permet de
       gagner 50 cents de l'heure en allant sur internet avec un bandeau publicitaire. Ce 
n'est pas un "attrape-nigaud" (certaines revues en parlent en bien).
       Si vous etes interesses, merci de vous inscrire a partir de cette adresse : 
http://www.alladvantage.com/go.asp?refid=HOG-495 . Ca me rajoutera
       des dollars :) et peut-etre meme que je pourrais devenir rentier et ecrire des tutoriaux 
a plein temps. Merci et a bientļt pour de nouvelles
       aventures.
       [XsFl0od/P4X] - 3/02/00
       Pour tout commentaire etc ... n'hesitez pas a ecrire : p4x@hotmail.com 

Downloader la doc

Retour au sommaire Programmation
HOME

Ce site n'a absolument rien a voir avec la societe Hewlett-Packard
©2000-2001, HP-Arena.com et ses differents particicipants

[an error occurred while processing this directive]