Vous êtes sur la page 1sur 31

Remarques et astuces de programmation en assembleur

1- Charger une valeur littérale dans un registre

movlw B'10001100' ; W = B'10001100'

movwf REGISTRE ; (REGISTRE) = B'10001100' = 0x8C = D'140'

• Equivalence en langage C :

REGISTRE = 0x8C ;

2- Charger un registre avec le contenu d'un autre registre

movf REGISTRE1 , W ; W = (REGISTRE1)

movwf REGISTRE2 ; (REGISTRE2) = (REGISTRE1)

• Equivalence en langage C :

REGISTRE2 = REGISTRE1 ;

3- Echanger le contenu de deux registres : (REGISTRE1) < - > (REGISTRE2)

Il faut utiliser une variable intermédiaire :

REGISTRE_TEMP (registre d'usage général)

movf REGISTRE1 , W ; W = (REGISTRE1)

movwf REGISTRE_TEMP ; (REGISTRE_TEMP) = (REGISTRE1)

1
movf REGISTRE2, W ; W = (REGISTRE2)

movwf REGISTRE1 ; (REGISTRE1) = (REGISTRE2)

movf REGISTRE_TEMP, W ; W = (REGISTRE_TEMP)

movwf REGISTRE2 ; (REGISTRE2) = (REGISTRE_TEMP)

• Equivalence en langage C :

REGISTRE_TEMP = REGISTRE1 ;

REGISTRE1 = REGISTRE2 ;

REGISTRE2 = REGISTRE_TEMP ;

4- Tests de comparaison

4-1- Tests d'égalité

4-1-1- Le contenu du registre est-il nul ?

(REGISTRE) = 0x00 ?

2
movf REGISTRE , f ; (REGISTRE) = (REGISTRE)

btfss STATUS , Z ; test du bit Z

goto non ; Z = 0 c'est-à-dire (REGISTRE) != 0x00

{ bloc d'instructions 1 }

goto suite

non

{ bloc d'instructions 2 }

suite

{ suite du programme }

• Equivalence en langage C :

if (REGISTRE = = 0x00)

// bloc d'instructions 1

else

// bloc d'instructions 2

4-1-2- Le contenu du registre est-il différent de zéro ?

(REGISTRE) != 0x00 ?

3
movf REGISTRE , f ; (REGISTRE) = (REGISTRE)

btfsc STATUS , Z ; test du bit Z

goto non ; Z = 1 c'est-à-dire (REGISTRE) = 0x00

{ bloc d'instructions 1 }

goto suite

non

{ bloc d'instructions 2 }

suite

{ suite du programme }

• Equivalence en langage C :

if (REGISTRE != 0x00)

// bloc d'instructions 1

4
else

// bloc d'instructions 2

4-1-3- Le contenu du registre est-il égal à une certaine valeur ?

(REGISTRE) = 0x3F ?

movlw 0x3F ; W = 0x3F

subwf REGISTRE, W ; W = (REGISTRE) - 0x3F

btfss STATUS, Z ; test du bit Z

goto non ; Z = 0 c'est-à-dire (REGISTRE) != 0x3F

{ bloc d'instructions 1 }

goto suite

non

5
{ bloc d'instructions 2 }

suite

{ suite du programme }

• Equivalence en langage C :

if (REGISTRE = = 0x3F)

// bloc d'instructions 1

else

// bloc d'instructions 2

4-1-4- Le contenu du registre est-il différent d'une certaine valeur ?

(REGISTRE) != 0x3F ?

6
movlw 0x3F ; W = 0x3F

subwf REGISTRE, W ; W = (REGISTRE) - 0x3F

btfsc STATUS, Z ; test du bit Z

goto non ; Z = 1 c'est-à-dire (REGISTRE) = 0x3F

{ bloc d'instructions 1 }

goto suite

non

{ bloc d'instructions 2 }

suite

{ suite du programme }

• Equivalence en langage C :

if (REGISTRE != 0x3F)

7
{

// bloc d'instructions 1

else

// bloc d'instructions 2

4-1-5- Le contenu du registre est-il égal au contenu d'un autre registre ?

(REGISTRE1) = (REGISTRE2) ?

movf REGISTRE2 , W ; W = (REGISTRE2)

subwf REGISTRE1, W ; W = (REGISTRE1) - (REGISTRE2)

btfss STATUS, Z ; test du bit Z

8
goto non ; Z = 0 c'est-à-dire (REGISTRE1) != (REGISTRE2)

{ bloc d'instructions 1 }

goto suite

non

{ bloc d'instructions 2 }

suite

{ suite du programme }

• Equivalence en langage C :

if (REGISTRE1 = = REGISTRE2)

// bloc d'instructions 1

else

// bloc d'instructions 2

4-1-6- Le contenu du registre est-il différent du contenu d'un autre registre ?

(REGISTRE1) != (REGISTRE2) ?

9
movf REGISTRE2 , W ; W = (REGISTRE2)

subwf REGISTRE1, W ; W = (REGISTRE1) - (REGISTRE2)

btfsc STATUS, Z ; test du bit Z

goto non ; Z = 1 c'est-à-dire (REGISTRE1) = (REGISTRE2)

{ bloc d'instructions 1 }

goto suite

non

{ bloc d'instructions 2 }

suite

{ suite du programme }

• Equivalence en langage C :

if (REGISTRE1 != REGISTRE2)

10
// bloc d'instructions 1

else

// bloc d'instructions 2

4-2- Tests de supériorité

4-2-1 - Le contenu du registre est-il strictement supérieur à une certaine valeur ?

(REGISTRE) > 0x3F ?

Les valeurs sont supposées en binaire naturel.

movf REGISTRE , W ; W = (REGISTRE)

11
sublw 0x3F ; W = 0x3F - (REGISTRE)

btfsc STATUS, C ; test du bit C (Carry)

goto non ; C = 1 c'est-à-dire 0x3F >= (REGISTRE)

{ bloc d'instructions 1 }

goto suite

non

{ bloc d'instructions 2 }

suite

{ suite du programme }

• Equivalence en langage C :

if (REGISTRE > 0x3F)

// bloc d'instructions 1

else

// bloc d'instructions 2

4-2-2 - Le contenu du registre est-il supérieur ou égal à une certaine valeur ?

(REGISTRE) >= 0x3F ?

Les valeurs sont supposées en binaire naturel.

12
movlw 0x3F ; W = 0x3F

subwf REGISTRE, W ; W = (REGISTRE) - 0x3F

btfss STATUS, C ; test du bit C (Carry)

goto non ; C = 0 c'est-à-dire (REGISTRE) < 0x3F

{ bloc d'instructions 1 }

goto suite

non

{ bloc d'instructions 2 }

suite

{ suite du programme }

• Equivalence en langage C :

if (REGISTRE >= 0x3F)

13
// bloc d'instructions 1

else

// bloc d'instructions 2

4-2-3 - Le contenu du registre est-il strictement inférieur à une certaine valeur ?

(REGISTRE) < 0x3F ?

Les valeurs sont supposées en binaire naturel.

movlw 0x3F ; W = 0x3F

subwf REGISTRE, W ; W = (REGISTRE) - 0x3F

btfsc STATUS, C ; test du bit C (Carry)

goto non ; C = 1 c'est-à-dire (REGISTRE) >= 0x3F

{ bloc d'instructions 1 }

14
goto suite

non

{ bloc d'instructions 2 }

suite

{ suite du programme }

• Equivalence en langage C :

if (REGISTRE < 0x3F)

// bloc d'instructions 1

else

// bloc d'instructions 2

4-2-4 - Le contenu du registre est-il inférieur ou égal à une certaine valeur ?

(REGISTRE) <= 0x3F ?

Les valeurs sont supposées en binaire naturel.

15
movf REGISTRE , W ; W = (REGISTRE)

sublw 0x3F ; W = 0x3F - (REGISTRE)

btfss STATUS, C ; test du bit C (Carry)

goto non ; C = 0 c'est-à-dire 0x3F < (REGISTRE)

{ bloc d'instructions 1 }

goto suite

non

{ bloc d'instructions 2 }

suite

{ suite du programme }

• Equivalence en langage C :

if (REGISTRE <= 0x3F)

16
// bloc d'instructions 1

else

// bloc d'instructions 2

4-2-5 - Le contenu du registre est-il supérieur ou égal au contenu d'un autre registre ?

(REGISTRE1) >= (REGISTRE2) ?

Les valeurs sont supposées en binaire naturel.

movf REGISTRE2 , W ; W = (REGISTRE2)

subwf REGISTRE1, W ; W = (REGISTRE1) - (REGISTRE2)

btfss STATUS, C ; test du bit C (Carry)

goto non ; C = 0 c'est-à-dire (REGISTRE1) < (REGISTRE2)

17
{ bloc d'instructions 1 }

goto suite

non

{ bloc d'instructions 2 }

suite

{ suite du programme }

• Equivalence en langage C :

if (REGISTRE1 >= REGISTRE2)

// bloc d'instructions 1

else

// bloc d'instructions 2

4-2-6 - Le contenu du registre est-il strictement inférieur au contenu d'un autre registre
?

(REGISTRE1) < (REGISTRE2) ?

Les valeurs sont supposées en binaire naturel.

18
movf REGISTRE2 , W ; W = (REGISTRE2)

subwf REGISTRE1, W ; W = (REGISTRE1) - (REGISTRE2)

btfsc STATUS, C ; test du bit C (Carry)

goto non ; C = 1 c'est-à-dire (REGISTRE1) >= (REGISTRE2)

{ bloc d'instructions 1 }

goto suite

non

{ bloc d'instructions 2 }

suite

{ suite du programme }

• Equivalence en langage C :

if (REGISTRE1 < REGISTRE2)

19
// bloc d'instructions 1

else

// bloc d'instructions 2

5- Boucle Do While

Exemple :

debut

{ bloc d'instructions }

20
movf REGISTRE , f

btfsc STATUS , Z

goto debut

suite

{ suite du programme }

• Equivalence en langage C :

do

// bloc d'instructions

while (REGISTRE = = 0x00) ;

6- Boucle While

Exemple :

21
debut

movlw 0xE8 ; W = 0xE8

subwf REGISTRE, W ; W = (REGISTRE) - 0xE8

btfss STATUS , Z

goto suite

{ bloc d'instructions }

goto debut

suite

{ suite du programme }

• Equivalence en langage C :

while (REGISTRE = = 0xE8)

// bloc d'instructions

7- Boucle FOR

Une variable (1 octet) sert de compteur.

Exemple :

Pour exécuter le bloc d'instructions 20 fois, la valeur initiale du compteur doit être 21 :

22
movlw D'21' ; W = D'21'

movwf COMPTEUR ; (COMPTEUR) = D'21' pour 20 boucles

debut

decfsz COMPTEUR , f ; (COMPTEUR) = (COMPTEUR) - 1

goto boucle ; (COMPTEUR) != 0

goto suite ; (COMPTEUR) = 0

boucle

{ bloc d'instructions }

goto debut

23
suite

{ suite du programme }

N.B. Avec (COMPTEUR) = 0xFF en valeur initiale, on effectue 254 boucles.

Avec (COMPTEUR) = 0x00 en valeur initiale, on effectue 255 boucles.

Avec (COMPTEUR) = 0x01 en valeur initiale, on effectue 0 boucle.

• Equivalence en langage C

for (COMPTEUR = 20 ; COMPTEUR > 0 ; COMPTEUR--)

// bloc d'instructions

8- Manipulation de bits. Les masques

8-1- Mettre à 0 certains bits d'un registre

Exemple : on veut mettre à 0 les bits 1, 2, 4 et 6, les autres bits étant inchangés :

B'u0u0u00u'

movlw B'10101001' ; W = B'10101001' (on appelle ça un masque)

andwf REGISTRE , f ; fonction ET logique

Valeur initiale : (REGISTRE) = B'11010101'

Valeur finale : (REGISTRE) = B'10000001'

24
N.B. S'il n'y a qu'un seul bit à mettre à 0, il faut simplement utiliser l'instruction bcf.

S'il faut mettre tous les bits à 0, il faut simplement utiliser l'instruction clrf REGISTRE.

8-2- Mettre à 1 certains bits d'un registre

Exemple : on veut mettre à 1 les bits 1, 2, 4 et 6, les autres bits étant inchangés :

B'u1u1u11u'

movlw B'01010110' ; W = B'01010110' (masque)

iorwf REGISTRE , f ; fonction OU logique

Valeur initiale : (REGISTRE) = B'11010101'

Valeur finale : (REGISTRE) = B'11010111'

N.B. s'il n'y a qu'un seul bit à mettre à 1, il faut simplement utiliser l'instruction bcf.

8-3- Inverser certains bits d'un registre

Exemple : on veut complémenter les bits 1, 2, 4 et 6, les autres bits étant inchangés.

movlw B'01010110' ; W = B'01010110' (masque)

xorwf REGISTRE , f ; fonction logique OU exclusif

Valeur initiale : (REGISTRE) = B'11010101'

Valeur finale : (REGISTRE) = B'10000011'

25
N.B. s'il faut inverser tous les bits, il faut simplement utiliser l'instruction comf REGISTRE ,
f

9- Tables de données

On utilise la technique de l'adressage relatif.

• Exemple :

On désire effectuer l'opération arithmétique : y = 10x +1

Ainsi, pour x =D'16' : y = D'161'

Cela peut se faire simplement avec un tableau de données.

On commence par créer la routine table.

Pour des raisons de simplicité, l'adresse de début de cette routine peut être (pour un
microcontrôleur 16F84A) :

• 0x100
• 0x200
• 0x300

; xxxxxxxxxxx

; Routine table

; xxxxxxxxxxx

org 0x0300 ; adresse de début de la table

table

addwf PCL , f ; (PCL) = (PCL) + W

retlw D'1'

retlw D'11'

retlw D'21'

retlw D'31'

26
retlw D'41'

retlw D'51'

retlw D'61'

retlw D'71'

retlw D'81'

retlw D'91'

retlw D'101'

retlw D'111'

retlw D'121'

retlw D'131'

retlw D'141'

retlw D'151'

retlw D'161'

retlw D'171'

retlw D'181'

retlw D'191'

retlw D'201'

retlw D'211'

retlw D'221'

retlw D'231'

retlw D'241'

retlw D'251'

; Fin de la routine table

; xxxxxxxxxxxxxxxxxx

27
Avec un début de routine à l'adresse 0x300, l'instruction retlw D'1' se trouve à l'adresse
0x301, retlw D'11' à l'adresse 0x302 etc...

La table peut contenir jusqu'à 255 éléments (0x301 à 0x3FF).

Ici, notre table possède 26 éléments donc pas de problème de taille.

Dans le programme principal, pour appeler la routine, il faut au préalable charger le registre
spécial PCLATH avec la valeur 0x03 (0x02 si l'adresse de début est 0x200 etc ...) :

movlw 0x03 ; W = 0x03

movwf PCLATH ; (PCLATH) = 0x03

movlw D'16' ; W = D'16' : 16ème ligne de la table

call table

movwf resultat ; (resultat) = D'161'

Adressage indirect :

Registres FSR et INDF

• FSR est un registre spécial situé à l'adresse 0x04 (en banque 0) de la mémoire des
données (Data RAM).

Ce registre est également accessible en banque 1 (à l'adresse 0x84), en banque 2 (à


l'adresse 0x104) et en banque 3 (à l'adresse 0x184),

Ce registre contient une adresse (de la mémoire des données).

On dit que FSR est un "pointeur".

• Le registre spécial INDF contient la valeur du registre pointé par le registre FSR
(on parle d'adressage indirect).

INDF n'est pas un registre physique.

28
-> Exemple n°1 : lecture du port B

Intéressons-nous au registre PORTB (adresse 0x06 de la mémoire des données).

Supposons que le contenu de ce registre est B'10001111'.

movf PORTB, W ; lecture du port B : B'10001111' est chargé dans l'accumulateur

Le même résultat est obtenu par adressage indirect, de la manière suivante :

movlw H'06' ; on charge 0x06 dans l'accumulateur

movwf FSR ; on charge 0x06 (= adresse du registre PORTB) dans le registre FSR

movf INDF, W ; lecture du port B : B'10001111' est chargé dans l'accumulateur

-> Exemple n°2 : écriture du port B

movlw B'00111100' ; B'00111100' est chargé dans l'accumulateur

movwf PORTB ; Ecriture du port B : B'00111100' est chargé dans le port B

La même chose par adressage indirect :

movlw H'06' ; on charge 0x06 dans l'accumulateur

movwf FSR ; on charge 0x06 (= adresse du registre PORTB) dans le registre FSR

movlw B'00111100' ; B'00111100' est chargé dans l'accumulateur

movwf INDF ; Ecriture du port B : B'00111100' est chargé dans le port B

-> Exemple n°3 : Effacement de la mémoire RAM du PIC 16F84A

29
En pratique, il n'est pas judicieux d'utiliser l'adressage indirect dans les examples 1 et 2.

Voici un example où l'usage de l'adressage indirect est très efficace (pour optimiser la taille
du programme) :

Il s'agit d'effacer les 68 octets d'usage général de la mémoire RAM, situés aux adresses
0x0C à 0x4F :

movlw 0x0C

movwf FSR ; on charge l'adresse de début (0x0C)

debut

clrf INDF ; effacement du contenu du registre pointé par FSR

incf FSR, f ; on incrémente l'adresse

movlw 0x50 ; adresse de fin + 1 (0x50)

subwf FSR, W

btfss STATUS, Z ; on teste si (FSR) = 0x50

goto debut ; non : on recommence

suite

...

soit seulement 8 instructions (et 477 cycles).

N.B.

Par adressage direct, il faut aligner 68 instructions, ce qui est gourmand en mémoire de
programme.

clrf 0x0C

clrf 0x0D

...

clrf 0x4F

30
Par contre, l'exécution demande seulement 68 cycles (optimisation de la vitesse d'exécution).

31

Vous aimerez peut-être aussi