Tema: Subrutine cu parametri
Laborator Nr 2
Scopul lucrări:
Instructiunea MOV
Instructiuni aritmetice. Instructiunile ADD, SUB, INC, DEC
Instructiunile PUSH/POP
Laborator Nr 2
Scopul lucrări:
- initiere in procesul de chemare a subrutinei,
- protectia starii globale a registrilor
- transmiterea parametrilor catre subrutina
Sarcina lucrarii:
Sa se realizeze un program, care ar realiza calculul
unei expresii simple: a * b + 22 cu ajutorul unei subroutine cu parametri. Sa
se realizeze protectia starii globale a registrilor. Expresia: a*b+22
Consideraţii teoretice:
Formatul subrutinei:
My_sub:
…
…
…
RET
Subrutine poate fi chemata cu: RCALL(ne permite sa chemam o subrutina care nu este mai departe
decat adresa de 256 locatii), ICALL(chemarea
unei subrutine adresa careia se afla intr-un registru indirect. Aceasta comanda
presupune ca adresa subrutinei preeliminar va fi incarcată în registrul
indirect Z), CALL
O etichetă în Assembler va reprezenta adresa curentă.
Pentru a avea salvata adresa de returnare din
subrutină, adresa curentă, de unde a avut loc chemarea subrutinei se va salva
automat în stivă, adică PC + 1 -> Stack (se execută automat 2 PUSH-uri). Apoi are loc salt necondiţionat: PC <- My_sub şi se execută subrutina după ce se realizează PC <- Stack.
Subrutinele
sunt utila atunci când vrem să
executăm un set de instrucţiuni de mai multe ori în diferite locuri a
programului, dar şi pentru modularizarea şi reutilizarea codului.
Subrutina reintrantă presupune că
oricând va fi apelată – vom avea acelaşi rezultat, adică ea nu depinde de
starea globală a sistemului.
Subrutina securizată – execuţia ei nu
modifică starea globală.
Pentru
ca subrutina sa fie securizată, adică
să nu modifice starea globală a regiştrilor se recomandă ca regiştrii utilizaţi
pentru lucrul în interiorul subrutinei să fie salvaţi în stivă la începutul
subrutinei (ex: PUSH R16, PUSH R18) şi restabiliţi imediat înainte de
returnarea din ea (POP R18, POP R16). Ordinea
de restabilire este inversă celei de salvare(LIFO). Numărul de salvări în stivă
trebuie să fie strict egal cu numărul de restabiliri, pentru evitarea spargerii
stivei. Cresterea necontrolată
a stivei va duce la supraîncărcarea stivei şi invers, micşorarea necontrolată a
stivei va provocarea spargerea ei. Subrutina
cu parametri. Parametrii către subrutină pot fi transmişi prin intermediul
regiştrilor de uz general ca valori sau referinţe(pointeri) către anumite
resurse. Pentru returnarea din subrutină
se vor folosi regiştri ca valori sau referinţe. Regiştrii utilizaţi ca
parametrii se vor salva în stivă înainte de iniţializarea lor şi se vor
restabili după colectarea rezultatelor returnate de către subrutină. Regiştrii
utilizaţi ca parametri nu vor fi salvaţi în interiorul subrutinei. Mecanismul
de protejare a lor este realizat în afara subrutinei.
Mersul lucrării:
1) Schema bloc
2)
Următorul
pas este crearea ciruitului în programul de simulare PROTEUS, unde se
demonstrează cum funţionează porturile de I/O şi respectiv programul
microcontrolerului.
Figura 1
Listengul programului:
Descrierea instrucţiunilor
utilizate:
Instructiunea MOV
Sintaxa:
§
mov dest, source // echivalenta cu dest = source
Descriere:
Instructiunea copiaza
o valoare dintr-o locatie in alta locatie. Aceasta locatie poate fi zona de
memorie, variabila, registru. De retinut este ca nu exista variante ale
instructiunii care copiaza direct dintr-o zona de memorie in alta.
Flaguri afectate
Instructiunea mov nu modifica nici un flag.
Restrictii:
Ambii operanzi trebuie
sa aiba aceeasi marime. De exemplu pentru ultima varianta a instructiunii mov
trebuie specificata marimea zonei de memorie. Instructiunea "mov [bx],
0" nu este corecta deoarece compilatorul nu stie ce vrea sa faca instructiunea:
sa copieze valoarea 0 in byte-ul, in word-ul sau in doubleword-ul de la adresa
bx. Astfel variantele corecte sunt:
1
2
3
|
mov byte ptr [bx], 0 mov word ptr [bx], 0 mov dword ptr [bx], 0 |
Exemplu:
mov ax, 3 // ax = 3 mov bx, ax // bx = ax |
Instructiuni aritmetice. Instructiunile ADD, SUB, INC, DEC
Sintaxa:
§
add dest, source // echivalenta cu dest+=source
§
sub dest, source // echivalenta cu dest-=source
§
inc dest // echivalenta cu dest++
§
dec dest // echivalenta cu dest--
Descriere:
Instructiunea "add" este folosita
pentru a aduna doua valori, "sub" pentru a scadea o valoare
din alta, "inc" - incrementarea unei variabile, "dec" - decrementarea
unei variabile (registru/memorie).
Flaguri afectate:
§
carry flag - pentru "signed overflow"
§ overflow flag - pentru overflow
§
sign flag - activat daca rezultatul este negativ
§
zero flag - activat daca rezultatul operatiei a
fost 0
§
parity flag - este setat in functie de paritatea
rezultatului
Restrictii:
Destinatia trebuie sa
aiba aceeasi marime ca si sursa.
Exemplu:
mov ax, 3 // ax = 3 add bx, ax // bx = ax+3 |
Instructiunile PUSH/POP
Descriere:
Aceste instructiuni
sunt folosite pentru accesarea stivei sistemului. Instructiunea PUSH pune pe stiva sistemului o valoare,
iar instructiunea POP extrage
valoarea din varful stivei.
Sintaxa:
§ push val
§ pop val
Instructiunea IN:
Forma: IN destinatie, port
Efect: citeste de la portul dat in destinatie.
Nota: destinatia poate fi doar AX sau AH.
Forma: IN destinatie, port
Efect: citeste de la portul dat in destinatie.
Nota: destinatia poate fi doar AX sau AH.
Instructiunea
OUT:
Forma: OUT destinatie, port
Efect: scrie la portul dat valoarea destinatiei.
Nota: destinatia poate fi doar AX sau AL.
Forma: OUT destinatie, port
Efect: scrie la portul dat valoarea destinatiei.
Nota: destinatia poate fi doar AX sau AL.
Concluzi:
Efectuînd lacrarea
de laborator „Subrutine cu parametri” am aflat inportanţa utilizări subrutinelor.
Subrutina este o 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
(:). Dar mai întîi trebuie de iniţializat stiva şi anume 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.