You are on page 1of 10

Apelarea funciilor Assembler din C

Compilarea, asamblarea si linkarea cu C, Assembler si TLINK:

Ciclul se pornete cu: bcc 1 2.asm

Instruciunea de mai sus spune C-ului sa compileze 1.c in 1.obj, apoi invoca Assembler-ul s asambleze din 2.asm in 2.obj i n final invoc TLINK-ul pentru a lega 1.obj i 2.obj in fiierul executabil 1.exe. Observaie: Este posibil i compilarea separat a celor dou dar in acest caz programatorul in asm trebuie sa aib grij la toate detaliile de interfaare a codurilor in C i asm pentru c C-ul se descurc cu specificarea segmentelor, trecerea de parametrii, referirile variabilelor C, n schimb, funciile de asamblare compilate separat trebuie s fac totul in mod explicit. Reguli pentru linkarea C si ASM Modulele ASM trebuie s foloseasc o schem de numire a segmentelor compatibile cu C-ul. Modulele C si ASM trebuie s share-uiasc nume de funcii i variabile potrivite, intr-o form acceptabil de C. TLINK trebuie folosit pentru a combina modulele ntr-un .exe

Module de memorie si segmente Pentru ca o funcie asm dat s poat fi apelat din C, funcia trebuie s foloseasc acelasi model de memorie cu programul C si un cod segment C-compatibil. Pentru ca datele definite n modulele asm s fie accesibile din codul C (sau datele C s fie accesibile din asm) trebuie ca codul asm s urmreasc conveniile C de numire a DS-ului. Assemblerul, virtual, implementeaz module i segmente de memorie C.

Directive segment simplificate i C-ul

DOSSEG segment n concordan cu conveniile INTEL ca i C-ul. .MODEL segmentele sunt compatibile cu modelul de memorie ales (tiny, small, compact, medium, large, huge) i controleaz tipul implicit (near/far) al procedurilor create cu directiva PROC. Aceste modele sunt compatibile cu modelele echivalente ale C-ului.

.CODE, .DATA, .FARDATA , .CONST genereaz segmente C-compatibil.

Pentru compilare trebuie introdus linia de comand: bcc nume_c nume_asm.asm

Codul : ASM poate: Apela functii C Referii variabile C externe C poate: Apela functii publice ASM Referii variabile ASM publice C-ul asteapta ca toate etichetele externe s nceap cu _ (n fiierele .asm). n ASM etichetele care nu sunt referite in C nu au nevoie de _ . Litere mari i mici ASM nu este case sensitive, dar C-ul este. Dac se dorete ca i ASM-ul s fie case sensitive, sunt disponibile comenzile: /ml - ASM ul devine case sensitive pentru toate simbolurile. /mx - ASM ul devine case sensitive pentru toate simbolurile declarate cu directivele PUBLIC, EXTERN, GLOBAL i COMM.

Cnd este necesar ncrcarea segmentelor?

La intrarea din C ntr-o funcie asm, regitrii CS i DS au urmtoarele setri, n funcie de memoria folosit (SS este ntotdeauna folosit pentru segmente stiv i ES pentru un registru segment scratch). Model Tiny Small Compact Medium Large Huge CS Text Text Text numefi*_text numefi*_text numefi*_text DS DGROUP DGROUP DGROUP DGROUP DGROUP calling_numefi*_DATA**

*numefi reprezint numele modulului de asamblare **calling_numefi_DATA reprezint numele modulului ce apeleaz modulul de asamblare

Observaie: La intrarea n funcii de tip: Tiny: CS=DS Tiny, small, medium: SS=DS

CS: se seteaz automat n funcie de cum este nevoie n apelurile de tip far, jump-uri i return-uri; SS: pointeaz ctre segmente stiv i nu trebuie schimbat n timpul rulrii unor programe (dect dac se scrie cod n care se schimb stive ntre ele, dar trebuie s tii exact ceea ce facei!!!!!!); ES: poate fi folosit pentru a pointa ctre date deprtate sau poate fi ncrcat ca registrul destinaie al unei instruciuni string; DS: o pointeaz ctre segmente statice de date (DGROUP) la intrarea n funcii (mai puin modelul huge) o pentru modelul huge: fiecare modul are propriul segment de date i este de tip far relativ la toate celelalte module din program, deci DS-ul trebuie setat s pointeze ctre respectivul segment deprtat al modulului.

Corespondena dintre tipurile de date C si ASM


C Unsigned char Char Enum Unsigned short Short Unsigned int Int Unsigned long Long Float Double Long double Near* Far* ASM byte byte word word word word word dword dword dword qword tbyte word dword

Asm vs. C

