Bienvenue aux nouveaux arrivants sur FantasPic !

- Pensez à lire les règles durant votre visite, il n'y en a pas beaucoup, mais encore faut-il les respecter .
- N’hésitez pas à faire des remarques et/ou suggestions sur le Forum, dans le but de l'améliorer et de rendre vos prochaines visites plus agréables.
- Vous pouvez regarder votre "panneau de l'utilisateur" afin de configurer vos préférences.
- Un passage par "l'utilisation du forum" est recommandé pour connaître les fonctionnalités du forum.

--- L’équipe FantasPic ---
Commentez, partagez et proposez des Tutos en langage ASM !
Une manière de diffuser des routines utilitaires
JJE
Passioné
Passioné
Messages : 399
Âge : 83
Enregistré en : novembre 2017
Localisation : Picardie

#1 Message par JJE » dim. 8 juil. 2018 19:32

Bonjour à tous,
je reprends le sujet routines signées 8 bits proposé ici pour développer l'idée que, quitte à proposer une routine, il faut qu'elle soit le plus facile possible à mettre en oeuvre.
Bien sûr, si l'utilisateur a moins de travail, c'est que l'auteur en a fait plus. J'espère que cet exemple pourra servir de "modèle" à d'autres.
Je propose ci-dessous d'habiller les routines d'addition et de soustraction 8 bits signés. Il reste à l'utilisateur 2 lignes de code à ajouter à son développement pour mettre en oeuvre ces routines
les programmes proposés sont suivis par quelques explications.
Un espace mémoire de 3 octets est réservé en fond de chaque banque, ceci évite les changements de banque et on peut invoquer les macros quelle que soit la banque active, la seule contrainte étant que les deux ou trois variables utilisées soient dans la même banque.

Code : Tout sélectionner

;**********************************************************************
;
   Test des routines arithmétique 8 bits signés                      *  
;                                                                     *
;**********************************************************************
;
                                                                     *
;
    NOM:      Test8bitsSignés                                        *
;
    Date:     28/05/2018                                             *
;
    Version:  2.0                                                    *
;
    Circuit:  sans objet                                             *
;
    Auteur:   JJE                                                     *
;
                                                                     *
;**********************************************************************
;
                                                                     *
;
    Fichiers requis: 
;        8bs.inc
;                                                                     *
;**********************************************************************
;
                                                                     *
;
    Notes: 
;    Ce petit programme permet de tester les routines 8bits signés     *
;
    sous le simulateur de MPLAB
;     lancez en pas à pas et 
;    suivez les indications données dans les remarques
;
;
     Dans Configure/Select Device, choisir un Pic Mid-Range 
;    à 4 pages de mémoire
;                                                                     *
;**********************************************************************



STATUS    EQU    .3
RP0        EQU    .5
RP1        EQU    .6
C        EQU    0
Z        EQU    2

    ifndef __MAXRAM
        
#DEFINE __MAXRAM 0x1FF
    endif

;*********************************************************************
;
                             MACROS                                  *
;*********************************************************************

;
 La banque active étant supposée contenir la variable Source,
;
 cette macro active la banque contenant la variable But 
; en le minimum d'instructions
BANKCHANGE    macro    Source, But
    local V, VV
V set low(Source) & 0x80
VV set low(But)& 0x80
    if V  ==0 && VV ==0x80
        bsf    STATUS, 5
    endif
    if V  ==0x80 && VV ==0
        bcf    STATUS, 5
    endif
V set high(Source) & 0x01
VV set high(But)& 0x01
    if V  ==0 && VV ==0x01
        bsf    STATUS, 6
    endif
    if V  ==0x01 && VV ==0
        bcf    STATUS, 6
    endif
    endm

;*********************************************************************
;                   DECLARATIONS DE VARIABLES                        *
;*********************************************************************

; sauvegardes pour l'
IT, sans objet dans ce programme
; placées ici pour éviter les problèmes de banque
 
;   CBLOCK 0x07F                     
 
;   w_temp : 1                    ; W
 
