Sunteți pe pagina 1din 9

Universitatea Tehnic a Moldovei

Facultatea Calculatoare, Informatic i Microelectronica

Catedra Microlectronica i Ingineria Biomedicala

Raport
La lucrarea de laborator 3

Disciplina: Microprocesoare

Tema: Subrutine

A efectuat: studentul
grupei MN-141

Gurduza Petru

A verificat:
lector asistent

Lazari Eugeniu

Chiinu 2016
Partea teoretica:
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.21
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:
ldi R16, LOW(RAMEND)
out SPL, R16 ; initializare byte inferior SP
ldi R16, HIGH(RAMEND)
out SPH, R16 ; initializare byte superior SP
unde:
LOW - macroinstructiunea pentru selectarea byte-ului inferior dintr-o constanta.
HIGH - macroinstructiunea pentru selectarea byte-ului superior dintr-o constanta.
Intr-un ciclu de program numarul de inregistrari trebuie sa fie egal cu numarul de
extrageri pentru a evita erori de scurgere sau violare de memorie.

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
(:)
MySub: ; Numele subrutinei reprezentata de
; eticheta inceputui subrutinei
...
... ; Corpul subrutinei
...
ret ; returnare din subrutina
Subrutina poate fi apelata prin numele ei cu una din comanzile de chemare subrutinei
CALL, RCALL sau ICALL.
...
rcall MySub ; apelul subrutinei MySub
...
Mecanismul de chemare a subrutinei consta in salvarea adresei curente de executie in
stiva pentru a avea posibilitatea de a restabili executia comenzilor urmatoare dupa
returnarea din subrutina.
Instructiunea de apel a subrutinei cu o instructiune de tip CALL ca fi interpretata dupa
cum urmeaza:
Odata cu chemarea subrutinei are loc salvarea in stiva a contorului de program si
restabilirea lui la returnarea din subrutina.
1. PC -> STACK - salvarea adresei curente in Stiva
2. jmp MySub - salt la adresa etichetei My Sub
Returnarea din subrutina are loc odata cu executarea comenzii RET ca regula plasata la
sfirsitul subrutinei.
Pentru returnare din subrutina vom avea:
1. PC <- STACK - restabilirea adresei din stiva
2. PC <- PC + 1 - trecerea la comanda urmatoare dupa comanda de apel a
subrutinei
De mentionat ca Contorul de Program PC este un registru de 16 biti, respectiv va a ocupa
doua locatii in stiva, executanduse doua operatii de salvare a unui byte in stiva.
Deoarece un apel de subrutina presupune utilizarea stivei. este strict recomandat ca
inainte de un oarecare prim apel stiva sa fie initializata, iar locul cel mai potrivit este in
partea de initializare a programului.

.include "m32def.inc" ; includem fisierul de adrese la periferice


; pentru Atmega32
.cseg ; indicam inceputul segmentului de cod
.org 0 ; programul va fi inregistrat de la
; adresa 0x00
init: ; punctul de intrare in program
ldi R16, LOW(RAMEND) ; initializarea stivei
out SPL, R16
ldi R16, HIGH(RAMEND)
out SPH, R16
...
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.
MySub: ; Numele subrutinei reprezentata de
; eticheta inceputui subrutinei
push r15 ; salvarea registrului r15
push r16 ; salvarea registrului r16
... ; Corpul subrutinei
... ; utilizare registri r15 si r16
...
pop r16 ; restabilire r16
pop r15 ; restabilier r16
ret ; returnare din subrutina

De mentionat ca ordinea restabilirii registrilor de lucru este inversa celei de salvare,


conform principiului LIFO al stivei.
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
...
Registrii utilizati ca parametri de intrare/iesire NU vor fi salvati in interiorul subrutinei.
Mecanismul de salvare a registrilor utilizati ca parametri in scop de masura de protectie a
datelor curente din acesti registri se va implementa dupa cum urmeaza: paramtrii se vor
salva in stiva inainte de initializare si se vor restabili dupa 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
...

Partea practica:
Obiectivele lucrarii:
1) Utilizarea subrutinelor cu parametru in limbajul Assembler.

Scopul lucrarii:
1) Sa se realizeze un program cu ajutorul AVR Studio care ar seta doua porturi la intrarea
semnalului, iar celelalte doua la iesire. La porturile de intrare sa fie setate doua numere,
care apoi sa se faca operatia de imultire. Rezultatele se fie repartizare pe 16 biti si sa fie
aratate pe indicatori de 7 segmente.
Mersul lucrarii:
1. Cream in proiect nou in AtmelStudio:

