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.
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
; segmentul de date
var1 : .BYTE 1 ; declaratia variabilei var1 si rezervarea
; a 1 byte pentru aceasta variabila.
; a 1 byte pentru aceasta variabila.
var1 : .BYTE 2
; declaratia variabilei var2 si rezervarea
; a 2 byte pentru aceasta variabila.
; 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
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.
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.