;   status_temp : 1                ; STATUS
 
;   ENDC                        ; Fin de la zone    
; quelques variables pour les test 

; en banque 0
    CBLOCK    0x20
    V01    
:    1
    V02    
:     1
    V03    
:    1
    ENDC                        
; Fin de la zone    

; en banque 1
    CBLOCK    0xA0
    V11    
:    1
    V12    
:     1
    V13    
:    1
    ENDC                        
; Fin de la zone    
    
; en banque 2
    CBLOCK    0x120
    V21    
:    1
    V22    
:     1
    V23    
:    1
    ENDC                        
; Fin de la zone    
    
; en banque 3
    CBLOCK    0x190
    V31    
:    1
    V32    
:     1
    V33    
:    1
    ENDC                        
; Fin de la zone    
    
  

;**********************************************************************
;
                      DEMARRAGE SUR RESET                            *
;**********************************************************************

    org     0x000                 ; Adresse de départ après reset
      goto    init                
; 
      
;**********************************************************************
;
                     ROUTINES D'INTERRUPTION                            *
;**********************************************************************

    ORG     0x004                ; adresse d'
interruption

; sans objet dans ce programme
    
;**********************************************************************
;
                     Programme principal                             *
;**********************************************************************

    errorlevel    -302

    variable add 
= 0x6d
    include 8bs
.inc

init
    
; ici ouvrir une fenêtre Watch et y ajouter les variables suivantes
    
; en fonction du test
    
; STATUS
    
; WREG 
    
; V01, V02, V03
    
; V21, V22, V23
    
; V31 et V32
    
; op1 op2, result
    
; op1 + 0x80/0x100/0x180,  op2 + 0x80/0x100/0x180,  result + 0x80/0x100/0x180
    
; et surveillez ce qui se passe

;**********************************************************************

;
 quelques test avec l'addition      
      ; test sans débordement
    ; ici, on est en banque 0
      movlw    .99    
      movwf    V01
      movlw    .1        
      movwf    V02
      add_8bits_signé    V01, V02, V03
      btfsc    STATUS, C
      call    Erreur
      movlw    .99    
      movwf    V01
      movlw    .31
      movwf    V02
      ; test avec débordement
      add_8bits_signé    V01, V02, V03
      btfsc    STATUS, C
      call    Erreur
       ; test sans débordement avec des variables en Banque 2
     ; passer en banque 2
      BANKCHANGE    V01, V21
      movlw    .20    
      movwf    V21
      movlw    .10        
      movwf    V22
      add_8bits_signé    V21, V22, V23

;**********************************************************************
; test avec l'
opposé  
; sans débordement, variables en banque 2    
      opp_8bits_signé    V21
, V22
; avec débordement, variables en banque 3    
      BANKCHANGE    V21
, V31
      movlw    0x80
      movwf    V31
      opp_8bits_signé    V31
, V32
      btfsc    STATUS
, C
      call    Erreur
    
;**********************************************************************
;
 test avec la soustraction
      BANKCHANGE    V31
, V21
      movlw    .10        
      movwf    V22
      sub_8bits_signé    V21
, V22, V23
      btfsc    STATUS
, C
      call    Erreur
; cas particuliers ou on retranche -128
; d'un nombre négatif
      movlw    -.10        
      movwf    V21
      movlw    -.128
      movwf    V22
      sub_8bits_signé    V21, V22, V23
      btfsc    STATUS, C
      call    Erreur
; d'
un nombre positif
      movlw    .10        
      movwf    V21
      movlw    
-.128
      movwf    V22
      sub_8bits_signé    V21
, V22, V23
      btfsc    STATUS
, C
      call    Erreur

      
; Compléter le source avec d'autres tests de votr choix
      
      goto    init
      
Erreur
    ; ici, en général, on ne sait pas trop quoi faire
    return
    
; les invocations directes des macros faisant le travail
; ont été interdites.
; pour le constater, enlever  le ; des lignes suivantes
;Appelle_add_8bits_signé
;    m_add_8bits_signé
;Appelle_opp_8bits_signé
;    m_opposé_8bits_signé
;Appelle_sub_8bits_signé
;    m_sub_8bits_signé
    
    END             ; directive fin de programme



