Pl2 CORRIG 2.DOC/fr
---------------------- CORRIGES DES EXERCICES NR°2 ---------------------- 1) Exercice nr°1 ------------- Voilà les listings des 2 macros instructions 'SAUVE' et 'RESTORE' qui permettent respectivement de sauvegarder et restaurer les registres du 68000. Je passe sur les d‚tails, il suffisait d'utiliser l'instruction MOVEM. Les registres seront sauv‚s dans la pile système par mode pr‚d‚cr‚men- t‚ et restaur‚s par mode postincr‚ment‚.C'est tout ... TEXT SAUVE MACRO movem.l d0-d7/a0-a6,-(sp) ENDM RESTORE MACRO movem.l (sp)+,d0-d7/a0-a6 ENDM END 2) Exercice nr°2 ------------- Voilà le listing de la macro HEXA, qui permet d'afficher en hexad‚cimal le contenu de son paramètre. Il faut d'abord atteindre sucessivement les 8 demi-octets qui composent le L-M pass‚ en paramètre (1 chiffre hexa=4 bits) Pour cela on utilise l'instruction de rotation ROL et on la place dans une boucle. (LSR convenait aussi...) On masquera ensuite les 4 bits de plus faible poids avec AND.L #%1111,dn pour ne garder que le demi-octet à traiter. Le plus difficile vient ensuite: Il faut maintenant afficher la valeur de ce chiffre hexa cod‚ par 4 bits à l'‚cran. Si le chiffre est <$A (donc <10) ce chiffre sera compris entre 0 et 9. En additionnant $30 à la valeur de ce chiffre on obtiendra le code ascii du chiffre. (Car le code ascii de '0' est $30:celui de '1' est donc ‚gal à $30+1=$31 etc...) Si le chiffre hexa à afficher est >9 ce chiffre sera une lettre de l'alph- abet (de A à F). En ajoutant $37+$A à la valeur de ce chiffre on obtiendra le code ascii du chiffre à afficher.(Car le code ascii de 'A' est $37+$A :celui de 'B' est donc ‚gal à $37+$B=$42 etc...) Il suffit ensuite d'afficher avec CCONOUT le code ascii ainsi obtenu et de recommencer l'op‚ration avec tous les demi-octets du paramètre. NB:On utilise les macros SAUVE et RESTORE dans notre macro HEXA pour -- pouvoir utiliser tous les registres sans modifier leur contenu à la fin de la macro. Vous remarquerez que j'utilise des LABELS dans la macro HEXA. La macro ne pourra donc qu'ètre utilis‚e 1 fois dans un listing car l'assembleur ne peut pas distinguer deux labels identiques et à chaque appel d'une macro, celle-ci est re‚crite entièrement... Vous pouvez cependant mettre la macro dans un sous-programme pour pouvoir l'appeller plusieurs fois... TEXT HEXA MACRO $\1 ;macro à 1 paramètre SAUVE ;on sauve les registres pour ne pas ;perdre leur contenu move.l \1,d1 ;on pose le paramètre dans d1 moveq #0,d2 ;initialise le nombre de glissement DECAL addi.b #4,d2 ;on ajoute 4 au nb de glissements cmpi.b #36,d2 ;si d2=36=32+4=on a finit les 32 beq FIN ;rotations,dans ce cas -> FIN move.l d1,d3 ;sinon on pose d1 dans d3 et on rol.l d2,d3 ;fait une rotation de 4 bits andi.l #%1111,d3 ;et on masque ces 4 bits car seuls ;eux doivent ètres trait‚s. ; d3 contient donc la valeur à afficher: 0 à 9 ou A à F. (car un chiffre ;hexa est cod‚ par 4 bits (voir introduction) ) cmpi.b #9,d3 bgt HEX ;si d3 >9, on va en HEX car il faudra ;afficher une lettre et nom plus un ;chiffre... DECIMAL addi.b #$30,d3 ;d3=d3+$30 car la valeur ASCII de 0 est $30 ;Donc si par exp. d3 vaut 1, on le repr‚sente ;par le caractère ascii $30+1=$31='1', si il ;vaut 5, par le code ascii $30+5=$35='5',ainsi ;de suite pour tous les chiffres hexa <9 CCONOUT d3 ;‚dition du contenu de d3 jmp DECAL ;on red‚cale le paramètre et on continue ;avec les 4 bits suivants en DECAL HEX addi.b #$37,d3 ;d3=d3+$37 pour les nombres hexa repr‚sent‚s ;par les lettres car la valeur ASCII de A est ;$37+$A.Donc si par exp. d3 vaut $B,on le re- ;pr‚sente par le code ascii $37+$B=$42='B'... CCONOUT d3 ;on affiche la lettre (de A à F) jmp DECAL ;on red‚cale le paramètre et on continue ;avec les 4 bits suivants en DECAL FIN RESTORE ;quand on a fini l'opp‚ration avec tous les ;32 bits, on restore les registres empil‚s ENDM END 3) Exercice nr°3 ------------- Voilà la correction de la macro 'BINAIRE'. Pour atteindre les 32 bits du paramètre et pour les afficher à l'‚cran, on utilise l'instruction LSL.L #1,paramètre dans une boucle et suivant la valeur du bit sorti, on affiche un '1' (bit actif) ou un '0' ( bit etteind). L'instruction de branchement conditionnel correspondant peut par exemple ètre bCC (Qui teste si le bit C du CCR est nul: LSL copie le bit sorti dans le bit C du CCR) Pour afficher le '1' ou le '0', on utilise la macro CCONOUT #'1' ou CCONOUT #'0'. NB:Mèmes remarques que pour la macro HEXA en ce qui conscerne l'utilisa- -- tion de labels dans la macro 'BINAIRE'. TEXT BINAIRE MACRO $\1 ;MACRO à 1 paramètre SAUVE ;sauvegarde des registres move.L \1,d1 ;le paramètre dans d1 move #31,d3 ;compteur de boucle pour les d‚calages LOOK move #'0',d0 ;d0 contient le code ascii de 0 lsl.l #1,d1 ;d‚calage d'un bit de d1:Copie du bit dans ;le code C du CCR bcc ZERO ;si le bit est nul (C=0):va en 'zero' move #'1',d0 ;sinon d0 contient le code ascii de '1' ZERO CCONOUT d0 ;on affiche le contenu de d0 (0 ou 1) dbf d3,LOOK ;on recommence avec les 31 autres bits RESTORE ;on restore les registres ENDM ;fini... END 4) Exercice nr°4: -------------- Voilà le listing du programme qui permet de formater une disquette. Il suffisait d'utiliser correctement la fonction FLOPFMT du Gemdos et de la mettre dans une boucle pour pouvoir faire varier le nr° de la piste à formater. Pour demander une confirmation d'‚xecution à l'utilisateur du programme, on affiche un message d'alerte avec PRINTLINE, on attend qu'il enfonce une touche du clavier (avec 'WAIT') et on teste le code ascii de la touche selectionn‚e. (valeur qui retourne dans d0) Si cette touche est 'F' on formate la disquette, sinon on quitte le prg avec la macro TERM (fonction TERM du Gemdos). Si une erreur se produit durant le formatage (d0 n‚gatif après FLOPFMT), on affiche le code d'erreur en DECIMAL. Il faudra d'abord rendre le chiffre à traiter positif avec NEG dn. Le chiffre à traiter (le code d'erreur) sera donc un nombre positif et inf‚rieur à 100 (cf. les codes d'erreur du Gemdos). On effectue une division par 10 de ce chiffre pour obtenir le chiffre des dixaines (avec DIVU #10,dn) du code d'erreur. Le quotient retourne dans le mot de poids faible de dn: c'est le chiffre des dixaine, on l'affiche en lui ajoutant $30 pour obtenir un code ascii (avec CCONOUT). Le reste est dans le mot de poids fort de dn:Il repr‚sente le chiffre des unit‚s du code d'erreur.On SWAP dn et on l'affiche lui aussi. Quand le formatage sera termin‚, on affichera un message signalant que tout est OK. Remarque: --------- ATTENTION, notre programme va bien formater la disquette, mais si vous regardez les informations conscernant la disquette en utili- sant l'option 'INFORMATIONS' du bureau GEM ,on vous indiquera qu'il reste 0 Octets de libre alors qu'il y en a aussi 0 d'utilis‚s... Ceci s'explique par le fait que nous n'avons pas initialis‚ le BOOT SECTOR de la disquette:On ne pourra donc rien y ‚crire car il contient toutes les informations n‚cessaires aux op‚rations de disk... NB:Ceux qui ne possèdent pas PROFIMAT et qui veulent (doivent!) mettre -- le tampon pour FLOPFMT à une adresse PAIRE ne doivent pas ‚crire la DIRECTIVE :'ALIGN.W' en zone BSS. Pour METACOMCO, il existe une DIRECTIVE ‚quivalente:CNOP 0,2 Pour DEVPAC ST: c'est la directive EVEN. Les autres assemblerons le listing et si il ne marche pas, c'est que le tampon pour FLOPFMT n'est pas à une adresse paire. Il suffira alors de r‚server 1 OCTET juste devant le tampon:celui-ci passera donc d'une adresse impaire à une adresse paire (impaire+1). TEXT INCLUDE "INIT_TOS.L" INCLUDE "MACROS.L" SETBLOCK PRINTLINE ATTENTION ;le message d'alerte WAIT ;attente d'une touche:code ascii dans d0 CMPI.B #'F',d0 ;d0='F' ? BEQ FORMAT ;alors FORMAT CMPI.B #'f',d0 ;d0='f' ? BEQ FORMAT ;alors FORMAT TERM ;sinon quitter FORMAT SUPER ;mode SUPERVISEUR clr.l d0 BOUCLE movem.l d0,-(sp) ;on sauvegarde juste d0 move.w #$e5e5,-(sp) ;virgin move.l #$87654321,-(sp) ;mot magic move.w #1,-(sp) ;interleave move.w #0,-(sp) ;face move.w d0,-(sp) ;d0=les diff‚rentes pistes move.w #9,-(sp) ;nb de secteurs par piste move.w #0,-(sp) ;drive A clr.l -(sp) ;l-m=0 pea TAMPON ;adresse du tampon move.w #$a,-(sp) ;Flopfmt trap #14 add.l #26,sp ;mise à jour de SP tst d0 bmi ERROR ;Si d0 est n‚gatif: erreur movem.l (sp)+,d0 ;on restore d0 addi.b #1,d0 ;on incr‚mente le nr° de piste cmpi.b #80,d0 ;a-t-on les 80 pistes ? bne BOUCLE PRINTLINE OK ;pas de probleme, OK GO WAIT ;attente d'une touche USER ;on revient en mode USER TERM ;-> retour ERROR move d0,d5 ;on sauve d0 dans d5 car d0 sera modifi‚ PRINTLINE PROBLEME neg d5 ;d5 devient positif ; affichage DECIMAL de d5 divu #10,d5 ;chiffre des dixaines dans d5.w faible add #$30,d5 ;chiffre=code ascii CCONOUT d5 ;on l'affiche swap d5 ;d5.w faible=reste de la division=chiffre ;des unit‚s de d5 add #$30,d5 ;chiffre=code ascii CCONOUT d5 ;on l'affiche jmp GO ;--> fin DATA ATTENTION DC.B 27,'E','DANGER ! Ce programme FORMATE la disquette,' DC.B ' inserez une disquette VIERGE puis',10,13,'pressez' DC.B ' [F] pour FORMATER la disquette ...' DC.B ' (Ou une autre touche pour QUITTER!)',7,0 OK DC.B 27,'E','Pas d',39,'erreur : OK...',0 PROBLEME DC.B 27,'E',7,'ERREUR de code :-',0 BSS DS.B 20000 ;tampon en ammont de la nouvelle PILE PILE DS.B 1 ;le formatage n‚cessite beaucoup de place... ALIGN.W ;SPECIFIQUE à PROFIMAT !!!!! TAMPON DS.B 10000 ;tampon pour le formatage (adresse PAIRE) SAUV_SP DS.L 1 ;tampon pour SUPER et USER END 5) Exercice nr°5 ------------- Voilà le programme qui rejoue les sons cr‚es avec PRO SOUND DESIGNER. Le programme va attendre qu'on enfonce une touche du clavier puis il la teste (Macro 'WAIT' du gemdos, retour du code et du scancode dans d0). Les touches de Fonction n'ont pas de code ascii mais possèdent toutes un SCANCODE qui les diff‚rencies. Si l'octet de poids faible de d0 contient un code ascii (d0.w diff‚rent de 0), on quitte le prg car cela voudrait dire qu'on a enfonc‚ une autre touche qu'une des 10 touches de fonction. Vous avez ensuite d— chercher les diff‚rents scancodes des touches de fonction pour pouvoir les utiliser ici. Pour cela, il suffisait d'‚crire le programme suivant, TEXT INCLUDE "MACROS.L" AA WAIT ;attente d'une touche SWAP d0 ;d0.b de poids faible = scancode and.l #$FF,d0 ;on ne garde que l'octet de poids faible de ;ce mot (soit le SCANCODE) HEXA d0 ;affichage en HEXA du scancode WAIT ;attente d'une touche CCONOUT #27 CCONOUT #'E' ;on efface l'‚cran jmp AA ;et on recommence END puis de l'assembler ,de l'‚xecuter et d'appuyer sur les touches de fonction pour noter leurs SCANCODES. Le reste du programme doit identifier les diff‚rents scancodes des touches de fonction et jouer un son. Pour tester les valeurs du scancode de la touche enfonc‚e, on compare la valeur du scancode rentr‚ aux valeurs des 10 scancodes des touches de fonction que nous avons plac‚ en zone DATA. En mème temps, on fait varier la valeur d'un registre d'adresse 'an' qui pointe sur les diff‚rentes adresses des sons. Si un scancode est identifi‚, on joue le son point‚ par 'an' en le fournissant comme paramètre à la macro 'DOSOUND', sinon on incr‚mente les registres d'adresse (mode (an)+) pointant sur les DATAs qui repr‚- sentent les scancodes et les adresses des sons. Si finalement aucun scancode n'est reconnu, on recommence le test des touches du clavier au d‚but du programme. Les donn‚es d‚finissant les sons se trouvent dans le fichier PROSOUND.DAT, il suffit de l'inclure en zone DATA dans le listing. NB:Je modifie la valeur d'une VARIABLE SYSTEME dans ce listing (avec -- move.b #0,$484) ceci dans le but d'arrèter le 'BIP' qui se fait entendre quand on appuye sur une touche afin de ne pas perturber le son rejou‚. Je parlerais bientot des VARIABLES SYSTEME... TEXT INCLUDE "INIT_TOS.L" INCLUDE "MACROS.L" SETBLOCK SUPER ;mode SUPERVISEUR PRINTLINE message ;texte move.b #0,$484 ;variable système (mettre ;0 enlève r‚p‚tition et ;bip des touches) TEZT WAIT ;attente d'une touche ;:CODE dans d0 tst.b d0 ;si code ascii diff‚rent de bne STP ;0, alors SToP, sinon swap d0 ;d0.w de poids faible ;devient le SCANCODE lea FONCT,a0 ;a0=adresse des SCANCODES lea VECTEUR,a1 ;a1=adresse des adresses ;des sons de VECTEUR LISONS cmp.b (a0)+,d0 ;compare SCANCODE de la ;touche enfonc‚e (d0) à ;ceux de la table DC.B . move.l (a1)+,a5 ;Pose l'adresse point‚e par ;a1 dans a5 beq SON ;si CMP=oui, va jouer le ;son point‚ par a5 addq.b #1,d1 ;sinon ajoute 1 à d1 cmpi.b #9,d1 ;d1=9 ? beq TEZT ;alors plus de scancodes ;et on revient en 'TEZT' jmp LISONS ;sinon on incr‚mente a0 ;et a1 SON DOSOUND a5 ;Dosound le son point‚ par ;a5 jmp TEZT ;puis on revient en 'TEZT' STP USER ;mode UTILISATEUR TERM ;on quitte DATA MESSAGE DC.B 27,'E','Voilà des sons de PRO SOUND DESIGNER' DC.B ', tapez sur les touches de Fonction :',13,10 DC.B '(Ou une autre touche pour sortir )',7,0 VECTEUR DC.L sound0,sound1,sound2,sound3,sound4,sound5 DC.L sound6,sound7,sound8,sound9 ;les adresses des 10 sons. FONCT DC.B $3B,$3C,$3D,$3E,$3F,$40,$41,$42,$43,$44 ;les scancodes des touches de fonction (F1->F10) ;Donn‚es d‚finissant les sons de PRO SOUND DESIGNER sound0 DC.B 0,214 DC.B 1,0 DC.B 2,215 DC.B 3,0 DC.B 4,215 DC.B 5,0 DC.B 7,248 DC.B 8,16 DC.B 9,16 DC.B 10,16 DC.B 11,32 DC.B 12,73 DC.B 13,0 DC.B 129,2 DC.B 0,0 DC.B 255,0 sound1 DC.B 0,24 DC.B 1,1 DC.B 2,25 DC.B 3,1 DC.B 4,23 DC.B 5,1 DC.B 7,248 DC.B 8,16 DC.B 9,16 DC.B 10,16 DC.B 11,32 DC.B 12,73 DC.B 13,0 DC.B 129,2 DC.B 0,0 DC.B 255,0 sound2 DC.B 0,156 DC.B 1,1 DC.B 2,156 DC.B 3,1 DC.B 4,156 DC.B 5,1 DC.B 7,248 DC.B 8,16 DC.B 9,16 DC.B 10,16 DC.B 11,32 DC.B 12,73 DC.B 13,0 DC.B 129,2 DC.B 0,0 DC.B 255,0 sound3 DC.B 0,22 DC.B 1,2 DC.B 2,21 DC.B 3,2 DC.B 4,23 DC.B 5,2 DC.B 7,248 DC.B 8,16 DC.B 9,16 DC.B 10,16 DC.B 11,32 DC.B 12,73 DC.B 13,0 DC.B 129,2 DC.B 0,0 DC.B 255,0 sound4 DC.B 0,55 DC.B 1,3 DC.B 2,59 DC.B 3,3 DC.B 4,57 DC.B 5,3 DC.B 7,248 DC.B 8,16 DC.B 9,16 DC.B 10,16 DC.B 11,32 DC.B 12,73 DC.B 13,0 DC.B 129,2 DC.B 0,0 DC.B 255,0 sound5 DC.B 0,235 DC.B 1,3 DC.B 2,234 DC.B 3,3 DC.B 4,232 DC.B 5,3 DC.B 7,248 DC.B 8,16 DC.B 9,16 DC.B 10,16 DC.B 11,32 DC.B 12,73 DC.B 13,0 DC.B 129,2 DC.B 0,0 DC.B 255,0 sound6 DC.B 0,70 DC.B 1,5 DC.B 2,72 DC.B 3,5 DC.B 4,71 DC.B 5,5 DC.B 7,248 DC.B 8,16 DC.B 9,16 DC.B 10,16 DC.B 11,32 DC.B 12,73 DC.B 13,0 DC.B 129,2 DC.B 0,0 DC.B 255,0 sound7 DC.B 0,84 DC.B 1,7 DC.B 2,84 DC.B 3,7 DC.B 4,84 DC.B 5,7 DC.B 7,248 DC.B 8,16 DC.B 9,16 DC.B 10,16 DC.B 11,32 DC.B 12,73 DC.B 13,0 DC.B 129,2 DC.B 0,0 DC.B 255,0 sound8 DC.B 0,175 DC.B 1,0 DC.B 2,193 DC.B 3,4 DC.B 4,20 DC.B 5,6 DC.B 7,254 DC.B 8,16 DC.B 9,16 DC.B 10,16 DC.B 11,32 DC.B 12,73 DC.B 13,0 DC.B 129,0 DC.B 93,63 DC.B 255,0 sound9 DC.B 0,175 DC.B 1,0 DC.B 2,193 DC.B 3,4 DC.B 4,232 DC.B 5,4 DC.B 7,254 DC.B 8,16 DC.B 9,16 DC.B 10,16 DC.B 11,32 DC.B 12,73 DC.B 13,0 DC.B 129,0 DC.B 80,88 DC.B 255,0 BSS DS.B 40000 ;pour SETBLOCK PILE DS.B 1 SAUV_SP DS.L 1 ;pour SUPER/USER END 6) Exercice 6 ---------- Voilà le programme qui permet de visualiser le directory d'une disquette. Il fallait simplement utiliser la macro 'SEARCH' et la fonction SEARCH- NEXT du gemdos qui d‚livrent dans le tampon DTA le nom du fichier et cer- tains autres renseignements conscernant le fichier reconnu. Il fallait ensuite afficher le nom de chaque fichier reconnu: Le nom se trouve en DTA+30, pour l'afficher on utilise la macro PRINTLINE. NB:Mèmes remarques que pour le listing nr°4 conscernant l'adresse PAIRE -- du tampon DTA. TEXT INCLUDE "INIT_TOS.L" INCLUDE "MACROS.L" SETBLOCK PRINTLINE DIR ;message SEARCH DTA,#0,PRG ;installe DTA,cherche le prg (L/E) tst d0 ;erreur ? bne FIN ;si ? alors FIN PRINTLINE DTANOM ;en DTANOM se trouve le nom du fichier CCONOUT #13 ;on saute une ligne CCONOUT #10 ;on revient colonne 1 BOUCLE move #$4f,-(SP) ;SEARCH-NEXT trap #1 addq.l #2,SP tst d0 ;encore des prg ? bne FIN ;non ?! Alors FIN PRINTLINE DTANOM ;on affiche le nom du prg CCONOUT #13 ;on saute une ligne CCONOUT #10 ;on revient à la colonne 1 jmp BOUCLE ;et on continue FIN PRINTLINE FINI ;message WAIT ;attente TERM ;salut !! DATA PRG DC.B 'A:\*.*',0 ;= TOUS les fichiers DIR DC.B 27,'E','LE DIRECTORY DE CETTE DISQUETTE EST:',10,13,0 FINI DC.B 13,10,7,'Voilà pour cette Disquette...',0 BSS DS.B 2000 PILE DS.B 1 ALIGN.W ;SPECIFIQUE à PROFIMAT !!! DTA DS.B 30 ;d‚but tampon DTANOM DS.B 14 ;ici DTA+30, le NOM du fichier ZERO DS.B 1 ;octet NUL pour PRINTLINE END PETIT PLUS: ----------- Voilà le listing d'un programme qui va parfaitement illuster les termes de PROGRAMME PERE et PROGRAMME FILS ainsi que les possiblilit‚s de chainage de programme gràce aux fonctions PEXEC et TERM du Gemdos. TEXT INCLUDE "INIT_TOS.L" INCLUDE "MACROS.L" SETBLOCK PRINTLINE MESSAGE ;texte WAIT ;attente PRINTLINE EFFACE ;texte PEXEC ZERO,NUL,PRG,#0 ;Pexec en mode 0 PRINTLINE RETOUR ;texte WAIT ;attente TERM ;retour DATA MESSAGE DC.B 27,'E',7,'Je vais charger le programme SON.PRG' DC.B ' ,je resterais en m‚moire et quand le',13,10 DC.B 'programme se terminera il me redonnera la ' DC.B 'main car je suis le PRG PERE :',0 EFFACE DC.B 27,'E','je charge mon PRG FILS :',0 RETOUR DC.B 27,'E','PRG PERE: COUCOU !!! me revoilà ...',0 NUL DC.B 0 ;pas d'environnenment ZERO DC.B 0 ;pas de ligne de commande PRG DC.B 'A:\SON.PRG',0 ;nom du programme FILS BSS DS.B 200 ;pour SETBLOCK PILE DS.B 1 END ------------------- Voilà pour les corrections. Je vous signale que les macros instructions SAUVE,RESTORE,HEXA,BINAIRE sont pr‚sentes dans le fichier MACROS_2.L et vous sont d‚sormais entiè- rement disponibles. ---------- Il existe aussi des PRG exemples utilisant ces macros instructions dans les fichiers: listing :EXEMPLE.L ‚xecutable:EXEMPLE.PRG Les listings complets des programmes issus des exercices nr°4,5,6 et du programme Exemple ci-dessus sont pr‚sents dans les fichiers: FORMAT.L SON.L DIR.L PERE.L ainsi que les programmes d‚jà assembl‚s: FORMAT.PRG SON.PRG DIR.PRG PERE.PRG Tous ces fichiers sont sur la disquette nr° 1. ---------------------------------------------- PIECHOCKI Laurent 8,impasse Bellevue Suite dans le fichier:VDI.DOC 57980 TENTELING -------
Back to ASM_Tutorial