Je me suis lancé il y a peu dans l'assembleur pour pouvoir programmer sur Ti-83. J'ai donc essayé de faire mon premier programme à partir de fragments de tutoriaux pêchés à droite et à gauche.
C'est une version ASM du programme en Ti-Basic de quelques lignes que j'ai sur ma calculatrice. Ultra-classique, il calcule le discriminant, le sommet, et la/les racines d'un trinôme à partir de ses trois coefficients. C'est un premier programme pour me faire la main, mais ça ne marche pas vraiment.
Voici mon code:
#include "input.asm" #include "begin.asm" ;------------------------> variables varstart = 8265h ;-------------------------------------------------- ;variable name value size description ;-------------------------------------------------- var_a =varstart+9 ;9 coefficient en x² du trinôme var_b =var_a+9 ;9 coefficient en x du trinôme var_c =var_b+9 ;9 dernier terme en x^0 du trinôme var_delta =var_c+9 ;9 discriminant (b²-4ac) var_sommet =var_delta+9 ;9 var_sommet du trinôme (-b/2a) call _clrLCDFull call _homeup call _zeroop1 call _newline ld hl,debut call _puts call _newline ;obention de a ld de,PROMPT ld hl,prompta ld bc,3 call PGMIO_EXEC ;transfert de OP1 vers var_a ld hl,op1 ld de,var_a ld bc,9 ldir ;obention de b ld de,PROMPT ld hl,promptb ld bc,3 call PGMIO_EXEC ;transfert de OP1 vers var_b ld hl,op1 ld de,var_b ld bc,9 ldir ;obention de c ld de,PROMPT ld hl,promptc ld bc,3 call PGMIO_EXEC ;transfert de OP1 vers _c ld hl,op1 ld de,var_c ld bc,9 ldir ; ;calcul du sommet (-b/2a) ; ;transfert de var_b vers OP1 ld hl,var_b ld de,op1 ld bc,9 ldir ;inversion du signe call changesign ;transfert de var_a vers op1 pour la multiplication par deux ;auparavant, sauvegarde de -b (op1) vers op2 call _OP1TOOp2 ld hl,var_a ld de,op1 ld bc,9 ldir call _TIMES2 ;on remet -b dans op1, et 2a dans op 2 pour la division finale call _OP1TOOP3 ;on met 2a dans op 3 call _OP2TOOP1 ;on met -b dans op 1 call _OP3TOOP2 ;enfin, on remet 2a dans op2, et on peut faire la division call _FPDIV ;enfin, on sauvegarde le résultat dans var_sommet: ld hl,op1 ld de,var_sommet ld bc,9 ldir ; ;transfet de B vers OP1 puis calcul de b² ; ld hl,var_b ld de,op1 ld bc,9 ldir call _FPSQUARE ;on retransfert b²(op1) dans op3 et on calcule maintenant 4ac call _OP1TOOP3 call _op1set4 ld hl,op2 ld de,var_a ld bc,9 ldir ;on effectue 4*A call _FPMULT ;on charge maintenant C dans op2 ld hl,var_c ld de,op2 ld bc,9 ldir call _FPMULT ;enfin, on fait b²(op3) - 4ac(op1) call _OP1TOOP2 ;on met 4ac dans op2 car c'est le deuxième terme call _OP3TOOP1 ;on remet b² dans op1 call _FPSUB ;on a notre var_delta, on fait maintenant en fonction des valeurs ;sauvegarde de var_delta ld hl,op1 ld de,var_delta ld bc,9 ldir call _op2set0 call _cpop1op2 jp m,deltaneg jp z,delta0 jp p,deltapos deltaneg: ld hl,nosolution call _puts delta0: ;affichage de la chaîne puis du var_sommet ld hl,solution call _puts ld hl,var_sommet ld de,op1 ld bc,9 ldir call _formDisp deltapos: ;calcul des deux racines (-b-sqrt(var_delta)/2a) ;d'abord, on calcule racine de var_delta : on stocke var_delta dans op1 ld hl,var_delta ld de,op1 ld bc,9 ldir call _SQROOT call _OP1TOOP2 ;on met sqrt(var_delta) dans op2 call _OP1TOOP6 ;on garde également en mémoire la valeur pour les futurs calculs ;on place var_b dans op1 ld hl,var_b ld de,op1 ld bc,9 ldir ;inversion du signe call changesign call _FPSUB ;on soustrait maintenant ;on stocke temporairement -b-sqrt(var_delta)[op1] dans op3 pour faire la multiplication 2*a call _OP1TOOP3 ;multiplication de a par deux ld hl,var_a ld de,op1 ld bc,9 ldir call _TIMES2 call _OP1TOOP2 call _OP3TOOP1 call _FPDIV ;enfin après avoir retransférer les valeurs où il faut, on divise le tout ;on stocke la première racine dans op4 call _OP1TOOP4 ;on réutilise la valeur de sqrt(var_delta) stockée dans op6 call _OP6TOOP2 ;on place var_b dans op1 ld hl,var_b ld de,op1 ld bc,9 ldir ;inversion du signe call changesign call _FPADD ;on stocke temporairement -b+sqrt(var_delta)[op1] dans op3 pour faire la multiplication 2*a call _OP1TOOP3 ;multiplication de a par deux ld hl,var_a ld de,op1 ld bc,9 ldir call _TIMES2 call _OP1TOOP2 call _OP3TOOP1 call _FPDIV ;enfin après avoir retransférer les valeurs où il faut, on divise le tout ;on stocke la deuxième racine dans op5 call _OP1TOOP5 ;on affiche ensuite les valeurs ld hl,solutions call _puts call _OP4TOOP1 call _formDisp call _OP5TOOP1 call _formDisp changesign: ld a,(op1) cp 0 call nz,set_pos call z,set_neg ret set_pos: ld a,0 ld (op1),a ret set_neg: ld a,$80 ld (op1),a ret debut: .db "Calcul du discriminant",0 prompta: .db "A:",0 promptb: .db "B:",0 promptc: .db "C:",0 nosolution: .db "Pas de solutions",0 solution: .db "Une solution:",0 solutions: .db "Deux solutions:",0 .end END
Quand je l'exécute sur VTI, j'ai juste une ligne verticale de pixel qui s'affiche à droite et ça plante. Avant, j'utilisais des variables comme promptb (déclarées dans le segmet data, comme .db etc...) à la place de var_a, var_b, etc... mais ça ne marchait pas mieux, les invite prompt ne s'affichaient pas, je rentrais quand même trois nombre et ça me mettait enfin "Error : Division by zero".
J'aimerai donc que vous me donniez des conseils déjà pour que mon programme fonctionne, et ensuite si possible sur les utilisations de tel et tel routine, sur la déclaration, les techniques couramment utilisées, sur le style, etc...
bref toute suggestion qui me serait utile.
Merci d'avance, @++