Les lignes 32 à 40 pallient l'absence d'inclusion d'un fichier .inc pour un pic particulier. Si tel n'est pas le cas, il ne faut pas les écrire.

Code : Tout sélectionner


STATUS    EQU    .3
RP0        EQU    .5
RP1        EQU    .6
C        EQU    0
Z        EQU    2

    ifndef __MAXRAM
        
#DEFINE __MAXRAM 0x1FF
    endif

juste avant l'étiquette init

Code : Tout sélectionner


    variable add 
= 0x6d
    include 8bs
.inc

inclut le fichier décrit ci-dessous dans le source et attribue à la variable add l'adresse
où devra être installée la zone de données des sous-programmes, c'est une manière de passer un paramètre à un fichier à inclure

Fichier à inclure fourni

Code : Tout sélectionner

;**********************************************************************
;
                Macros d'exploitation des                              *
;           routines arithmétique 8 bits signés                          *  
;                                                                     *
;**********************************************************************
;                                                                     *
;    NOM:      8bs.inc                                                  *
;    Date:     06/07/2018                                             *
;    Version:  1.0                                                    *
;    Circuit:  sans objet                                             *
;    Auteur:   JJE                                                     *
;                                                                     *
;**********************************************************************
;                                                                     *
;    Fichier requis:                                                  *
;                                                                     *
;**********************************************************************
;                                                                     *
;    Notes:                                                           *
;    Contient les macros utiles à l'
arithmétique signée 8 bits          *
;
                                                                     *
;**********************************************************************
;
                        Définition de la zone de travail
;**********************************************************************

;
 un espace de 3 octets est réservé dans chaque page de RAM
; à partir de l'adresse V
m_8bs_Data macro W
    variable V = W &0x7F
    CBLOCK    V
        Data_8bs    : 3
    ENDC
    if (__MAXRAM & 0x80)!=0
        CBLOCK    V + 0x80
        Data_8bsResB1    : 3
        ENDC
    endif
    if (__MAXRAM & 0x100)!=0
        CBLOCK    V + 0x100
        Data_8bsResB2    : 3
        ENDC
    endif
    if (__MAXRAM & 0x80)!=0 && (__MAXRAM & 0x100)!=0 
        CBLOCK    V + 0x180
        Data_8bsResB3    : 3
        ENDC
    endif
; étiquette attribuée à chacun des octets
; les sous-programmes définis dans les macros ci-dessous
; travaillent avec ces étiquettes dans la banque active à l'
appel    
op1    EQU Data_8bs
op2    EQU Data_8bs
+1
result    EQU Data_8bs
+2
    
    endm
;**********************************************************************
;
                            Macro de test                           *
;**********************************************************************
;
 vérifie que les variables passées en paramètre sont dans la même banque
; déclenche une erreur sinon
; ne génère aucun code
MEMESBANQUES    macro P
, Q    
    local V
, VV
V set low
(P) & 0x80
VV set low
(Q)& 0x80
    if    V 
!= VV
        error    
"variables dans des banques différentes"
    endif
V set high
(P) & 0x01
VV set high
(Q)& 0x01
    if    V 
!= VV
        error    
"variables dans des banques différentes"
    endif
    endm
;**********************************************************************
;
                            Sous-programmes                           *
;**********************************************************************
;
 équivalent de P3=P1+P2 d'un langage évolué
; en évitant au programmeur de mettre les mains dans le cambouis
; P1, P2, P3 doivent être dans la banque active
add_8bits_signé    macro    P1, P2, P3
    MEMESBANQUES P1, P2    
    MEMESBANQUES P2, P3
    #DEFINE Invocation_Autorisée
    goto    add_8bits_signé_1
    local    Appelle_add_8bits_signé
Appelle_add_8bits_signé
    m_add_8bits_signé
    local    add_8bits_signé_1
    #UNDEFINE Invocation_Autorisée