Trecerea parametrilor C-ul face trecerea parametrilor la funcii pe stiv naintea apelrii unei funcii. nti introduce parametrii funciei respective pe stiv (ncepnd cu parametrul cel mai din dreapta i terminnd cu cel mai din stanga). Exemplu: Apelul unei funcii C, Test(i, j, 1), va introduce pe stiv parametrii n ordinea 1, j, i. Dup return-ul funciei, parametrii sunt nc pe stiv, dar fr folos. Imediat dup fiecare apel de funcie, C-ul ajusteaz pointerul stivei inapoi la valoarea coninut nainte s fie introdui parametrii stivei i elibernd astfel stiva de aceti parametri. Deci, n exemplul de mai sus, avem 3 parametrii x 2 bytes fiecare = 6 bytes. C-ul va aduna 6 la pointerul stivei pentru a scpa de parametrii. Observaie: Dup conveniile de apel ale C-ului, codul apelant este cel responsabil de scoaterea parametrilor din stiv. Funciile assembler-ului pot accesa parametrii stivei relativ la registrul BP (care adreseaz segmentul stiv). Exemplu: .MODEL SMALL .CODE .PUBLIC _Test _Test PROC PUSH BP MOV BP,SP ; BP adreseaz segmentul stiv ; Se incarac SP n BP. Dup ncrcarea BP n SP, se pot ; accesa aceti parametrii relativ la BP. BP-ul trebuie ; prezervat deoarece codul C apelant ateapt ca return-ul ; s fie cu BP-ul neschimbat. MOV AX, [BP+4] ; Ia primul parametru

ADD AX, [BP+6] ; Adun parametrul 2 la primul parametru SUB AX, [BP+8] ; Scade parametrul 3 din sum POP BP RET _Test ENDP END Dac presupunem i=25, j=4 i funcia Test(i, j, 1) n C, atunci starea stivei nainte de execuia instruciunii din Test se poate observa din figura de mai jos:

Dup execuia liniilor

PUSH BP MOV BP, SP

stiva va conine:

Observaie: Spaiul pentru variabilele locale poate fi rezervat prin scderea numrului de bytes din SP. Exemplu: Spaiul pentru 100 bytes pentru un array tip local poate fi rezervat prin a porni Test cu PUSH BP MOV BP, SP SUB SP, 100 ...

Stiva va conine:

Cum poriunea din stiv ce conine variabilele ncepe de la o adres mai mic dect BP, se folosesc pentru adresarea variabilelor offset-uri negative de la BP. Instruciunea MOV BYTE PTR [BP-100],0 va seta primul bit, din cei alocai, la 0. Rezult c parametrii trecui sunt ntotdeauna adresai la offset-uri pozitive fa de BP. Pentru alocarea spaiului se poate folosi directiva LOCAL. ntr-o procedur, se presupune c ntalnirea acesteia definete variabile locale pentru procedura respectiv. Exemplu: LOCAL LocalArray:BYTE:100,LocalCount:WORD:AUTO_SIZE

LocalArray etichet pentru [BP 100] LocalCount etichet pentru [BP 102]

AUTO_SIZE numrul de octei pentru memorarea automat necesar (aceast valoare trebuie sczut din SP pentru alocarea spaiului pentru aceste variabile).

Observaie: LOCAL nu aloc variabile automat, ci genereaz etichete ce pot fi folosite pentru alocarea memoriei i accesarea variabilelor. Alternativ pentru trecerea de parametrii in rutinele de asamblare este directiva ARG care genereaz automat offseturi corecte ale stivei pentru variabilele specificate. Exemplu: ARG FillArray:WORD,Count:WORD,FillValue:BYTE Specific trei parametrii FillArray de tip WORD, Count de tip WORD i FillValue de tip BYTE i, dac se presupune c codul se afl procedur de tip NEAR, va seta eticheta FillArray la [BP + 4] Count la [BP + 6] FillValue la [BP + 8].

Prezervarea registrilor BP, SP, CS, DS si SS pot fi alterai n timpul execuiei unei funcii asm, dar cnd se realizeaz ntoarcerea la codul apelant acetia trebuie s fie exact cum erau nainte de apel. AX, BX, CX, DX, ES i flagurile pot fi schimbai in orice fel. SI i DI sunt regitri variabili pentru C: dac sunt activai din C, atunci trebuie prezervai altfel nu.

Valori returnate O funcie apelabil ASM poate intoarce o valoare:


Tip ntors unsigned char Locaie valori ntoarse AX

char enum unsigned short short unsigned int int unsigned long long float double long double near far

AX AX AX AX AX AX DX:AX DX:AX 8087 top of stack (TOS) register (ST(0)) 8087 top of stack (TOS) register (ST(0)) 8087 top of stack (TOS) register (ST(0)) AX DX:AX

n general, pentru valorile pe 8/16 bii registrul este AX pentru valorile pe 32 bii registrul este DX:AX unde: high DX low AX

You might also like