Microprocesoare (MP) #3

Tema:  Algoritmi cu Ramificari, Variabile, Expresii aritmeticeLaborator Nr 3

Scopul lucrări:
Studiul algoritmului cu ramificare şi iniţializare în variabile
Sarcina lucrarii:

În dependenţă de o condiţie iniţiala să se evalueze una din expresiile aritmetice logice.
Consideraţii teoretice:
Variabila vom  numi un obiect ce contine date care pot varia.
    Pentru limbajul ASM o variabila vom numi o zona de memorie alocata acestei vatiabile accesibile dupa un nume. Numele de variabila este o eticheta in segmentul de date care reprezinta de fapt adresa catre zona de memorie alocata variabilei. Spre deosebire de limbajele de nivel inalt, in ASM nu exista tip al variabilei. O variabila este caracterizata doar de nume acesteia, eticheta, si volumul de memorie alocat acestei variabile.


Declararea Variabilei.
    O variabila se va declara in segmentul de date .DSEG si va reprezenta o eticheta urmata de o directiva de preprocesare .BYTE care permite rezervarea unei zone de memorie pentru variabila data.

 .DSEG                          ; variabilele for fi declarate in
                                   ; segmentul de date
 var1 : .BYTE 1          ; declaratia variabilei var1 si rezervarea 
                                     ; a 1 byte pentru aceasta variabila.
 var1 : .BYTE 2          ; declaratia variabilei var2 si rezervarea
                                       ; a 2 byte pentru aceasta variabila.

Figura  1 Alocarea de memorie pentru variabile
Pentru a intelege mai bine mecanismul de declarare a variabilelor in ASM vom prezenta o comparatie cu   declaratia de variabile in limbajul C++.

       C++     |     SIZE        |   ASM        
  char ch;     |  8 bit ,  1 byte | ch: .BYTE 1
  int a;          | 32 bit , 4 byte |  a: .BYTE 4
  short int b; | 16 bit , 2 byte |  b: .BYTE 2
  long int c;  | 64 bit , 8 byte |  c: .BYTE 8
  float d;       | 32 bit , 4 byte |  d: .BYTE 4
  double e;    | 64 bit , 8 byte |  e: .BYTE 8
Operatii de transfer cu variabilele.

  Operatiile de transfer pentru variabile va fi executat cu comenzi de acces direct la memorie cum ar fi:
·                     LDS R, k - incarcarea directa a valorii de la adresa k din SRAM intrun registru de uz general. 
·                     STS k, R - stocarea directa valorii unui registru de uz general la adresa k din SRAM.
    Eticheta - numele variabilei va reprezenta adresa primei locatii a variabilei. Locatiile superioare dupa principiul "little-endian" se vor accesa dupa adresele imediat urmatoare. 

Atribuirea unei valori constante catre o variabila
   Deorece nu exista comanda de transfer a unei constante direct in SRAM, va trebui mai intai sa incarcam acea valoare intrun registru de uz general dupa care transferata direct la adresa specificata de numele variavilei.

    //exemplu var1 = 25
    .DSEG               //variabilele for fi declarate in segmentul de date
     var1 : .BYTE 1
    .CSEG               //programul se scrie in segmentul de cod
        ldi r16, 25
        sts var1, r16   
Operatii aritmetice cu variabile
    Pentru a evalua o operatie artmetica intre doua variabile va trebui sa transferam mai intai valorile variabilelor in registri de uz general dupacare vom avea posibilitatea de a evalua o operatie aritmetica sau logica. Acest fapt se datoreaza restrictiilor arhitecturii care permite operatii aritmetice doar cu registri de uz general.
          //Ex: a = b + c
    .DSEG               //variabilele for fi declarate in
                        //segmentul de date
     a : .BYTE 1        //rezervare a 1 byte pentru variabila a
     b : .BYTE 1        //rezervare a 1 byte pentru variabila b
     c : .BYTE 1        //rezervare a 2 byte pentru variabila c

    .CSEG               //programul se scrie in segmentul de cod
 lds r15, b                  // incarcarea valorii variabilei b intr-un registru de lucru
 lds r16, c                 //incarcarea valorii variabilei c in alt registru de lucru    
        add r15, r16    //evaluarea operatiei de adunare
        sts   a, r15    //descarcarea rezultatului in variabila a

   Programarea in limbajul ASM (si nu numai in ASM) se reduce executarea conditionata sau neconditionata a unor instructiuni. Pentru executarea neconditionata vom avea asa numitii algoritmi seriali, care sunt compusi dintro serie de operatii de transfer si prelucrare.
Executia conditionata presupune executia unui set de instructiuni de transfer sau prelucrare in dependenta de o conditie.

Fig. 2 Executia conditionata

Prin "set de instructiuni" vom avea in vedere de la nici o comanda pana la secvente complexe de program.
Setul de comenzi pentru arhitectura AVR presupune doua tipuri de comenzi conditionale:
   Comenzi de salt conditionat - BR_OP LABEL
   Comenzi de ignorare a instructiunii imediat urmatoare  -  SB_OP --> 

Implementarea algoritmilor cu comenzi de salt conditionat
   Comenzile de acest tip sunt comenzi care dupa testarea unei anumite conditii, presupuse de comanda, de obicei fiind un bit din registrul de stare SREG, executa un salt a executiei la o adresa fixa specificata de eticheta (label). In constext vom numi acest tip de comenzi ca BR_OP - operatii de ramificare. Bitii verificati din SREG pot fi gasiti in tabelul de comenzi a operatiilor de transfer al controlului, operatii de salt conditionat.
