duminică, 17 iulie 2016

Transferul parametrilor, asamblare.

Transferul parametrilor către proceduri

1.1. Tipuri de transfer (prin valoare sau prin referinţă)

O primă chestiune care trebuie decisă în proiectarea unei proceduri este tipul de transfer al parametrilor. Se
pot utiliza două tipuri de transfer:
• transfer prin valoare, care implică transmiterea conţinutului unei variabile; se utilizează atunci când
variabila care trebuie transmisă nu este alocată în memorie, ci într-un registru;
• transfer prin referinţă, care implică transmiterea adresei de memorie a unei variabile; se utilizează
atunci când trebuie transmise structuri de date de volum mare (tablouri, structuri, tablouri de
structuri, etc.). Se mai foloseşte atunci când procedura trebuie să modifice o variabilă parametru
formal alocată în memorie.
Să considerăm o procedură aduna, de tip near, care adună două numere pe 4 octeţi, întorcând rezultatul în
perechea de registre DX:AX:
 .data
 n1 dd 12345H
 n2 dd 54321H
 rez dd ?
 .code
 aduna proc near
 add ax, bx
 adc dx, cx
 ret
 aduna endp
 ……
 mov ax, word ptr n1
 mov dx, word ptr n1+2
 mov bx, word ptr n2
 mov cx, word ptr n2+2
 call near ptr aduna
 mov word ptr rez, ax
 mov word ptr rez+2, dx
Să considerăm acum varianta transmiterii prin referinţă a parametrilor, în care se transmit către procedură
adresele de tip near ale variabilelor n1 şi n1.
 aduna proc near
 mov ax, [si]
 add ax, [di]
 mov dx, [si+2]
 adc dx, [di+2]
 ret
 aduna endp
 ……
 lea si, n1
 lea di, n2
 call near ptr aduna
 mov word ptr rez, ax
 mov word ptr rez+2, dx

1.2. Transfer prin registre

Avantajul transferului prin registre constă în faptul că, în procedură, parametrii actuali sunt disponibili
imediat. Principalul dezavantaj al acestei metode constă în numărul limitat de registre. Pentru conservarea
registrelor se foloseşte următoarea secvenţă de apel:
• salvare în stivă a registrelor implicate în transfer;
• încărcare registre cu parametri actuali;
• apel de procedură;
• refacere registre din stivă.

1.3. Transfer prin zonă de date

În această variantă, se pregăteşte anterior o zonă de date şi se transmite către procedură adresa acestei zone
de date. În exemplul următor transferul parametrilor către procedura aduna se face printr-o zonă de date:
 .data
 zona label dword
 n1 dd 12345H
 n2 dd 54321H
 rez dd ?
 .code
 aduna proc near
 mov ax, [bx]
 add ax, [bx+4]
 mov dx, [bx+2]
 adc dx, [bx+6]
 ret
 aduna endp
 ……
 lea bx, zona
call near ptr aduna
 mov word ptr rez, ax
 mov word ptr rez+2, dx

1.4. Transfer prin stivă

Transferul parametrilor prin stivă este cea mai utilizată modalitate de transfer. Avantajele acestei metode
sunt uniformitatea şi compatibilitatea cu limbajele de nivel înalt. Tehnica de acces standard la parametrii
procedurii se bazează pe adresarea bazată prin registrul BP, care presupune registrul SS ca registru implicit
de segment. Accesul se realizează prin următoarele operaţii, efectuate la intrarea în procedură:
• se salvează BP în stivă;
• se copiază SP în BP;
• se salvează în stivă registrele utilizate de procedură;
• se accesează parametrii prin adresare indirectă cu BP.
La încheierea procedurii, se execută următoarele operaţii:
• se refac registrele salvate;
• se reface BP;
• se revine în programul apelant prin RET.
Calculul explicit al deplasamentelor parametrilor reprezintă o sursă potenţială de greşeli, de aceea se
utilizează un şablon care conţine imaginea stivei, de la registrul BP în jos. Să considerăm procedura aduna
de tip near, care primeşte parametrii n1 şi n2 prin stivă
.data
 n1 dd 12345H
 n2 dd 54321H
 rez dd ?
 sablon struc
 _bp dw ?
 _ip dw ?
 n2_low dw ?
 n2_high dw ?
 n1_low dw ?
 n1_high dw ?
 sablon ends
 .code
 aduna proc near
 push bp
 mov bp, sp
 mov ax, [bp].n1_low
 add ax, [bp].n2_low
 mov dx, [bp].n1_high
 adc dx, [bp].n2_high
 pop bp
 ret
 aduna endp
 ……
 push word ptr n1+2
 push word ptr n1
 push word ptr n2+2
 push word ptr n2
 call near ptr aduna