2. Elaboram solutia problemei formind shema-bloc. Conform algoritmului obtinut scriem


listingul in assembler.
Schema-bloc:

Fig.1 Schema bloc


3. Listingul programului:

.include "m32def.inc" ;Includem fisierul de descrierea a controlerului


.cseg ;Anuntam segmentul de cod
.org 0 ;Stabilim adresa curenta la pozitia 0

main:
init: ;Incepem initializarea
LDI R16,0x00 ;Incarcam o constanta intr-un RUG
LDI R17,0xFF
OUT DDRA,R16 ;Initializam portul A ca port de intrare si acrivam rezistenta de pull-up
OUT PORTA,R17
OUT DDRB,R16 ;Initializam portul B ca port de intrare si acrivam rezistenta de pull-up
OUT PORTB,R17
OUT DDRC, R17 ;Initializam portul C ca port de iesire
OUT PORTC,R16
OUT DDRD,R17 ;Initializam portul D ca port de iesire
OUT PORTD,R16
endinit: ;Sfirsitul initializarii
stackinit: ;Initializarea stivei
LDI R17,LOW(RAMEND)
OUT SPL,R17
LDI R17,HIGH(RAMEND)
OUT SPH,R17
endstackinit: ;Sfirsitul initializarii stivei

main_loop: ;Inceperea procesarii

PUSH R18 ;Securizam registrii


PUSH R19
PUSH R20
PUSH R21

IN R18,PINA ;Incarcam val. din port in reg. pentru a putea lucra in continuare cu valorile
acestora
IN R19,PINB ;AH:AL(R18:R19)
;RH:RL(R20:R21)
CALL MYMUL ;Apelul subrutinei pt inmultire

OUT PORTC, R20 ;AH ;Afisarea rezultatului pt inmultire


OUT PORTD, R21 ;AL

POP R21 ;Restabilim registrii


POP R20
POP R19
POP R18

RJMP main_loop
endmain_loop:
ret

MYMUL: ;Eticheta subrutinei de inmultire


PUSH R22
CLR R20 ;Curatim rezultatul high
CLR R21 ;Curatim rezultatul low

L0: CPI R18,0 ;Verificam daca valoarea PINA = 0


BREQ MYMUL_END ;Daca da,sare la sfirsitul subrutinei
L1: CPI R19,0 ;Daca nu,verificam daca valoarea PINB = 0
BREQ MYMUL_END ;Daca da, sare la sfirsitul subrutinei

L2: SBRS R19,0 ;Verificam daca bitul din registru este setat
RJMP L4 ;Daca nu sare la L4, daca da merge in continuare la L3

L3: ADD R21, R18 ;Adunam aritmetic fara transport, valorile de low AL:RL
ADC R20, R22 ;Adunam cu transport, valorile de high AH:RH
L4: LSL R18 ;Shiftare logica la stinga
ROL R22 ;Rotare la stinga peste bitul de transport
LSR R19 ;Shiftare logica la dreapta

RJMP L1
POP R22

MYMUL_END: ;Sfirsitul subrutinei de inmultire


RET
4. Controlam de erori sintaxice codul obtinut:

5. Cream schema electrica a circuitului in Proteus verificind daca avem erori logice.
Schema electrica:

Fig.2: Schema electrica,exemple de inmultire

Pentru efectuarea lucrarii am folosit microcontrolerul ATMega 32, 7SEG-BCD si switch-ul


(DIPSWC_8). Am conectat la fiecare port de intrare (PORTA,PORTB) cite un switch ,iar la iesire am
conectat 4 BCD-uri. Cu switch alegem combinatia ce dorim sa o introducem. Pentru a vizualiza valorile
hexazecimale ce corespund combinatiei introdusa la intrari de asemenea conectam BCD-uri.Schema
functioneaza astfel: introducem cite o combinatie la fiecare intrare. Conform codului incarcat in
microcontroler, se va efectua inmultirea iar solutia va fi transmisa la iesire(PORTC(val.high),
PORTD(val low))si vizualizata.

6. Concluzii:
In urma efectuarii lucrarii de laborator am studiat si am utilizat subrutinele.Am realizeazat
inmultirea a doua numere. Am inteles cum se poate de lucrat cu subrutinele, apoi am afisat
rezultatele pe indicatoare de 7 segmente. Am utilizat subrutinele securizate si am observat ca ele
ne permit sa nu afectam starea globala a controlerului (valorile registrilor utilizati dupa executia
subrutinei ramin aceleasi).

S-ar putea să vă placă și