Fig. 3 Salt conditionat executat de comanda BRANCH

Pentru acest tip de comenzi putem face niste echivalari cu instructiunile conditionale din limbajele de nivel inalt cum ar fi Limbajul C.
//exemplu:
   BREQ if ==  daca este egalitate
   BRNE if !=  daca este diferit
   BRSH if >=  daca este mai mare sau egal
   BRLO   if <   daca este mai mic
   O comanda de tip BR_OP de cele mai dese ori este precedata de o instructiune de comparatie CP, CPI sau TEST. Comenzile de comparatie sunt menite pentru a evalua relatia intre elementele participante la TEST avand ca rezultat modificarea registrului de stare SREG. O instructiune de tip BR_OP poate sa nu fie precedata de o operatie comparatie in cazul in care operatia de prelucrare de inaintea operatiei de ramificare configureaza singura registrul SREG in starea necesara pentru ramificare. De exemplu dupa o decrementare pana la ZERO in cicluri. De fapt in spatele comparatiei se executa o operatie de scadere fara a salva resultatul operatiei, iar ca urmare a operatiei de scadere se vor seta bitii din registrul de stare SREG.
Constructia algoritmica de ramificare in ulimbajul ASM poate fi implementata dupa cum urmeaza unde     etichetele L1, L2, L3 si L4 corespund pun-ctelor cu acelasi nume prezentate in figura de mai sus.
L1:             //inceputul constructiei de ramificare
    cp R1,R2     //operatia de comparare (R2 - R1)
    BR_OP L3     //operatia de salt conditionat - ramificare
L2:                  //F - test FALSE
    ...
    ...                     //OP1 - setul de instructiuni pentru ramura FALS
    rjmp L4           //salt neconditionat la sfarsitul
                              //constructiei de ramificare
L3:                    //T - test TRUE
    ...
    ...              //OP2 - setul de instructiuni pentru ramura TRUE
    (rjmp L4)       //poate fi omis
L4:             //sfarsitul constructiei de ramificare

Implementarea ramificarilor cu comenzi de ignorare a urmatoarei comenzi.
   Comenzile de acest tip presupun ignorarea exexutiei comenzii imediat care o urmeaza. Vom numi acet tip de comenzi in acest context ca comenzi tip SB_OP. Aceste comenzi de cele mai dese ori presupun verificarea unui bit dintr-un Registru de Uz General (din cei 32), Registru Periferic (din cei 64) sau registrul SREG. Bitul verificat se poate gasi din tabelul de comenzi pentru fiecare comanda in parte. Saltul conditionat pentru aceste comenzi va fi reprezentat prin saltul peste o comanda, si deci nu este nevoie de specificat adresa la care va avea loc saltul.
Formatul instructiunii va arata dupa cum urmeaza
   SB_OP TST_REG, N unde:
  SB_OP - denumirea comenzii care va specifica o testare la bit setat sau resetat

   TST_REG - numele registrului testat
   N - numarul de ordine a bitului testat in registrul selectat
Iar definitia comenzii va suna in felul urmator: Salt peste o comanda (PC = PC+2) daca bitul N din registrul TST_REG este setat/resetat. in caz contrar executa comanda urmatoare (PC=PC+1).

Echivalarile pentru limbagele de nivel inalt vor fi de tip

   if(TST_REG[N]==0)
   sau
     if(TST_REG[N]==1)
   Aceste comenzi nu necesita operatii de pre-comparare, ele executa comparatia necesara si saltul in cadrul aceleiasi instructiuni.
Vom realiza mai jos constructia algoritmica de ramificare  si  implementarea ei in ulimbajul ASM unde     etichetele L1, L2, L3 si L4 corespund punctelor cu acelasi nume.
L1:             //inceputul constructiei de ramificare
    SB_OP       //operatia ignorare a comenzii ce urmeaza
    rjmp L3     //salt la executia clauzei FALSE
   (rjmp L2)    //salt la executia clauzei TRUE, poate fi omis
L2:             //T - test TRUE
    ...         //OP1 - setul de instructiuni pentru ramura TRUE
    ...
    rjmp L4     //salt neconditionat la sfarsitul
                //constructiei de ramificare
L3:             //F - test FALSE
    ...
    ...         //OP2 - setul de instructiuni pentru ramura FALSE
    ...
    (rjmp L4)   //poate fi omis
L4:             //sfarsitul constructiei de ramificare
Mersul lucrării:  
1)      Schema bloc

 1)      Următorul pas este crearea ciruitului în programul de simulare PROTEUS, unde se demonstrează cum funţionează porturile de I/O şi respectiv programul microcontrollerului.
 Listengul programului:



 Concluzie
 Efectuînd lacrarea de laborator nr 3 “Algoritmi cu ramificari, variabile, expresii aritmetice” am facut cunoştinţe cu variabile in limbajul de programare assembler. Ramificarea în assembler presupune schimbarea valorii din Program Counter în dependenţă de o anumită condiţie (biţii din SREG) astfel că se execută un salt la o altă adresă din Program Memory şi se îndeplinesc instrucţiunile de la ea.