add_8bits_signé_1
;    errorlevel -302
    movf    P1,W
    movwf    op1
    movf    P2,W
    movwf    op2
    call    Appelle_add_8bits_signé
    movf    result, w
    movwf    P3
;    errorlevel +302

    endm
    
; réalise l'
addition de deux entiers 8 bits signés
; entrée :
;
     op1 opérande 1 
;     op2 opérande 2
; sortie :
;
     op1, op2 inchangés
;     result contient op1 + op2
;     STATUS,C armé si débordement
;     STATUS,Z armé si résultat nul
; remarque :
;
     la banque mémoire contenant op1, op2 et result 
;     doit être sélectionnée
m_add_8bits_signé    macro
    ifndef Invocation_Autorisée
        error 
"invocation directe interdite"
        exitm
    endif
    ifdef    m_add_8bits_signé_flag
        
; pour interdire une miltiple invocation de cette macro
        
; toutes sauf la première appelle le code installé par la première invocation
        goto add_8bits_signé_code
        exitm
    endif
    
#DEFINE m_add_8bits_signé_flag
;    errorlevel    -302
add_8bits_signé_code
    movf    op1
,w
    xorwf    op2
,w        ; ou exlusif avec op2
    movwf    result        
; pour manipuler le bit 7 du résultat
    btfsc    result
,7    ; on ne s'intéresse qu'au bit de signe
    goto    add_8bits_signé_1
    
; ici, op1 et op2 sont de même signe
    call    add_8bits_non_signé
    
; W contient result
    xorwf    op1
,w    ; ou exlusif avec op1
    andlw    0x80    
; isoler bit 7
    btfss    STATUS
, Z
    
; le bit de signe du résultat diffère de celui des opérandes
    
; il y a débordement
    bsf        STATUS
, C    ; on indique le débordement
    movf    result
,f    ; pour armer STATUS,Z en fonction de result
    return                
; le résultat n'est pas nul
    
add_8bits_signé_1
    ; ici op1 et op2 sont de signe différent
    ; il ne peut pas y avoir de débordement,
    ; on les ajoute comme des insignés
    call    add_8bits_non_signé
    ; et on marque le non débordement
    bcf        STATUS, C
    return
add_8bits_non_signé    
;    m_add_8bits_non_signé
    movf    op1,w
    addwf    op2,w
    movwf    result
    return
;    errorlevel    +302
    endm

;**********************************************************************
    
; équivalent de P3=P1-P2 d'
un langage évolué
; en évitant au programmeur de mettre les mains dans le cambouis
; P1, P2, P3 doivent être dans la banque active
sub_8bits_signé    macro    P1
, P2, P3    
    MEMESBANQUES P1
, P2    
    MEMESBANQUES P2
, P3
    
#DEFINE Invocation_Autorisée
    goto    sub_8bits_signé_1
    local    Appelle_sub_8bits_signé
Appelle_sub_8bits_signé
    m_sub_8bits_signé
    local    sub_8bits_signé_1
    
#UNDEFINE Invocation_Autorisée
sub_8bits_signé_1
;    errorlevel -302
    movf    P1
,W
    movwf    op1
    movf    P2
,W
    movwf    op2
    call    Appelle_sub_8bits_signé
    movf    result
, w
    movwf    P3
;    errorlevel +302

    endm
; réalise la soustraction de deux entiers 8 bits signés
; entrée :
;
     op1 opérande 1 
;     op2 opérande 2
; sortie :
;
     op1 inchangé
;    op2 remplacé par son opposé
;     result contient op1 - op2
;     STATUS,C armé si débordement
;     STATUS,Z armé si résultat nul
; remarque :
;
    utilise un niveau de pile
;     la banque mémoire contenant op1, op2 et result 
;     doit être sélectionnée
;     chaîne sur add_8bits_signé pour gagner un octet de code
m_sub_8bits_signé macro
    ifndef Invocation_Autorisée
        error 
"invocation directe interdite"
        exitm
    endif
    ifdef    m_sub_8bits_signé_flag
        
