Pl2 CORRIG 2.DOC/fr
Jump to navigation
Jump to search
----------------------
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