GUIDE PRATIQUE — 68HC11 Assembleur, Modes d'adressage & Jeux d'instructions — TP 1. LA SYNTAXE — Lire et écrire une ligne assembleur Chaque ligne d'un programme 68HC11 a cette structure : Champ LABEL MNÉMONIQUE OPÉRANDE ;commentaire Rôle Nom optionnel de la ligne (pour les sauts) L'instruction à exécuter La donnée ou adresse + note explicative Exemple DEBUT: LDAA #$1F ; charge A avec 31 Exemple 2 LOOP: BNE LOOP ; retour si Z=0 Le LABEL est obligatoire uniquement quand tu veux sauter vers cette ligne (BNE, BRA...). Sinon, tu peux l'omettre. Les préfixes de base numérique pour les valeurs Préfixe Base Exemple $ Hexadécimal $1F = 31 en décimal % Binaire %00011111 = 31 @ Octal @37 = 31 (rien) Décimal 31 'C' ASCII code ASCII de la lettre C 2. MODES D'ADRESSAGE — Comprendre chaque mode L'opérande d'une instruction peut pointer vers la donnée de 7 façons différentes. C'est ça, le mode d'adressage. Mode IMMÉDIAT → #valeur Tu fournis la valeur directement dans l'instruction. Le MCU n'a pas besoin d'aller chercher en mémoire. LDAA #$4F ; Registre A = 0x4F (79 en décimal) LDAB #%10110000 ; Registre B = 0b10110000 LDX #$1000 ; Registre X = 0x1000 LDAA #'A' ; Registre A = 65 (code ASCII de 'A') Utilise ce mode pour : initialiser un registre, charger une constante connue à l'avance, définir un masque pour les opérations logiques. Mode DIRECT → adresse 1 octet ($00 à $FF) L'adresse mémoire est codée sur 1 octet. Le MCU considère automatiquement que l'adresse complète est $00xx. LDAA $20 ; A = contenu de la case mémoire $0020 STAA $0F ; stocke A dans la case $000F Utilise ce mode pour accéder aux variables RAM dans la page $0000-$00FF. Plus rapide et plus court que le mode étendu (économise 1 octet d'instruction). ⚠ Ne fonctionne que si l'adresse est entre $0000 et $00FF ! Mode ÉTENDU → adresse 2 octets L'adresse est sur 2 octets complets. Permet d'accéder à n'importe quelle case mémoire du MCU. LDAA $1000 STAB $FFF0 LDAA portb ; A = contenu de la case $1000 ; stocke B à l'adresse $FFF0 (zone registres I/O) ; si portb EQU $1004, même chose Utilise ce mode pour accéder aux registres I/O du 68HC11 (PORTA, PORTB...) ou à des adresses RAM/ROM en dehors de la page zéro. Mode INDEXÉ → offset, X ou offset, Y L'adresse effective = registre X (ou Y) + un décalage (offset). Le registre X/Y contient l'adresse de base, l'offset se déplace à partir de là. LDX #$1000 LDAA 0,X STAB 5,X LDAB 2,Y ; X pointe sur la base = $1000 ; A = contenu de $1000 + 0 = $1000 ; stocke B à $1000 + 5 = $1005 ; B = contenu de (Y + 2) Utilise ce mode pour parcourir des tableaux/buffers en mémoire. Tu fais avancer X avec INX, et tu accèdes à chaque élément sans changer l'instruction. Exemple concret — parcourir un tableau de 5 octets : LDX #$0050 LDAA #5 LOOP: CLR 0,X INX DECA BNE LOOP ; X = adresse de début du tableau ; compteur ; met à zéro chaque case ; X pointe sur la case suivante ; décrémente compteur ; recommence si pas fini Mode INHÉRENT → pas d'opérande L'instruction agit sur des registres implicites. Pas besoin de préciser d'adresse ou de valeur. TAB TBA INCA DECB MUL ABA CLR ; B = A (copie A vers B) ; A = B (copie B vers A) ; A = A + 1 ; B = B - 1 ; D = A x B (résultat 16 bits dans D) ; A = A + B ; met à zéro Utilise ce mode pour les opérations entre registres : additions rapides, copies, incréments. Ce sont les instructions les plus rapides du jeu. Mode RELATIF → étiquette (pour les sauts) Utilisé uniquement par les instructions de branchement (BRA, BEQ, BNE...). Le saut est calculé relativement à la position actuelle du PC. En pratique : tu mets une étiquette (label), l'assembleur calcule tout seul le décalage. T1: LDY DEY BNE END #$0064 T1 ; Y = 100 (compteur) ; Y = Y - 1 ; si Y ≠ 0, retour à T1 → boucle de 100 tours ⚠ Le branchement relatif est limité à ±127 octets. Si trop loin, utiliser JMP (mode étendu) à la place. Utilise BRA pour saut inconditionnel, BEQ si Z=1, BNE si Z=0, BGT/BGE/BLT/BLE pour comparaisons signées. Mode MANIPULATION DE BIT → BSET / BCLR / BRSET / BRCLR Permet de modifier ou tester des bits précis dans une case mémoire directement, sans passer par un registre. BSET $00 %00000011 BCLR $00 %00000011 BRSET $10 $80 SUITE BRCLR $10 $80 SUITE ; met à 1 les bits 0 et 1 de l'adresse $0000 ; met à 0 les bits 0 et 1 de l'adresse $0000 ; si bit 7 de $0010 = 1 → saute à SUITE ; si bit 7 de $0010 = 0 → saute à SUITE Utile pour contrôler des I/O bit par bit (allumer/éteindre un LED, tester l'état d'un capteur) sans toucher aux autres bits du port. 3. LES DIRECTIVES ASSEMBLEUR Directive Syntaxe Utilité ORG ORG $C000 Définit l'adresse de départ du programme END END Fin du programme (obligatoire) EQU portb EQU $1004 Définit une constante symbolique (comme un #define en C) FCB TAB FCB $01,$02,$03 Déclare un tableau de constantes 8 bits FDB FDB $1234,$ABCD Déclare des constantes 16 bits FCC FCC /Bonjour/ Déclare une chaîne de caractères ASCII RMB VAR RMB 1 Réserve N octets en RAM (pour une variable) Exemple de structure complète d'un programme : ORG RMB $0000 1 ; réserve 1 octet pour la variable CPTR ORG portb EQU DDRA EQU $C000 $1004 $1003 ; le code commence à $C000 ; PORTB = adresse $1004 ; DDRA = registre direction port A CPTR LDAA #$FF STAA DDRA LDAA #$00 STAA portb LOOP: BRA LOOP END ; configure PORTA en sortie ; éteint tous les bits de PORTB ; boucle infinie 4. JEUX D'INSTRUCTIONS — Résumé par catégorie Chargement / Stockage / Transfert Instruction Exemple Effet LDAA / LDAB LDAA #$10 Charge A ou B depuis mémoire ou valeur immédiate LDD LDD $1000 Charge le registre D (16 bits = A:B) LDX / LDY LDX #$0050 Charge le registre d'index X ou Y STAA / STAB STAA $0020 Stocke A ou B en mémoire STD / STX / STY STX $0030 Stocke D / X / Y en mémoire TAB / TBA TAB Transfert A→B ou B→A (inhérent) Opérations arithmétiques Instruction Exemple Effet ADDA / ADDB ADDA #$05 A = A + valeur ADDD ADDD #$0010 D = D + valeur 16 bits SUBA / SUBB SUBA $20 A = A - valeur MUL MUL D = A × B (résultat 16 bits) IDIV IDIV X = D / X (division entière) INCA / INCB INCA A = A + 1 (rapide, pas de carry) DECA / DECB DECB B=B-1 INX / INY INX X=X+1 DEX / DEY DEY Y=Y-1 Opérations logiques Instruction Exemple Effet ANDA / ANDB ANDA #%11110000 A = A AND masque → isoler des bits ORAA / ORAB ORAA #%00001111 A = A OR masque → forcer des bits à 1 EORA / EORB EORA #%11111111 A = A XOR masque → inverser des bits COMA / COMB COMA A = complément à 1 de A NEGA / NEGB NEGA A = complément à 2 de A (opposé) CLRA / CLRB CLRA A=0 Comparaison et branchements Principe : CMPA compare A avec une valeur et positionne les flags (Z, N, C...). Ensuite, une instruction de branchement vérifie ces flags. LDAA #$0A ; A = 10 CMPA $20 ; compare A avec le contenu de $0020 BEQ EGAL ; saute si A == $0020 BGT PLUS_GRAND ; saute si A > $0020 BLT PLUS_PETIT ; saute si A < $0020 Instruction Condition Signification BRA Toujours Saut inconditionnel (comme goto) BEQ Z=1 Saut si égal (Equal) BNE Z=0 Saut si non égal (Not Equal) BGT Z=0, N=V Saut si supérieur (signé) BGE N=V Saut si supérieur ou égal BLT N≠V Saut si inférieur (signé) BLE Z=1 ou N≠V Saut si inférieur ou égal JMP Toujours Saut inconditionnel longue distance (étendu) Décalage et rotation Instruction Exemple Effet LSLA / LSLB LSLA Décalage logique gauche (×2) — bit 7 va dans C LSRA / LSRB LSRB Décalage logique droite (÷2) — bit 0 va dans C ROLA / ROLB ROLA Rotation gauche à travers le carry RORA / RORB RORA Rotation droite à travers le carry LSL ×2 / LSR ÷2 = alternative rapide à la multiplication/division par 2 sans MUL/DIV. Sous-programmes et pile Instruction Exemple Effet JSR JSR INIT Appel de sous-programme (sauvegarde PC dans la pile) BSR BSR DELAY Idem JSR mais saut relatif (court) RTS RTS Retour de sous-programme (restaure PC) PSHA / PSHB PSHA Empile A ou B sur la pile (SP--) PULA / PULB PULA Dépile vers A ou B (SP++) RTI RTI Retour d'interruption (restaure tout le contexte) 5. EXEMPLES COMPLETS POUR TP Exemple 1 — Boucle de comptage (100 itérations) ORG $C000 LDAB #100 LOOP: NOP DECB BNE LOOP END ; compteur = 100 ; corps de la boucle (ici rien) ; compteur - 1 ; si B ≠ 0, recommencer Exemple 2 — Allumer PORTB (tous les bits à 1) portb EQU $1004 DDRB EQU $1005 ORG $C000 LDAA #$FF STAA DDRB STAA portb LOOP: BRA LOOP END ; registre direction PORTB ; PORTB = tout en sortie ; allume tous les bits Exemple 3 — Addition de deux nombres en mémoire NB1 NB2 RES ORG RMB RMB RMB $0000 1 1 1 ORG $C000 LDAA #$25 STAA NB1 LDAA #$13 STAA NB2 LDAA NB1 ADDA NB2 STAA RES END ; variable 1 à $0000 ; variable 2 à $0001 ; résultat à $0002 ; NB1 = 37 ; NB2 = 19 ; A = NB1 + NB2 ; stocke le résultat Exemple 4 — Parcourir un tableau avec mode indexé TAB ORG FCB $0010 $01,$02,$03,$04,$05 ORG $C000 LDX #TAB LDAB #5 LOOP: LDAA 0,X INCA STAA 0,X INX DECB BNE LOOP END ; tableau de 5 octets en $0010 ; X = adresse de début du tableau ; compteur = 5 éléments ; A = tableau[i] ; A = A + 1 (traitement) ; on remet en mémoire ; i++ ; compteur-- ENSAM Meknès — Systèmes Numériques de Commande — Génie Électromécanique