; pour interdire une multiple invocation de cette macro
        
; toutes sauf la première appelle le code installé par la première invocation
        goto sub_8bits_signé_code
        exitm
    endif
    
#DEFINE m_sub_8bits_signé_flag
;    errorlevel    -302
sub_8bits_signé_code
    call    opposé_8bits_signé
    btfsc    STATUS
,C
    goto    sub_8bits_signé_1
    call    add_8bits_signé_code
    return
sub_8bits_signé_1
    
; ici on calcule op1-(-128) ce qui n'est possible que si
    ; op1<0
    btfsc    op1,7
    goto    sub_8bits_signé_2
    bsf        STATUS,C
    return
sub_8bits_signé_2    
    movf    op1,w
    addwf    op2,w
    movwf    result
    bcf        STATUS, C
    return
    local    opposé_8bits_signé
opposé_8bits_signé
    m_opposé_8bits_signé    
;    errorlevel    +302
    endm

;**********************************************************************

;
; équivalent de P2= -P1 d'
un langage évolué
; en évitant au programmeur de mettre les mains dans le cambouis
; P1, P2 doivent être dans la banque active
opp_8bits_signé    macro    P1
, P2    
    MEMESBANQUES P1
, P2    
    
#DEFINE Invocation_Autorisée
    goto    opp_8bits_signé_1
    local    Appelle_opp_8bits_signé
Appelle_opp_8bits_signé
    m_opposé_8bits_signé
    local opp_8bits_signé_1
    
#UNDEFINE Invocation_Autorisée
;    errorlevel -302
opp_8bits_signé_1
    movf    P1
,W
    movwf    op2
    call     Appelle_opp_8bits_signé    
    movf    op2
, w
    movwf    P2
;    errorlevel +302
    endm

; calcule l'opposé d'un entier 8 bits signés
; entrée :
    ; op2 l'octet à traiter    
; sortie : 
;     op2 contient -op2
;     STATUS, C est armé si dépassement de capacité
;     se produit si la valeur de l'
octet traité en entrée est -128 (0x80)
;
     on se débarasse de ce cas gènant 
; remarque :
;
     la banque mémoire contenant op2 doit être sélectionnée
m_opposé_8bits_signé macro
    ifndef Invocation_Autorisée
        error 
"invocation directe interdite"
        exitm
    endif
    ifdef    m_opposé_8bits_signé_flag
        
; pour interdire une multiple invocation de cette macro
        
; toutes sauf la première appelle le code installé par la première invocation
        goto opposé_8bits_signé_code
        exitm
    endif
    
#DEFINE m_opposé_8bits_signé_flag
;    errorlevel    -302
opposé_8bits_signé_code
    movf    op2
, w
    xorlw    0x80
    bsf        STATUS
,C
    btfsc    STATUS
,Z
    
; C a été armé en prévision
    return
    bcf        STATUS
,C    ; ici, on n'aura pas de débordement
                        ; et aucune des instructions suivantes ne touche à C
    comf    op2, f
    incf    op2, f
    return
;    errorlevel    +302
    endm

    m_8bs_Data add



lignes 26 à 55

Code : Tout sélectionner

; un espace de 3 octets est réservé dans chaque page de RAM
; à partir de l'adresse V
m_8bs_Data macro W
    variable V = W &0x7F
    CBLOCK    V
        Data_8bs    : 3
    ENDC
    if (__MAXRAM & 0x80)!=0
        CBLOCK    V + 0x80
        Data_8bsResB1    : 3
        ENDC
    endif
    if (__MAXRAM & 0x100)!=0
        CBLOCK    V + 0x100
        Data_8bsResB2    : 3
        ENDC
    endif
    if (__MAXRAM & 0x80)!=0 && (__MAXRAM & 0x100)!=0 
        CBLOCK    V + 0x180
        Data_8bsResB3    : 3
        ENDC
    endif
; étiquette attribuée à chacun des octets
; les sous-programmes définis dans les macros ci-dessous
; travaillent avec ces étiquettes dans la banque active à l'
appel    
op1    EQU Data_8bs
op2    EQU Data_8bs
+1
result    EQU Data_8bs
+2
    
    endm