add sp,8
 mov word ptr rez, ax
 mov word ptr rez+2, dx
În cazul în care procedura este de tip far, pentru adresa de revenire trebuie rezervate în şablon 4 octeţi
(adresă completă):
sablon struc
 _bp dw ?
 _cs_ip dd ?
 n2_low dw ?
 n2_high dw ?
 n1_low dw ?
 n1_high dw ?
 sablon ends
 .code
 aduna proc far
 push bp
 mov bp, sp
 mov ax, [bp].n1_low
 add ax, [bp].n2_low
 mov dx, [bp].n1_high
 adc dx, [bp].n2_high
 pop bp
 ret
 aduna endp
 ……
 push word ptr n1+2
 push word ptr n1
 push word ptr n2+2
 push word ptr n2
 call far ptr aduna
add sp,8
 mov word ptr rez, ax
 mov word ptr rez+2, dx

2. Întoarcerea datelor de către proceduri

Există următoarele modalităţi de a întoarce datele de către proceduri:
• în lista de parametri apar adresele rezultatelor sau adresa zonei de date care conţine câmpuri pentru
rezultate;
• rezultatele se întorc prin registre;
• rezultatele se întorc în vârful stivei.
Prima tehnică a fost deja descrisă la transmiterea parametrilor prin zonă de date. Practic, în interiorul
procedurii se depun explicit rezultatele la adresele conţinute în parametrii formali respectivi. A doua
tehnică, transferul rezultatelor prin registre, se foloseşte cel mai frecvent. De obicei se foloseşte registrul
acumulator, eventual extins (AL, AX, respectiv DX:AX, după cum rezultatul este pe 1, 2 sau 4 octeţi). A
treia tehnică, transferul rezultatelor prin stivă, se foloseşte destul de rar, fiind total nestandard.

3. Aplicaţii

3.1 Să se scrie un program care determină numărul biţilor 1 dintr-un număr pe 32 de biţi citit de la tastatură
(se vor folosi instrucţiunile SHL şi ADC);
3.2 Să se scrie o procedură care realizează adunarea a două valori citite de la tastatură. Numerele sunt
formate din maxim 32 de cifre.
3.3 Să se scrie un program care converteşte un număr din format BCD împachetat în format BCD
despachetat. Numărul este format din 10 cifre. Rezultatul va fi memorat în zona de date. Pentru
conversie se va utiliza o procedură care primeşte ca parametri adresa numărului BCD împachetat şi
adresa la care va memora numărul BCD despachetat. Cei doi parametri sunt transmişi prin stivă.
Observaţii:
• citirea unui caracter de la tastatură se realizează folosind funcţia 01H a întreruperii 21H. Se încarcă
în registrul AH valoarea 01H, se apelează întreruperea 21H, care va pune codul ASCII al
caracterului citit în AL;
• afişarea unui caracter pe ecran se realizează folosind funcţia 02H a întreruperii 21H. Se încarcă în
registrul AH valoarea 02H. Se încarcă în DL codul ASCII al caracterului care trebuie afişat şi apoi
se apelează întreruperea 21H, care va afişa caracterul pe ecran;
• afişarea unui şir de caractere pe ecran (şirul se termină cu caracterul $, care are codul ASCII 24H)
se realizează folosind funcţia 09H a întreruperii 21H. Se încarcă în registrul AH valoarea 09H. Se
încarcă în DS adresa de segment a şirului care trebuie afişat, şi în DX adresa efectivă (offsetul). Se
apelează întreruperea 21H, care va afişa şirul pe ecran.
• pentru trecerea la linie nouă se afişează şirul de caractere:
nl db 13, 10, 24H
 unde 13, 10 reprezintă codul ENTER-ului. 

Niciun comentariu:

Trimiteți un comentariu