Documente Academic
Documente Profesional
Documente Cultură
Raport
La disciplina: Microprocesoare
Tema: Subrutinele
2015
Tema lucrrii :Subrutine cu parametri;
Obiective:
O1 Realizarea subrutinelor securizate in limbajul ASM;
O2 Transferul parametrilor catre subroutine in limbajul ASM;
O3 Realizarea algoritmilor de impartire in ASM;
Definiia problemei:
Sa se realizeze o aplicatie cu MCU care va realiza inmultirea binara intre doua numere de 8 biti
culese de pe 2 porturi a microcontrollerului ( prin deplasare si adunare) si va afisa rezultatul obtinut
( pe 16 biti) pe alte 2 porturi.
Special pentru realizarea inmultirii se va scrie o subrutina care va utiliza 2 registri de uz general
in calitate de parametric de intrare pentru a prelua termenii intre care urmeaza sa se realizeze
inmultirea si 2 registri de uz general in calitate de parametric de iesire pentru returnarea
rezultatului. Subrutina trebuie sa fie securizata.
Nota! Subrutina create va implementa un algoritm special,fara a utiliza instructiunea MUL.Pentru
apreciere maxima se cere realizarea unei subroutine care va realiza impartirea.
Notiuni teoretice:
Stiva (Stack).
Stiva este un mecanism care permite stocarea temporara a datelor dupa principiul LIFO (Last
Input First Output) - Primul Intrat Ultimul Iesit.
Introducerea in stiva se va executa prin comanda PUSH R - introducerea continutului unui
Registru de Uz General in Stiva (R -> STACK). Extragerea datelor cu comanda POP R (R <-
STACK).
Deasemenea stiva este un mecanism fara de care nu este posibil lucrul cu subrutinele,
deoarece mecanismul stivei permite stocarea temporara a Contorului de Program PC pe durata
executiei subrutinei. Respectiv comenzile de tip CALL si RET deasemenea vor
introduce/extrage date din stiva.
Mecanismul de stiva este realizat in baza memoriei RAM si un Registru Indicator de Stiva -
SP (Stack Pointer).
Indicatorul de stiva SP indica la adresa curenta de scriere in spatiul RAM.
SP este un registru dublu (16 biti), construit in baza [ SPH : SPL ] facilitand accesul la intreg
spatiul de memorie, pana la 64 K.
Executand comanda PUSH R continutul registrului se va inregistra la adresa ce se contine in
registrul Indicator de Stiva SP, dupa care are loc decrementarea SP.
PUSH R
1. RAM[SP] = R
2. SP = SP - 1
Pentru comanda POP R executia presupune Incrementarea Indicatorului de stiva SP
urmata de transferul in Registrul de Uz General a valorii de la adresa SP
POP R
1. SP = SP + 1
2. R = RAM[SP]
Adaugarea elementelor in stiva va implica cresterea stivei. reesind din cele spuse mai sus, vom
afirma ca Stiva creste in directia diminuarii adreseilor memoriei RAM.
Initializarea Stivei
Registrul Indicator de Stiva SP este localizat in spatiul registrilor periferici, respectiv citirea si
modificarea valorii din SP se va efectua prin comenzile IN si OUT.
Deoarece valoarea indicatorului de stiva SP descreste odata cu cresterea stivei, se recomanda
initializarea stivei la o adresa avansata in spatiul de memorie RAM. O asemenea valoare pote fi
constanta RAMEND care contina ultima adresa existenta din memoria RAM interna a
Microcontrollerului.
Operatia de Initializare a stivei va consta in initializarea Indicatorului de stiva SP.
SP = RAMEND, [SPH:SPL] = RAMEND
Secventa de cod in ASM pentru operatia de mai sus va arata in felul urmator:
unde:
LOW - macroinstructiunea pentru selectarea byte-ului inferior dintr-o constanta.
HIGH - macroinstructiunea pentru selectarea byte-ului superior dintr-o constanta.
Subrutina.
Subrutina - Secventa de instructiuni grupata intre o eticheta (label) si instructiune de returnare
din subrutina RET. Eticheta reprezinta o adresa in memoria de programe fiindui atribuit un nume
de acces. In program va fi reprezentata de un nume de eticheta urmata de (:)
Subrutina poate fi apelata prin numele ei cu una din comanzile de chemare subrutinei CALL,
RCALL sau ICALL.
...
...
rcall MySub ; apelul subrutinei MySub
...
...
Subrutina securizata.
Vom numi subrutina securizata subrutina care nu afecteaza valorile registrilor prin executia sa.
Mecanismul subrutinei securizate consta in salvarea registrilor de lucru, utilizati in subrutina in
stiva la inceputul subrutinei si restabilirea valorilor registrilor inainte de returnare din subrutina.
Subrutina cu parametri
In calitate de parametri al unei subrutine pot fi utilizati registrii de uz general. In asa mod
pentru a transmite date date de intrare in subrutina, inainte de a apela o subrutina este nevoie ca
registrii utilizati ca parametri sa fie initializati cu valorile de intrare dorite pentru acesti
parametri. Iar dupa executia subrutinei se vor prelua valorile din registrii rezervati parametrulilor
de iesire.
Apelul de subrutina va arata in felul urmator:
...
...
ldi r16, K1 ; initializarea primului paramatru
ldi r17, K1 ; initializarea parametrului al doilea
rcall MySub ; apelul subrutinei MySub
sts a, r18 ; preluarea rezultatului subrutinei
...
...
...
...
push r16 ; salvarea registrului parametru r16
push r17 ; salvarea registrului parametru r17
push r18 ; salvarea registrului parametru r18
ldi r16, K1 ; initializarea primului paramatru
ldi r17, K1 ; initializarea parametrului al doilea
rcall MySub ; apelul subrutinei MySub
sts a, r18 ; preluarea rezultatului subrutinei
pop r18 ; restabilirea registrului parametru r16
pop r17 ; restabilirea registrului parametru r17
pop r16 ; restabilirea registrului parametru r18
...
...
Modul de locru:
1) Alcatuim schema bloc de functionare a programului:
Start
main:
init:
DDRA=0b00000000
PORTA=0b11111111
DDRB=0b00000000
PORTB=0b11111111
DDRC=0b00000000
PORTC=0b11111111
DDRD=0b11111111
PORTD=0b00000000
spl = low(ramend)
sph = high(ramend)
Start
R18=0, R19=9
L0: L1:
push R19, R18, R17, R16,
r16 = PINA, r17=PINB Rol R16, dec R19
Call: F A
impartire R19!=0
PORTD=r16
PORTC=r18 L2:
pop r16, r17,r18,r19
Stop Rol R18,
R18= R18-R17
Finish
F C=1 A
Fig.1 Schema bloc
L3:
R18=R18+R17 C=1
C=0
3)Codul Programului:
.include "m32def.inc"
.org 0
.cseg
main:
init:
ldi R16,0b00000000
out DDRA,R16
ldi R16,0b11111111
out PORTA,R16
ldi R16,0b00000000
out DDRB,R16
ldi R16,0b11111111
out PORTB,R16
ldi R16,0b11111111
out DDRC,R16
ldi R16,0b00000000
out PORTC,R16
ldi R16,0b11111111
out DDRD,R16
ldi R16,0b00000000
out PORTD,R16
ldi R25, low(ramend)
out spl,R25
ldi R25, high(ramend)
out sph,R25
end_init:
L0:
push R19 //Securizarea registrilor;
push R18
push R17
push R16
in r16,PINA //Initializarea parametrilor;
in r17,PINB
call impartire
out PORTD,r16
impartire:
clr r18 //ne asiguram ca restul este 0
ldi r19,9 //init counter-ului
L1:
rol r16 //shiftarea la stinga a numitorului
dec r19 //decrementarea counter
brne L2 //verificam daca counterul este 0 (Sare daka nu este egal)
ret
L2:
rol r18 //shiftarea numitorului in rest
sub r18,r17 ;rest - numarator
brcc L3 //daca rezultatul este negativ (Sare daca transportul este
sters)
add r18,r17 ;restaurarea restului
clc //stergerea carry pentru fi introdus in rezultat
rjmp L1
L3:
sec //setarea carry pentru a fi introdus in rezultat
rjmp L1
end_impartire:
end_main:
4) Rezultatele simularii:
Bibliografie:
http://www.microlab.club/