******************************* * PREMIERS PROGRAMMES * ******************************* INTRODUCTION Et bah voila les enfants il va falloir se mettre au boulot (et oui). Je presente ici un programme pas tres exitant mais qui a le merite d'etre simple a comprendre et d'utiliser un peu tout : gestion de presque tous les periferiques(clavier, ecran, buzzer), reservation memoire en ASM..., du pain sur la planche quoi! VOUS AVEZ DIT GX Pour les ignards qui ne le saurait pas encore la HP48GX est sortie(2040F a la camif, 2290F a maubert). La memoire de base est a 128Ko au lieu de 32, la vitesse a ete presque doublee, elle est maintenant extensible a plus de 4 mega octets(anciennes extentions compatibles). Bref je me suis mis sur la paille pour me l'acheter etant donne que je trouverais bien un pecos pour me racheter ma SX a 1500F et que 540F pour une carte 96Ko(128-32) c'est pas donne mais presque. Vous savez maintenant quoi faire. Je la recois la semaine prochaine et les programmes suivant seront compatibles pour les deux versions (ou je ferais 2 programmes). J'espere que cela ne posera pas de problemes au examem car la capacitee maximun des calculatrices est fixee a 32Ko(attention ca doit passer au bac ou a la FAC mais pas dans les concours d'ecole d'ingenieur). DE LA PROPRETE AVANT TOUT Il y a des programmeurs sales et il y a des programmeurs propres. Que ceux qui aiment la salete et la crasse aillent voir ailleurs si j'y suis. Programmer proprement signifie: quand le programme se fini, l'environnement doit etre exactement pareil que au moment ou il a commence(ou sauf si on veu modifier quelques chose expres). Si on ne respecte pas ces regles elementaires de propretes, on poura avoir des mauvaises surprises: Par exemple, si on utilise l'ecran graphique pour travailler en ASM, les graph seront perdu alors que c'est pas bien compliquer de reserver un ecran en plus.Si on utilise l'ecran courant(celui de la pile), on aura l'impression quand le programme se fini que l'on a rien modifie, car le systeme reconstruit cet ecran a la fin du programme, mais si vous le lancer a partir d'un autre programme alors la l'ecran ne se restaure pas (catastrofen). De meme pour la barre de menu, si on la descent sans la relever, le systeme la remontera toute seule, sauf si cela s'inscrit dans un programme RPL(on peut mettre plusieurs prog ASM(code) a la suite dans un prog RPL (les CODE sont des objets comme les autres(comme les LIST,ARRAY..)). voici donc les consignes de propretes les plus elementaires -sauvegarder tous les registres(appeles aussi variables du processeur) et les restaures a la fin du programme. -reserver un ecran(a la limite utiliser celui de la pile si on se sert des menus) -si on baisse le menu, le remonter. -ne jamais effacer quelque chose, ou modifier quelques choses sans etre sur qu'on peu le restaurer. A ce moment vous pourez etre sur que vos programmes marcherons tout le temps. Vous seriez surpris de savoir comment vos programmeurs preferes programment salement(mais il y a des saint de la proprete aussi). Moi meme au debut j'etais un vrai porc, mais c'est normal comment voulez vous reservez un ecran quand vous ne savez meme pas le faire. Et puis cela ajoute de la difficulte: on se dit "si ca marche pas c'est a cause de ma reservation memoire, alez je me fou en environnement graphique(super en plus j'aurais pas a retirer la barre de menu, c'est automatique)" FAUX ARCHIFAUX, c'est idio car apres cela est beaucoups plus dur pour revenir a un ecran reserve. le conseil de la journe est donc: faites vous un source qui reserve un ecran blanc et l'affiche et merger le(voir:se servir de ASMFLASH) des qu'il vous en faut un dans un source(un autre programme ASM). Bon alors j'en sent qui trepignent, qui en ont mare de la theorie, "alez on veut programmer merde". Et oui jusqu'ici c'etait simple, le probleme c'est ca: tous les gens se disent que l'ASM est complique parce que c'est le langage le plus puissant, celui qui prend le moins de place ... En fait c'est tout le contraire, l'ASM est reelement le langage le plus simple parce que l'on ne se sert que d'une 50aine d'instructions. Y en a qui vont piquer une crise alors on commence.(en face de chaque ligne ou groupe de lignes du programme, il y a un numero auquel on se refere dans le texte explicatif). SAUVEGARDER LES REGISTRES:*1* Quand un programme en langage machine se fini il faut que toutes les variables, tous les drapeaux soient identiques au moment ou il a commencer. Il faut donc sauvegarder les variables au debut, et les remetre a la fin. On pourait le faire a la main mais on peut faire un GOSUB en ROM qui nous fait tout ca automatiquement(un gosub est comme un goto sauf que des que la ou on a appele il y a un RTN(return) le programme se reprend apres le GOSUB. Ces gosub sont au debut GOSBVL 0679B (0679B est une adresse en ROM) a la fin GOSBVL 067D2 (aussi une adresse en ROM) Il faut egalement rendre la main au systeme: pour cela on fait A=DAT0 A (lecture de 5 cases a l'adresse qu'il y a dans D0 (c'est juste un nombre. Ces 5 cases sont recopie dans A) D0=D0+ 5 (Le nombre que contient D0 est augment‚ de cinq) PC=(A) (5 cases sont lues a l'adresse contenu dans les 5 premieres cases de la variable A et on les met dans le PC(program counter). Le programme s'arrete donc net et reprend a l'adresse contenu dans PC) Bon ca semble compliqu‚ ces adresses et tout mais de toute facon on s'en fou car ca c'est juste pour rendre la main au systeme. On a donc: "GOSBVL 0679B ... GOSBVL 067D2 A=DAT0 A D0=D0+ 5 PC=(A) @" ce petit programme sauve les registres, les recupere et rend la main au systeme. les pointilles corespondent a notre program a nous, qui peut etre n'importe quoi(ici c'est le programme qui demande le code). RESERVER UN ECRAN:*3* Pour cela on va demander au systeme de nous faire une place dans la memoire, une place dont on poura faire ce que l'on veut. Pourquoi ne pas mettre l'ecran a l'adresse 70300h par exemple, reponse: ca se trouve en 70300h il y a des trucs important(variable utilisateur, alarme) et si on les effaces c'est 90% de chance de faire un memory clear(vous savez le truc qui fait un tres joli beep quand on appuis sur ON,A et F en meme temps). Pour demander une place au systeme c'est tres simple: on met dans les 5 premieres cases de la variable processeur C (registre C) la taille dont on a besoin et on fait un GOSBVL: LC 00880 (C=taille d'un ecran en quartets(880h cases dans un ecran, une cases codant pour 4 pixel(voir notation binaire-hexadecimal) cela fait 880h*4 pixels(8704 en decimal)) GOSBVL 039BE et voila le systeme reserve 880h quartet a une addresse stockee en D0(voyage page 355). Cependant un probleme se pose avec cette reservation. Le probleme est que nous avons reserve directement et que la zone reservee n'est pas un objet(une LIST,ARRAY,PROG... la liste est en page 121).Vous voyez qu'a chaque objet correspondent 5 quartets que l'on appelle prologue de l'objet. Si ces 5 quartets sont au debut de la zone reserve, alors le systeme peut reconnaitre ce que c'est. Au debut de notre zone reservee nous, il n'y a rien. Que va t'il se passer quand on va rendre la main au systeme(fin du programme). Et bien cela est tres simple: ca va etre la merde car le systeme a une zone de sa memoire reserve et il ne sait pas ce que c'est, donc probleme de memoire, calculatrice hyper ralentie alors que la memoire est a fond, arrets systeme (comme avec ON-C) etc. Quel est la solution. On pourrait dereserver la zone en quittant le programme mais moi meme je ne connais pas le GOSBVL qui corespond. La deuxime solution serait de faire de cette zone un objet a part entiere(une chaine ou un graph de la longeur de la zone). Pour cela il faudrait ecrire le prologue de la chaine sur les 5 premiers quartets de la zone reservee, puis ecrire sur les 5 suivants, la taille de la zone (attention il faut que cela soit tres exact, si il y a la fin un quartet que l'on a reserve et qu'il n'est pas pris dans la chaine alors BUG(pour les quelques ignard qui ne connaissent rien au jargon informatique cela signifie que ca merde)). la solution serait donc LC 0088A (10 quartets de plus pour le prologue et la taille(5 chacun) comme cela on en a toujours 880h utilisable) GOSBVL 039BE (reserve moi ca mon petit saturn ) (voila j'ai maintenant 88Ah cases libres a partir de l'adresse qu'il y a en D0(si vous preferes 88Ah maisons dans la rue que je peu utiliser a partir d'une adresse qu'il y a en D0(70400h par exemple)) LC 02A2C (prologue de chaine) DAT0=C A (j'ecris les 5 premieres cases de C(le prologue quoi) dans les 5 premieres cases de ma zone reserve(l'adresse est en D0 et j'utilise DAT0 pour dire a l'adresse(D0=C aurait voulu dire que D0=02A20 ce qui ne nous sert a rien) LC 00885 (taille de la chaine prologue non compris mais indicateur de taille compris(voir page 131 pour structurer une chaine)). D0=D0+ 5 (on s'est occupe des 5 premieres cases(maisons) de la zones reserve, pour acceder aux autres il faut que l'on avance d'adresse, un peu comme le postier, il livre 5 maisons de suite puis il prend sa bagnole avance de 5 numeros de maison(adresse+5) descent et relivre 5 maisons). DAT0=C A (tranfert de la taille(contenue dans C) dans les cases de la memoires a l'adresse contenue dans D0) si la zone de memoire commence en 70400h(D0=70400(c'est un exemple)) on a apres ce petit programme adresse,contenu 70400h C 70401h 2 70402h A 70403h 2 70404h 0 70405h 5 70406h 8 70407h 8 70408h 0 70409h 0 7040Ah ... (souvenez vous que le processeur retourne ses donnes) on aurait pu faire aussi LC 0088A GOSBVL 039BE LC 0088502A2C (prologue et taille a la suite) DAT0=C 10 (10 quartets livres a la fois a l'adresse contenue dans D0) Bon si vous regarder le source moi j'ai fait LC 00880 GOSBVL 05B7D cela est absoluement equivalent sauf que le systeme fait la deuxime etape pour nous(il nous reserve une chaine de 880h quartets avec prologue et taille integres). Cependant si vous etes attentif vous avez remarquez que je n'ai pas mis exactement ca, j'ai mis LC 00881, pourquoi un de plus alors que l'ecran fait 880h. La reponse est tres simple: le gestionnaire d'ecran est un gestionnaire 8 bits(il gerent les quartets par groupe de deux, par bytes) et il faut absoluement que l'addresse de depard de la zone soit paire. En fait il y a une chance sur deux pour que cette adresse soit paire. Et je dis si cette adresse est paire je la laisse, si elle est impair le l'augmente d'un et elle sera paire. C'est pour cela que je reserve 881h quartets car si l'addresse de depard est impair je l'aumente de 1 et elle devient paire et il me reste toujours 880h cases de libres(raisonant avec des maisons: je reserve 881h maison,si l'adresse de la premiere est paire,je prend l'adresse de la suivante et il m'en reste 880h libre, soit toujours la taille de l'ecran). on code cela CD0EX (je suis obliger de mettre le contenu de D0 dans C pour tester la parite, la j'echange leur contenu(il n'existe pas la commande C=D0)) ?CBIT=0 0 GOYES adress_paire C=C+1 A *adress_paire D0=C pour savoir si le nombre contenu dans C est pair, il suffit que je teste si la premiere case est paire(logique), pour cela(une cases comportant 4 bits) il suffit de teste le premier bit(bit numero zero)(voir bases hexa_binaires). Si ce bit(egal a 0 ou a 1) est egal a 0 on saute au label "adress_paire" (GOYES signifie "va si oui" ceux qui ont au moins fait 1 jour d'anglais on du voir le subtil GO-YES(personellement j'aurais fait YESGO mais bon)) et sinon on augmente le chiffre contenu dans C(qui corespond a l'adresse de depard) de 1, il est maintenant paire. On le remet ensuite dans D0. les doigts dans le nez non! voila la zone memoire est reservee, maintenant il faut la declaree comme etant l'ecran: tres simple il suffit de placer l'adresse de la zone sur 5 cases en 00120h: (si C=adresse de debut de la zone reservee) D0= 00120 (il faut ecrire en 00120h donc on le met dans D0(page 73)) DAT0=C A (on ecris les 5 premieres cases de C en 00120h(C contient l'adresse de debut de la zone reservee) et voila votre bel ecran s'affiche(alleluia) EFFACER L'ECRAN:*5* Il faut savoir que la zone que vous avez reservee est sale(c'est a dire que dedans il y a n'importe quoi). Pour avoir un ecran blanc, il faut la remplir de 0.Pour cela rien de plus simple on va faire une boucle: on met 16 zeros dans A: A=0 W(page 365 pour le champs W) on met 880 dans C: LC 87 on suppose que D0 pointe sur le debut de la zone reservee un petit label: *efface on ecris 16 zeros a la fois: DAT0=A W on avance l'adresse de 16: D0=D0+ 16 on decremente le compteur: C=C-1 X si il n'est pas depasse->debut GONC efface Pour en revenir au facteur on peu supposer que D0 est l'adresse de la maison ou s'arrete la bagnole du facteurs , DAT0 le contenu des maisons, C un compteur dans la voiture du facteur qui lui dit quand s'arreter:le facteur etant le SATURN(le processeur). Scenario Splelbergien:on dit au facteur: tu va me remplir toutes ces maisons avec la carte postale A).Donc le facteur part. Sa carte postale A ne contient que des zeros, il met le compteur de sa bagnole a 87h, et il part(son adresse de depart etant la maison ayant l'adresse D0). DAT0=A W=il livre 16 maisons a la fois(c'est un sportif!). La carte postale A possede 16 cases blanches(avec un zero),il recopi une case par maison->resultat 16 maisons remplie chacunne d'un zero. Comme il est creve, il se dit qu'il va reprendre sa bagnole pour faire les 16 maisons suivantes. VROOM VROOM (D0=D0+ 16) sa bagnole avance de 16 maison, il retire un au compteur C dans sa voiture(hey il va pas faire ca in defiement) est il depasse? Non le compteur ne sonne pas c'est bon, il peut continuer:il livre 16 maisons(DAT0=A W) etc..... DRING le compteur est depasser, et le pauvre facteur creve sort de sa boucle infernale. Mais il faut savoir qu'on aurait tres bien pu imaginer un facteur moins sportif: A=0 P (le champs P signifie la premiere case(il est variable)) LC 87F (880h-1) *efface DAT0=A P(ou DAT0=A 0,1 seul quartet ou case livree) D0=D0+ 1 C=C-1 X GONC efface Analysez bien ce facteur. On ne peut pas etre plus faineant, lui il prend sa bagnole pour chaque maison(livre les maisons une par une) En voici encore un autre A=0 P LC 880 *efface DAT0=A P D0=D0+ 1 C=C-1 X ?C#0 X (le # signifie different) GOYES efface Il a un compteur plus perfectionne mais moins rapide. Au lieu d'utiliser les depassements de champs, il teste si les 3 cases de C sont a 0. RECOPIER UN GRAPH:*7* meme strategie que pour effacer on va recopier une partie de la memoire(le graph) dans la zone ecran. Je ne l'expliquerais pas la parce que ca serait interminable, je ferais un cours expres la dessus. ETEINDRE L'ECRAN:*8* Il suffit pour cela de mettre un 0 a l'adresse 00100(voyage page 164). Vous savez maintenant comment faire: D0= 00100 C=0 A DAT0=C P(le champs P signifie une seule case) On a aussi auparavant eteint le sablier(meme technique mais on ne change qu'un bit la) D1= 0010C adresse du sablier A=DAT1 P lit une cases->premiere case de A ABIT=0 0 modifi le bit numero 0 de la premiere case DAT1=A P reecris cette case(transfert inverse)(page 164) on vafaire ensuite une petite boucle d'attente pour que la HP recupere. En fait je fais cette boucle parce que sinon ca ne marche pas bien(les port ne doivent pas avoir le temps de se configurer(l'ecran d'afficher le graph) et cela interfere sur le SHUTDN). la boucle: LC FF *boucle C=C-1 B GONC boucle voila tant que le champs B de C n'est pas depasse on recommence. On peut remplacer le GONC par: ?C#0 B GOYES boucle Bon ensuite on fait SHUTDN. Cela met en veille le processeur jusqu'a ce que l'on appuit sur ON. Il passe en hibernation quoi(quand la HP s'etteint c'est exactement le meme systeme). Il fait une boucle a lui tout seul: le programme s'arrete la et repard avec ON. on ralume alors l'ecran et le sablier. LE TESTEUR DE TOUCHE: Votre prof prefere a fait une grosse erreur: je pense que mon testeur de touche est un peu complique pour votre niveau. En effet non seulement je teste les touches mais en plus j'attend que vous enleviez le doigt de la touche pour en tester une autre etc... Bref deja 22000 pas et si je m'en occupe ca fera 40000 et vous ne pigerez pas. Donc on revera ca plus tard: jetez un coups d'oeuil au cas ou quand meme. LE LISTING DU PROGRAMME !PC (indique a ASMFLASH que j'utilise la notation PC) !0-15 (voir se servir de ASMFLASH) % UN PETIT UTIL % DEBILE POUR PROTEGER % VOTRE HP 'PRO *1* ceci est un merge(fusion avec) la chaine s'appelant PRO(pour prologue en VAR), ca evite de remarquer a chaque fois GOSBVL 0679B GOSBVL 01115 *2* ceci coupe les interuptions % reserve un ecran avec le signe % on met des commentaires LC 00881 *3* on charge 881 dans les 5 premieres cases de C GOSBVL 05B7D appel en ROM pour reserver 881 cases CD0EX l'adresse de depard de la zone reserve est en D0 pour savoir si elle est pair on la met dans C ?CBIT=0 0 test de la parite GOYES address_paire oui paire on saute au label C=C+1 A non on ajoute 1 a l'adresse de depard(ca y est paire) *address_paire D0= 00120,DAT0=C A *4* declare la zone memoire comme etant l'ecran D0=C,B=C A place l'adresse de debut de la zone memoire reservee en D0 et dans B % efface on va effacer(mettre du blanc dans la zone memoire reservee) LC 87 *5* met 87 dans les deux premieres cases de C A=0 W met 0 dans toute(il y en a 16(page 365)) cases de A *efface DAT0=A W transefert du contenu de A a l'addresse pointe par D0 D0=D0+ 16 on incremente de 16 l'adresse d'ecriture C=C-1 B on decremente de 1 le compteur(sur le champs B) GONC efface tant que le champs B n'est pas depasse(depasse=etre a 0 et faire -1(voir ancien cours)) on saut a efface. % barre de menus D0= 00128 *6* D0=adresse de la hauteur des menus(sur 2 cases) LC 3F charge dans C la nouvelle hauteur des menus DAT0=C B transfert du contenu de C a l'add. pointee par D0 (champs B=2 premieres cases) % afficher le dessin LC 00220 *7* charge le nombre 220 dans C C=C+B A on l'ajoute a B(sur 5 cases, resultat dans C) D0=C on met le resultat dans D0 C=PC,GOINA dessin,A=A+C A,D1=A (D1 pointe sur le dessin) LC 2EB C=taille du dessin *recopi_dessin A=DAT1 P on lit 1 cases du dessin(pointee par D1(donc DAT1)) DAT0=A P on l'ecris dans la zone memoire(pointe par D0) D0=D0+ 1 on incremente de 1 l'addresse pointant sur la zone.. D1=D1+ 1 on incremente de 1 l'addresse pointant sur le dessin C=C-1 X on decremente le compteur de 1(sur 3 cases page 365) GONC recopi_dessin si le champs X n'est pas depasse on saute au label % eteindre l'ecran *eteindre D1= 0010C *8* adresse du sablier A=DAT1 P lit une cases->premiere case de A ABIT=0 0 modifi le bit numero 0 de la premiere case DAT1=A P reecris cette case(transfert inverse)(page 164) D0= 00100 adresse pour eteindre l'ecran C=0 A on met C a 0(5 cases) DAT0=C P on eteint l'ecran(=metre 0 a l'adresse 00100h) LC FF,*boucle,C=C-1 B petite boucle d'attente(voir explication) GONC boucle (tant que le champs B de C n'est pas depasse->boucle) SHUTDN met le processeur en veille(jusqu'a un ON) LC 8,DAT0=C P charge 8 dans C et ecriture en 00100(=ralume l'ecran) ABIT=1 0,DAT1=A P on remet le bit 0 et on l'ecris en 0010C(D1=0010Ch) % test du code B=0 A *9* met B a 0 sur 5 cases *debut_test C=PC,GOINA code,A=A+C A,D1=A (adresse du code des touches en D1) LC 02 nombres de touches(-1) dans c(en fait 3 touches) D=C B on fait passer dans D(on ne peut pas le mettre directement dans D) *waitkey *10* on va attendre qu'une touche soit appuyee LC 1FF,OUT=C on envoit sur toutes les lignes du clavier GOSBVL 0115A resultat dans A(voir clavier cours precedents etc..) B=B+15 A on incremente le compteur de temps GONC temps_ok tant que le champs A(5 cases) non depasse:Ok on saute GOTO eteindre sinon on saute en eteindre(ce qui va eteindre la HP) *temps_ok ?A=0 B si A=0(2 pemieres cases)=aucunes touches appuyes GOYES waitkey on saute en waitkey(on recommence(GOYES="va si oui") C=DAT1 X *11* on lit le code d'entre de la premiere touche OUT=C on l'envoit sur le clavier GOSBVL 0115A on recupere en A D1=D1+ 3 on monte de 3 l'adresse pointant sur le code clavier C=DAT1 B on lit le code de sortie D1=D1- 3 on redescent de 3 A=A&C B on fait un AND entre A et C(page 73) ?A=0 B,GOYES debut_test si A=0(touche non appuyee on reva au debut) GOSUB clear_buffer sinon on fait un petit GOSUB au label clear BUFFER D=D-1 B *12* on decremente le compteur de touche de 1 GOC code_ok si le champs B de D est depase c'est fini D1=D1+ 5 sinon on monte le pointeur de touche de 5(touche suivante) GOTO waitkey et on resaute au label waitkey *code_ok % restauration *13* remetre tout en etat D0= 7050E,A=DAT0 A lit sauvegarde de l'addresse ecran en 7050E(page 184) D0= 00120,DAT0=A A on l'ecris en 00120 pour revalider l'ecran(page 170) D0= 00128,LC 37,DAT0=C B*6* remet le menu a la bonne hauteur(voir debut) GOSBVL 010E5 on remet les interuptions 'ENDE *1* tout ce qu'il faut pour reloader les registres initiaux et rendre la mains au systeme *clear_buffer on attend que la touche appuyee soit lachee C=DAT1 X,OUT=C charge le code d'entree et l'envoit GOSBVL 0115A recupere la sortie ?A#0 B GOYES clear_buffer recommence tant que la sortie n'est pas nulle RTN retour de la sous routine(GOSUB->RTN) (RTN=return) *code voici les petit cocode des petite toutouches $20080 code pour la touche 1(200=entre,80=sortie) $20040 pour la touche 2(200=entree,40=sortie) $20020 pour la touche 3...(y en a marre,va voir page 73) il faut savoir que tous ces codes sont retournes par le saturn(le code d'entree est en fait 002,je met 200 pour que vous voyez bien que ca correspond j'aurais mis:002=entree,08=sortie, personne n'aurais capte) *dessin alo ici label dessin 'DESSIN on merge ici un dessin genial(que ca m'a pris des heures a le faire) @" indispensable marque de fin de prog CONCLUSION Je suis desole, j'ai essaye de faire un programme a part entiere pour le premier cours. Je ne pouvait pas faire plus petit. Mais bon en fait c'est juste pour que vous compreniez en gros. C'est une presentation, si vous n'avez pas tout compris, c'est pas grave. La prochaine fois on abordera des sujet beaucoups plus specifiques: afficher un graph a une position dans l'ecran(et le faire scroller)(1 semaine), et ensuite un petit TRON(meme difficulte que ce programme)(2 semaine). J'espere que vous avez quand meme compris quelques chose. N'hesitez pas a couper, coller des morceaux de programme mais surtout proteger sur vos cartes ou votre ordinateur: CAR L'INFAME MEMORY CLEAR vous guette dans son coin et est pres a vous sauter dessus a tout moment. J'attend vos insultes dans ma BAL, ou plutot en CRS.