; Appel du sous-programme Facture (chapitre 10) ; ; Philippe Gabrini Octobre 1993 (revu en août 2005) ; modifié par Bernard Martin (hiver 2017) pour pouvoir l'analyser avec le débogueur ; bug pour la multiplication par 1 corrigé (hiver 2020) ; LF: .EQUATE 0x000A ;Line Feed ;int main() { AppFact: LDA typ1,i ; Liste des cinq mots des types de service STA liste1,d ; premier paramètre LDA temps,i ; Durée STA liste2,d ; deuxième paramètre LDA result,i ; Résultat STA liste3,d ; troisième paramètre ; LDA liste1,i ; liste de trois pointeurs STA -4,s ; sauter espace pour code résultat SUBSP 4,i ; empilage #coderes #liste123 CALL Facture ; Facture(liste1); ; Affiche: DECO 0,s ; cout >> code; ADDSP 2,i ; Désempile code #coderes CHARO LF,i ; cout >> endl; DECO result,d ; cout >> résultat CHARO LF,i ; >> endl STRO mesg,d ; >> "Fin du traitement"; STOP ;} ; typ1: .WORD 3 typ2: .WORD 4 typ3: .WORD 5 typ4: .WORD 2 typ5: .WORD 0 temps: .WORD 10 result: .WORD 0 liste1: .BLOCK 2 ;Liste des trois pointeurs #2h liste2: .BLOCK 2 ; #2h liste3: .BLOCK 2 ; #2h liste123:.EQUATE 0 ; #2h coderes: .EQUATE 2 ; #2d mesg: .ASCII "Fin du traitement\n\x00" ; ; Calcul de la somme due par un patient de la clinique ; ; Ce programme reçoit un tableau de cinq entiers indiquant les ; types de service fournis au patient (entiers de 1 à 5). S'il ; y en a moins que 5, le tableau est complété par des zéros. ; Si un type est invalide, on revient au programme appelant avec ; un code d'erreur négatif au sommet de la pile. Le programme ; reçoit aussi la durée de traitement en quarts d'heure et ; produit comme résultat le coût dû par le patient. ; ; Appel: réserver espace pour code résultat ; empiler adresse liste 3 pointeurs ; CALL Facture ; avec Liste de 3 mots ; Mot 1 ---> 5 mots: types de service ; Mot 2 ---> 1 mot: quarts d'heure de service ; Mot 3 ---> 1 mot: résultat du traitement ; ; Philippe Gabrini juin 1993 (revu en août 2005) ;************************************************************** type: .EQUATE 0 ; type de traitement temporaire #2h compte: .EQUATE 2 ; compteur temporaire #2d cout: .EQUATE 4 ; cout temporaire #2d res: .EQUATE 6 ; adresse résultat #2h duree: .EQUATE 8 ; valeur durée #2h table: .EQUATE 10 ; adresse table des types #2h regX: .EQUATE 12 ; sauvegarde X #2h regA: .EQUATE 14 ; sauvegarde A #2h retour: .EQUATE 16 ; adresse de retour #2h liste: .EQUATE 18 ; adresse de la liste #2h code: .EQUATE 20 ; indice du résultat #2d ; Facture: SUBSP 16,i ;void Facture(liste) { #regA #regX #table #duree #res #cout #compte #type STA regA,s ; sauvegarde A STX regX,s ; sauvegarde X LDA 0,i ; code retour normal STA code,s ; LDX 0,i ; index = 0; LDA liste,sxf ; adresse table des types de service STA table,s ; ADDX 2,i ; index = 1; LDA liste,sxf ; adresse durée STA duree,s ; ADDX 2,i ; index = 2; LDA liste,sxf ; adresse résultat STA res,s ; LDA duree,sf ; valeur durée STA duree,s ; LDA 0,i ; coût nul STA cout,s ; STA compte,s ; Boucle: NOP0 ; while(true) { //5 fois LDX compte,s ; index = 0; LDA table,sxf ; service(index) CPA 0,i ; BREQ FinBouc ; if(type == 0) break; BRLT Others ; if(type < 0) non valide CPA 6,i ; BRGT Others ; if(type >6) non valide SUBA 1,i ; numéro cas-1 ASLA ; * 2 (taille des éléments de la table) STA type,s ; LDX type,s ; => adresse dans la table BR TabCas,x ; switch(type) { ; table des cas placée dans le code TabCas: .ADDRSS Cas1 .ADDRSS Cas2 .ADDRSS Cas3 .ADDRSS Cas4 .ADDRSS Cas5 .ADDRSS Cas6 Cas1: LDA duree,s ; case 1: IF01: CPA 12,i ; if(Durée <= 12) BRGT ELSE01 ; THEN01: LDA 1500,i ; Frais courants = 15.00; BR ENDIF01 ; else ELSE01: LDA 4500,i ; Frais courants = 45.00; ENDIF01: BR FinCas ; Cas2: LDA duree,s ; case 2: if(Durée >= 9) IF02: CPA 9,i ; BRLT ENDIF02 ; THEN02: ADDA 3,i ; Frais courants = (Durée + 3) ASRA ; / 4 ASRA ; ASLA ; *12$ ASLA ; STA type,s ; (multiplie par 4 ADDA type,s ; et ajoute 3 fois!) ADDA type,s ; ; *100 pour mettre le montant en dollars STA -4,s ; LDA 100,i ; STA -6,s ; SUBSP 6,i ; #resu #op1 #op2 CALL Multipli ; * 3.75$ LDA 0,s ; ADDSP 2,i ; Désempile résultat multiplication #resu IF03: CPA 7200,i ; if(Frais courants > 72) BRLE ENDIF03 ; THEN03: LDA 7200,i ; Frais courants = 72; ENDIF03: BR FinCas ; ENDIF02: LDA 0,i BR FinCas ; Cas3: LDA duree,s ; case 3 : Frais courants = Durée STA -4,s ; LDA 375,i ; STA -6,s ; SUBSP 6,i ; #resu #op1 #op2 CALL Multipli ; * 3.75$ LDA 0,s ; ADDSP 2,i ; Désempile résultat multiplication #resu BR FinCas ; Cas4: LDA 1200,i ; case 4 : Frais courants = 12.00 ; BR FinCas ; Cas5: LDA duree,s ; case 5 : Type5(); CALL Type5 ; BR FinCas ; Cas6: LDA 1200,i ; case 6 : Frais courants = 12.00 ; BR FinCas ; Others: LDA -1,i ; default : code d'erreur STA code,s ; BR FinBouc ; break ; ; }// switch FinCas: CPA cout,s ; if(Frais courants > Frais maximum) BRLE ENDIF04 ; THEN04: STA cout,s ; Frais maximum = Frais courants; ENDIF04: LDX compte,s ; index++; ADDX 2,i ; prochain type de service STX compte,s ; CPX 10,i ; if(index -> 5) break; BRLT Boucle ; }// while FinBouc: LDA cout,s ; Retourne Frais maximum LDX 0,i ; STA res,sxf ; résultat LDA retour,s ; adresse retour STA liste,s ; déplacée LDA regA,s ; restaure A LDX regX,s ; restaure X ADDSP 18,i ; nettoyer pile #retour #regA #regX #table #duree #res #cout #compte #type RET0 ; return ; ;********************************************************************** ; Sous-programme interne pour le traitement du type 5 ; Le registre A comprend la durée. Type5: CPA 4,i ; if(durée > 4) BRLT ELSIF06 ; THEN05: LDA 4500,i ; Frais courants = 45.00; BR ENDIF05 ; ELSIF06: CPA 3,i ; else if(Durée == 3) BRLT ELSIF07 ; THEN06: LDA 3450,i ; Frais courants = 34.50; BR ENDIF05 ; ELSIF07: CPA 2,i ; else if(Durée == 2) BRLT ELSIF08 ; THEN07: LDA 2250,i ; Frais courants = 22.50; BR ENDIF05 ; ELSIF08: CPA 1,i ; else if(Durée == 1) BRLT ENDIF05 ; THEN08: LDA 1200,i ; Frais courants = 12.00; ENDIF05: RET0 ; return; ;********************************************************************** ; Sous-programme interne pour la multiplication de deux entiers ; Appel: réserver espace résultat (mot) ; empiler premier entier ; empiler second entier ; CALL Multipli ; Retour: résultat au sommet de la pile ; sauveX: .EQUATE 0 ; #2h sauveA: .EQUATE 2 ; #2h adRetour:.EQUATE 4 ; #2h op2: .EQUATE 6 ; opérande 2 #2d op1: .EQUATE 8 ; opérande 1 #2d resu: .EQUATE 10 ; résultat #2d ; Multipli:SUBSP 4,i ; espace local sauvegarde #sauveA #sauveX STA sauveA,s ; sauvegarde A STX sauveX,s ; sauvegarde X LDA 0,i ; STA resu,s ; res = 0; LDX op1,s ; compte = op1; CPX 0,i ; if(op1 == 0) BREQ Fini ; résultat nul LDA op2,s ; additioner op2 STA resu,s ; CPA 0,i ; if(op2 == 0) BREQ Fini ; résultat nul CPX op2,s ; if(op1 < op2){ BRLE Calc ; Echange: LDX op2,s ; compte = op2; LDA op1,s ; additioner op1 Calc: STA resu,s ; CPX 1,i BREQ Saute Calcul: ADDA resu,s ; for(int i = 1; i <= Compte-1; i++){ BRV Deborde ; SUBX 1,i ; A = A + res; CPX 1,i ; BRNE Calcul ; } Saute: STA resu,s ; Fini: LDA adRetour,s ; adresse retour STA op1,s ; déplacée LDA sauveA,s ; restaure A LDX sauveX,s ; restaure X ADDSP 8,i ; nettoyer pile #op1 #op2 #sauveA #sauveX RET0 ; return Deborde: LDA 65535,i ; STA resu,s ; res = 65535; BR Fini ; .END