Equivalente Assembly
          dello statement Case
         | 
       
     
   
   
    
  La scelta tra più alternative
    
Capita sovente di dover implementare del codice che consenta la
selezione tra più alternative. Più in generale, all' uscita di una certa
procedura si avrà a disposizione un indice a 8 bit e quindi si potranno
definire fino a 256 possibili alternative per puntare diverse operazioni nel
programma.  
Occorre verificare con una comparazione a quale scelta corrisponde l'
indice.  
In C la funzione è svolta dal case: 
switch(input) 
{ 
case 1: 
funct1(); 
break; 
case 2: 
funct2(); 
break; 
case 3:  
.... 
case n: 
break; 
default:  
cout<<"Input error"; 
} 
 
In Assembly una via è quella di utilizzare una lookup table che
contenga tante linee quante sono le scelte possibili; questa è adeguata in ogni
caso, ma, se il numero delle scelte alternative non è particolarmente grande, si può usare una
tecnica diversa, che consiste nella semplice comparazione dell' indice con le
possibilità di scelta. 
I set di istruzioni dei PIC consente diverse tecniche di
comparazione, ad esempio utilizzando operazioni di sottrazione o somma e verificando subito dopo lo stato dei flag C, N, o Z. 
Se consideriamo l' istruzione di sottrazione, ad esempio nella forma: 
 
    subwf  file, w 
 
possiamo osservare che alcuni bit dello STATUS vengono modificati a seconda del
risultato dell' operazione.   Se
consideriamo il flag Z -  zero, esso è settato quando il risultato dell'
operazione è zero.  
 
             MOVF  
switch, W     ; muovere l' indice in W  
      SUBWF  index1,
W     ; Sottrarre 'W' (=indice) dallo
switch  
      BTFSC  STATUS,
Z     ; Se Z=0 saltare prossima
istruzione 
       GOTO 
case1         ; se
Z=1 saltare all' esecuzione del case 
      GOTO  
non_equal     ; altrimenti procedere
  Alcuni microcontroller, inoltre,
  hanno istruzioni dirette per il
  confronto, come la CPFSEQ degli Enhanced. 
  La cosa è, ovviamente, valida
  anche se le scelte sono literal, come solitamente capita: 
               
  MOVF   switch, W    
  ; muovere l' indice in W  
        SUBWF  index1,
  W     ; Sottrarre 'W' (=indice) dallo
  switch  
        BTFSC  STATUS,
  Z     ; Se Z=0 saltare prossima
  istruzione 
         GOTO 
  case1         ;
  se Z=1 saltare all' esecuzione del case 
        GOTO  
  non_equal     ; altrimenti procedere 
  Se dobbiamo, però, ripetere la comparazione per più elementi, è
  preferibile ricorre ad un' altra via, quella dell' istruzione di OR esclusivo, la XORWF. 
   
XOR o OR esclusivo: un breve ripasso. 
La funzione di OR esclusivo o  XOR (eXclusive OR) origina questa tavola
della verità: 
  
  
    
      | input B | 
      input A | 
      A OR B | 
      A
        XOR B | 
     
    
      | 0 | 
      0 | 
      0 | 
      0 | 
     
    
      | 0 | 
      1 | 
      1 | 
      1 | 
     
    
      | 1 | 
      0 | 
      1 | 
      1 | 
     
    
      | 1 | 
      1 | 
      1 | 
      0 | 
     
   
  
 
In pratica,  XOR rende 1 se i due bit confrontati sono diversi e 0 se sono
uguali. 
Le sue proprietà sono queste: 
  
    
      | Operazione | 
      Proprietà | 
      Descrizione | 
     
    
      | A^B = B^A | 
      commutativa | 
      cambiando ordine agli operatori il risultato non cambia | 
     
    
      | A^B^C = A^ (B^C)=(A^B)^C | 
      associativa | 
      operando un raggruppamento, il risultato non cambia | 
     
    
      | A^A = 0 | 
      non idempotenza | 
      XOR con se stesso dà risultato 0 | 
     
    
      | A^!A=1 | 
      complementazione | 
      
    
XOR con 
    
l' inverso di se
      stesso dà risultato 1 | 
   
  
  
    | A^0 = A | 
    identità | 
    XOR con 0 non cambia l'operando | 
   
  
    | A ^ 1 = !A | 
    inversione | 
    XOR con 1 inverte l' operando | 
   
   
 
Possiamo utilizzare questa istruzione come operatore in una comparazione. 
   
XOR per comparare
Se vogliamo verificare che un dato sia uguale ad un altro, ecco che, per
quanto appena detto, l' operazione di XOR è ideale. Infatti, se due valori sono
uguali, si tratta di un caso di A^A il cui risultato è 0. Se non fosse zero,
questo indicherebbe che i due valori sono in  qualche modo diversi. 
Dunque, per verificare se W contiene un certo valore, basterà: 
  MOVF   
val_to_compare,W    ; valore da comparare in W 
  XORLW   index              
; valore con cui comparare       
  BTFSC   STATUS, Z          
; check flag Z    
   GOTO   equal              
; se =1 sono uguali 
  GOTO    not_equal          
; se no sono diversi 
Questo ci consente di effettuare con semplicità una scelta tra diversi
possibili valori. Ad esempio, vogliamo verificare l' uguaglianza di un
determinato valore con una lista di possibilità.
     
       MOVF   
val_to_compare,W 
   XORLW   index1 
   BTFSC   STATUS, Z   
    GOTO   case1 
   MOVF    val_to_compare,W 
   XORLW   index2 
   BTFSC   STATUS, Z   
    GOTO   case2 
   ..... 
   MOVF    val_to_compare,W 
   XORLW   indexn 
   BTFSC   STATUS, Z   
    GOTO   casen    
   GOTO    not_equal
     
La riga MOVF val_to_compare,W viene ripetuta ad
ogni comparazione dato che l'operazione XORLW
distrugge il contenuto di W.
     
Per i PIC18F possiamo utilizzare l' istruzione BZ
:
     
      
MOVF    val_to_compare,W 
   XORLW   index1 
   BZ      case1 
   MOVF    val_to_compare,W 
   XORLW   index2 
   BZ      case2 
   ..... 
   MOVF    val_to_compare,W 
   XORLW   indexn 
   BZ      casen 
   GOTO    not_equal 
  ma questa scrittura è adeguata a tutti i PIC utilizzando una semplice
  macro:
     
   BZ    MACRO   
  dest 
   BTFSC   STATUS, Z   
    GOTO   dest 
         ENDM    
  
     
Possiamo
implementare una ulteriore variazione migliorativa considerando le proprietà
dell' XOR e in particolare la sequenza 
A^B^B
= A^ (B^B) = A^0 = A 
Quindi 
    
  MOVF    val_to_compare,W 
   XORLW   index1 
   XORLW   index1 
  rende 
  W = val_to_compare . Di conseguenza possiamo
scrivere: 
   MOVF    val_to_compare,W
   XORLW   index1
   BZ      case1
   XORLW   index1^index2
   BZ      case2
   XORLW   index2^index3
   BZ      case3
   .....
   MOVF    val_to_compare,W
   XORLW   index-1 ^ index
   BZ      casen
   GOTO    not_equal 
  In questo modo sarà possibile comparare un valore a 8 bit con una serie di
indici ed eseguire una diversa operazione a seconda del loro valore. 
Questo non è certamente il solo modo per effettuare una serie di scelte, però, nel caso di un limitato numero di comparazioni, è
senz'altro il più semplice ed efficace.  
  
  
   
  
    Argomenti collegati:
     
  
   
  
 |