La macro m_8bs_Data invoquée à la fin de ce fichier à inclure, a pour but de réserver les octets nécessaires aux sous-programmes. Remarquez qu'une étiquette est attribuée à chaque bloc bien que ce ne soit pas très utile mais je n'ai pas su réserver 3 octets autrement.
Les trois dernière lignes d'EQU définissent les adresses des octets utilisés par les sous-programmes dans la banque active.
Lignes 60 à 74, la macro MEMESBANQUES teste que deux variables passées en paramètre sont dans la même banque, c'est une condition imposée des sous-programmes. Elle est invoquée par chacune des macros proposées. Comme elle ne génère pas de code, elle donne simplement un peu de travail à l'assembleur qui sécurise l'usage de ces macros.
Les lignes 103 à 164 contiennent le code du sous-programme d'addition 8 bits signée
J'ai choisi d'interdire l'invocation de cette macro par l'utilisateur c'est la raison des 3 lignes

Code : Tout sélectionner


    ifndef Invocation_Autorisée
        error 
"invocation directe interdite"
        exitm
    endif

Remarquez que cette interdiction est très morale, plutôt pour l'exemple puisqu'il suffit d'une ligne avant d'évoquer cette macro pour la transgresser :

Code : Tout sélectionner


    
#DEFINE Invocation_Autorisée
 

Il ne faut pas qu'à chaque invocation, le code utile soit dupliqué, ce serait très gourmand en mémoire programme. C'est le rôle de ces quelques lignes

Code : Tout sélectionner


    ifdef    m_add_8bits_signé_flag
        
; pour interdire une miltiple invocation de cette macro
        
; toutes sauf la première appelle le code installé par la première invocation
        goto add_8bits_signé_code
        exitm
    endif
    
#DEFINE m_add_8bits_signé_flag
;    errorlevel    -302
add_8bits_signé_code

à la première invocation, le flag m_add_8bits_signé_flag n'est pas défini, le processeur de macros va incorporer les lignes qui suivent add_8bits_signé_code jusqu'au endm. Aux invocations suivantes, le flag m_add_8bits_signé_flag est défini, le processeur de macro va incorporer le goto qui branche au sous-programme add_8bits_signé_code installé à la première invocation. Le "exitm" permet de sauter le reste du source jusqu'au prochain endm
Les lignes 78 à 102 contiennent le code de l'une des 3 fonctionnalités, l'addition. C'est la macro à invoquer par l'utilisateur.
Elle commence par tester les variables d'appel et sort en erreur si elles ne sont pas dans la même banque
Remarquons que, à la première invocation de cette macro, la macro m_add_8bits_signé qui contient le code qui fait le travail, n'a pas encore été invoquée, il est donc urgent de le faire, mais on ne peut pas le faire ici car le transfert de données n'a pas été réalisé. On fait donc un goto un peu plus loin (add_8bits_signé_1) et on insère le code utile entre les deux par une invocation de m_add_8bits_signé. Remarquons que cette invocation ne générera qu'un goto sauf pour sa première. Je vous conseille de suivre le pas à pas dans le Disassembly listing pour bien voir ce mécanisme.
Les autres points d'entrée sont traités sur le même modèle.
Une dernière remarque sur ce source, j'ai laissé tous les appels à la directive errorlevel en remarque, car MPASM n'a pas de mécanisme pour revenir à l'état précédent si bien qu'à chaque invocation d'une macro, on serait à +302 quel que soit l'état où l'avait mis l'utilisateur avant l'invocation. Ce sera donc à l'utilisateur de gérer ce warning. Dans le programme exemple je l'ai mis à -302 en début de code.
Modifié en dernier par JJE le lun. 16 juil. 2018 07:00, modifié 1 fois.
Cordialement

JJE

C'est pas parcequ'on n'a rien à dire qu'il faut fermer sa G....e

Retourner vers « Langage ASM »

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 17 invités