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