Pour ce faire, nous allons tenter d'envoyer deux phrases à l'imprimante. Ces phrases sont placées en mémoire au préalable (voir les variables maPhrase et maPhrase2). Assumons que nous possédons une fonction de communication avec l'imprimante envoieDonneesImprimante, qui prend en entrée deux valeurs:
L'adresse du premier caractère en mémoire, placée dans R1;
L'adresse du dernier caractère + 1 en mémoire, placée dans R2;
Comme cette fonction communique avec un périphérique, elle n'est accessible que via un appel système. Pour faire un appel système à l'imprimante, faisons l'hypothèse que nous pouvons faire SVC #10.
Configuration
Dans le panneau configuration, entrez les informations suivantes:
Cocher "Activer"
Type "IRQ"
Écrire "500" dans "cycles" et "cycles (premier)"
De cette manière, nous simulerons une imprimante qui dit qu'elle a terminé à chaque 500 cycles. Normalement, une imprimante n'émet pas des interruptions périodiques comme ça: elle les émettrait seulement lorsqu'elle a effectivement terminé d'imprimer ce qu'on lui a demandé. Nous utilisons cette technique seulement pour les bienfaits de la démonstration.
Activer
Type
cycles
cycles (premier)
Vitesse d'exécution : ms
Français
SECTION INTVEC
; début de la table des vecteurs d'interruption
B init ; reset
NOP ; instruction indéfinie (non supportée)
B interruptionLogicielle ; interruption logicielle
NOP ; "fetch" invalide (non supportée)
NOP ; accès mémoire invalide (non supportée)
NOP ; ne rien mettre ici!
B interruptionIRQ ; IRQ
NOP ; FIQ
SECTION CODE
init
; Initialisation de la pile
LDR SP, =pile
ADD SP, SP, #64
; ------------------------------------------------------------------
; Début du programme principal
; Ce programme veut envoyer deux chaînes de caractères à l'imprimante.
; Il devra le faire via des appels systèmes (grâce à l'instruction SVC)
; ------------------------------------------------------------------
main
; Utilisons R5 pour charger "maPhrase" (R5=0), et "maPhrase2" (R5=1)
MOV R5, #0
debut
CMP R5, #0
LDREQ R1, =maPhrase
LDRNE R1, =maPhrase2
; Cette fonction placera l'adresse de fin dans R2.
BL trouveAdresseDeFin
; Appel au système qui interagit avec l'imprimante
SVC #10
; On attend que l'imprimante soit prête
; Supposons que lorsque l'imprimante est prête, R0 sera mis à 1.
MOV R9, #0
attenteImprimante
CMP R9, #0
BEQ attenteImprimante
; L'imprimante est prête à recevoir de nouveaux caractères
ADD R5, R5, #1
B debut
; ------------------------------------------------------------------
; Fonction déterminant l'adresse de fin d'une chaîne de caractères.
; Pour ce faire, elle parcourt la chaîne jusqu'à ce qu'elle trouve
; le caractère '0'.
; Accepte en entrée:
; R1: adresse du premier caractère dans la chaîne
; Retourne en sortie:
; R2: adresse du dernier caractère dans la chaîne + 1
; ------------------------------------------------------------------
trouveAdresseDeFin
PUSH {R3}
; Commençons au premier caractère
MOV R2, R1
boucleLecture
; Lire un caractère à la fois (LDRB = LDR Byte, soit lire un octet)
LDRB R3, [R2], #1
; Recommencer tant que le caractère ne soit pas '0'.
CMP R3, #0
BNE boucleLecture
POP {R3}
BX LR
; ------------------------------------------------------------------
; Routine de traitement de l'interuption logicielle
; Assume que les valeurs suivantes ont été placées dans les registres:
; R1: adresse du début de la chaîne de caractères à envoyer
; R2: adresse de fin de la chaîne de caractères à envoyer
; ------------------------------------------------------------------
interruptionLogicielle
; Préparons une pile pour le mode SVC
LDR SP, =pileSVC
ADD SP, SP, #64
PUSH {LR}
BL envoieDonneesImprimante
POP {LR}
; fin de la routine de traitement de l'interruption logicielle
SUBS PC, LR, #4
; ------------------------------------------------------------------
; Fonction système qui simule l'envoi de données à l'imprimante.
; Accepte en entrée:
; R1: adresse du début de la chaîne de caractères à envoyer
; R2: adresse de fin de la chaîne de caractères à envoyer
;
; **Elle ne peut être appelée qu'en mode SVC.**
; ------------------------------------------------------------------
envoieDonneesImprimante
PUSH {R0,R5} ; De quelle pile s'agit-il ici?
; Valider que nous sommes bien dans le mode SVC
MRS R0, CPSR
AND R0, R0, #0x1F
ASSERT R0=0x13 ; 0x13, soit 0b10011, correspond au mode SVC
boucleImprimante
CMP R1, R2
BEQ finBoucleImprimante
; Lecture d'un caractère
LDRB R5, [R1], #1
; L'envoi d'un caractère à l'imprimante consisterait à un STR à l'adresse
; correspondant à l'imprimante sur le bus d'adresses.
; STRB R5, [...]
B boucleImprimante
finBoucleImprimante
POP {R0,R5}
BX LR
; ------------------------------------------------------------------
; Routine de traitement de l'interruption matérielle IRQ
; Ici, nous assumons qu'il n'y a qu'un seul périphérique pouvant générer
; une telle interruption, soit l'imprimante.
; Lorsque l'imprimante est prête à recevoir un autre caractère, elle émet
; une interruption IRQ
; ------------------------------------------------------------------
interruptionIRQ
; pour traiter cette interruption, nous n'avons qu'à placer une valeur
; différente de 0 dans R9
MOV R9, #1
; fin de la routine de traitement de l'interruption matérielle IRQ
SUBS PC, LR, #4
SECTION DATA
maPhrase ASSIGN8 "Caracteres a envoyer a l'imprimante",0
maPhrase2 ASSIGN8 "Autres caracteres a envoyer", 0
pile ALLOC32 16
pileSVC ALLOC32 16