2015 cap 8 programarea multimodul

27
Cap. 8 Programarea multimodul

Upload: lakatos-andrei

Post on 22-Dec-2015

223 views

Category:

Documents


0 download

DESCRIPTION

Programarea multimodul assembly. Captiolul 8 care se ocupa cu programarea multimodul

TRANSCRIPT

Cap. 8Programarea multimodul

Cerinţele unui modul asamblare la legarea cu un alt modul Directiva PUBLIC

- exporta simboluri definite în modulul asamblare în alte module

PUBLIC [limbaj] simbol {,[limbaj] simbol}

PASCAL, C, BASIC, ASSEMBLER, FORTRAN, PROLOG sau NOLANGUAGE

• nume de proceduri• nume de variabile de memorie• etichete definite cu ajutorul directivelor EQU sau =, ale căror valori se reprezintă pe 1 sau 2 octeţi.

Ex: PUBLIC C ProcA

- impune ca simbolul ProcA să fie exportat în celelalte module ca _ProcA, conform regulilor limbajului C.

Cerinţele unui modul asamblare la legarea cu un alt modul Directiva EXTRN

- face vizibile în modulul curent simboluri definite în alte module

EXTRN definiţie {,definiţie}

[limbaj] nume : tip

ABS, BYTE, DATAPTR, DWORD, NEAR, FAR, FWORD, PROC, QWORD, TBYTE, UNKNOWN, WORD

numele simbolului care este definit în alt modul

Ex: EXTRN ProcA: near

Legarea mai multor module asamblare

- fiecare modul are în final o directivă END

- numai directiva END a modulului ce conţine instrucţiunea de la care programul trebuie să-şi înceapă execuţia va conţine specificarea adresei de start.

End start End End

Modul 1 Modul 2 Modul 3

Exemplu

Sir1 db …Sir2 db …SirFinal db … public SirFinal

extrn Concatenare:near

SirFinal = Concatenare(Sir1, Sir2)

extrn SirFinal: byte

Concatenare proc(Sir1, Sir2): byte;

public Concatenare

Declaratii variabile

Declaratii variabile

Declaratii subrutine

Declaratii subrutine

Apeluri subrutine

Modulul main.asm Modulul sub.asm

Programul principal main.asm:

.MODEL SMALL

.STACK 200

.DATASir1 DB 'Buna ', 0Sir2 DB 'dimineata!', '$', 0SirFinal DB 50 DUP (?)PUBLIC SirFinal; se poate înlocui cu GLOBAL SirFinal:BYTE

.CODEEXTRN Concatenare:PROC

Start:mov ax, @datamov ds, ax ; încărcarea registrului dsmov ax, OFFSET Sir1mov bx, OFFSET Sir2call Concatenare;SirFinal:=Sir1+Sir2mov ah, 9mov dx, OFFSET SirFinalint 21h ;tipărirea şirului obţinutmov ah, 4chint 21h

; terminarea programuluiEND Start

Modulul secundar sub.asm:

.MODEL SMALL

.DATAEXTRN SirFinal:BYTE ; se poate înlocui cu GLOBAL SirFinal:BYTE.CODEPUBLIC ConcatenareConcatenare PROC cld mov di, SEG SirFinal mov es, di mov di, OFFSET SirFinal ;es:di <- adresa şirului final mov si, ax ; ds:si <- adresa primului şir Sir1Loop: lodsb ; al <- caracterul curent and al, al ; verifică dacă e zeroul final jz cont stosb ; dacă nu, îl pune în destinaţie jmp Sir1Loop ; reia operaţiile cont: mov si, bx ; ds:si <- adresa celuilalt şir Sir2Loop: lodsb stosb ; încarcă şi zeroul final and al, al jnz Sir2Loop ret ; revenirea din procedurăConcatenare ENDPEND

Programul principal main.asm:

DATA SEGMENTSir1 DB 'Buna ', 0Sir2 DB 'dimineata!', '$', 0SirFinal DB 50 DUP (?)PUBLIC SirFinal

DATA ENDS

CODE SEGMENT EXTRN Concatenare:PROC

(sau EXTRN Concatenare:FAR)Start:

mov ax, datamov ds, axmov ax, OFFSET Sir1mov bx, OFFSET Sir2call FAR PTR Concatenare

(si atunci ramane call Concatenare) ;SirFinal:=Sir1+Sir2

mov ah, 9mov dx, OFFSET SirFinalint 21h ;tipărirea şirului obţinutmov ah, 4chint 21h

END Start

Modulul secundar sub.asm:

ASSUME CS:CODE

EXTRN SirFinal:BYTE PUBLIC Concatenare CODE SEGMENT Concatenare PROC cld mov di, SEG SirFinal mov es, di mov di, OFFSET SirFinal ;es:di <- adresa şirului final mov si, ax ; ds:si <- adresa primului şir Sir1Loop: lodsb ; al <- caracterul curent and al, al ; verifică dacă e zeroul final jz cont stosb ; dacă nu, îl pune în destinaţie jmp Sir1Loop ; reia operaţiile cont: mov si, bx ; ds:si <- adresa celuilalt şir Sir2Loop: lodsb stosb ; încarcă şi zeroul final and al, al jnz Sir2Loop ret ; revenirea din procedură Concatenare ENDPEND

Cele două module vor fi asamblate separat:

TASM MAIN[.ASM]

TASM SUB[.ASM]

Editarea legăturilor se va face:

TLINK MAIN[.OBJ]+SUB[.OBJ]

sau

TLINK MAIN[.OBJ] SUB[.OBJ]

Va rezulta un program executabil main.exe care, lansat în execuţie, va tipări mesajul "Buna dimineata!".

Legarea de module asamblare cu module scrise în limbaje de nivel înalt Cerinţe ale editorului de legături. Intrarea în procedură. Nealterarea valorilor unor regiştri. Transmiterea şi accesarea parametrilor. Alocarea de spaţiu pentru datele locale (opţional). Întoarcerea unui rezultat (opţional). Revenirea din procedură.

Cerinţe ale editorului de legături. Intrarea în procedură. Nealterarea valorilor unor regiştri. Transmiterea şi accesarea parametrilor. Alocarea de spaţiu pentru datele locale (opţional). Întoarcerea unui rezultat (opţional). Revenirea din procedură.

- numele segmentelor sunt impuse de limbajele de nivel înalt cu care se face legătura;

- orice simbol care este definit în modulul scris în limbaj de asamblare şi se doreşte a fi folosit în modulul scris în limbaj de nivel înalt trebuie făcut vizibil în acesta din urmă, utilizând directiva PUBLIC;

- orice simbol care este definit în modulul scris în limbaj de nivel înalt şi care va fi utilizat în modulul scris în limbaj de asamblare trebuie declarat ca extern în acesta din urmă, utilizând directiva EXTRN;

Cerinţe ale editorului de legături. Intrarea în procedură. Nealterarea valorilor unor regiştri. Transmiterea şi accesarea parametrilor. Alocarea de spaţiu pentru datele locale (opţional). Întoarcerea unui rezultat (opţional). Revenirea din procedură.

Directiva de compilare $L (poate să apară oriunde în textul sursă Pascal. )

{$L nume[.obj]}

Fişierul nume.obj să îndeplinească condiţiile:

- toate procedurile şi funcţiile trebuie să se afle într-un segment numit CODE sau CSEG, sau într-un segment al cărui nume se termină cu _TEXT;- toate datele iniţializate trebuie să fie plasate într-un segment numit CONST sau într-un segment al cărui nume se termină cu _DATA;- toate datele neiniţializate trebuie să fie plasate într-un segment numit DATA sau DSEG, sau într-un segment al cărui nume se termină cu _BSS;

Turbo

Assembler *

Turbo

Pascal

Declaraţiilor de tip standard din Pascal le corespund, în limbaj de asamblare, următoarele tipuri:

Integer – WORDReal – FWORDSingle – DWORDPointer – DWORD

Cerinţe ale editorului de legături. Intrarea în procedură. Nealterarea valorilor unor regiştri. Transmiterea şi accesarea parametrilor. Alocarea de spaţiu pentru datele locale (opţional). Întoarcerea unui rezultat (opţional). Revenirea din procedură.

Turbo

Assembler *

Turbo

Pascal

Turbo Pascal- Un subprogram utilizat in programul Pascal dar definit într-un alt modul trebuie să fie declarat cu ajutorul directivei EXTERNAL (numai la nivelul cel mai exterior al programului sau unităţii):

Procedure AsmProc (a:Integer; b:Real); external;

Function AsmFunc (c:Word; d:Byte): Integer; external;

Turbo AssemblerSingurele obiecte care pot fi exportate dintr-un modul scris în limbaj de asamblare într-un program sau unitate Pascal sunt etichetele de instrucţiuni sau nume de proceduri declarate PUBLIC.

CODE SEGMENTAsmProc PROC NEAR

PUBLIC AsmProc...

AsmProc ENDPAsmFunc PROC NEAR

PUBLIC AsmFunc...

AsmFunc ENDPCODE ENDSEND

Cerinţe ale editorului de legături. Intrarea în procedură. Nealterarea valorilor unor regiştri. Transmiterea şi accesarea parametrilor. Alocarea de spaţiu pentru datele locale (opţional). Întoarcerea unui rezultat (opţional). Revenirea din procedură.

Turbo

Assembler *

Turbo

Pascal

Turbo Assembler- Un modul TASM poate accesa orice procedură, funcţie, variabilă sau constantă cu tip declarată la nivelul cel mai exterior al unui program sau al unei unităţi Pascal, inclusiv rutinele din biblioteci. Acest lucru se face cu ajutorul declaraţiei EXTRN

DATA SEGMENTASSUME DS:DATAEXTRN A: BYTEEXTRN B: WORDEXTRN C: BYTE...

DATA ENDSCODE SEGMENT

EXTRN ProcA:NEAREXTRN FuncA:FAR...

; aici pot fi utilizate variabilele a, b, c şi pot fi apelate subprogramele ProcA, FuncACODE ENDS

Turbo Pascal...{variabile globale} Var a: Byte; b: Word; c: ShortInt;...Procedure ProcA;...{$F+}Function FuncA:Integer;...

Cerinţe ale editorului de legături. Intrarea în procedură. Nealterarea valorilor unor regiştri. Transmiterea şi accesarea parametrilor. Alocarea de spaţiu pentru datele locale (opţional). Întoarcerea unui rezultat (opţional). Revenirea din procedură.

- În momentul în care se face un apel de procedură sau funcţie, apelatorul pune mai întâi în stivă adresa de revenire, pe urmă dă controlul subprogramului apelat folosind pentru aceasta o instrucţiune CALL.

- Această adresă de revenire poate să fie o adresă FAR sau o adresă NEAR, în funcţie de modelul de memorie în care este compilat sau asamblat modulul.

- Este foarte important ca instrucţiunea de revenire din subprogram să execute o revenire care să corespundă apelului.

- Dacă se doreşte apelarea dintr-un modul scris în limbaj de nivel înalt (respectiv limbaj de asamblare) a unui subprogram scris în limbaj de asamblare (respectiv limbaj de nivel înalt), editorul de legături care leagă cele două module nu verifică dacă tipul apelului (far sau near) corespunde cu tipul revenirii. Această potrivire cade în sarcina programatorului.

Cerinţe ale editorului de legături. Intrarea în procedură. Nealterarea valorilor unor regiştri. Transmiterea şi accesarea parametrilor. Alocarea de spaţiu pentru datele locale (opţional). Întoarcerea unui rezultat (opţional). Revenirea din procedură.

- Limbajele de nivel înalt impun ca anumiţi regiştri să-şi păstreze la ieşire valoarea cu care intră într-o procedură.

- În acest scop, dacă subprogramul, definit în limbaj de asamblare, modifică unii dintre aceştia, atunci valorile lor de intrare trebuie salvate (eventual în stivă). Ele vor fi restaurate înainte de revenirea din procedură.

- Când este făcut un apel la o funcţie sau procedură trebuie păstrată nealterată valoarea a patru regiştri: SS, DS, BP, SP

- În momentul apelului:SS punctează spre segmentul de stivăDS punctează spre segmentul de date global (numit DATA)BP punctează spre baza stiveiSP punctează vârful stivei.

Turbo Pascal – Turbo Assembler

Cerinţe ale editorului de legături. Intrarea în procedură. Nealterarea valorilor unor regiştri. Transmiterea şi accesarea parametrilor. Alocarea de spaţiu pentru datele locale (opţional). Întoarcerea unui rezultat (opţional). Revenirea din procedură.

- prin referinţă NEAR: în stivă se pune, pe un cuvânt, offset-ul adresei;- prin referinţă FAR: în stivă se pun două cuvinte; mai întâi se pune segmentul, pe urmă se pune offset-ul;- prin valoare: în stivă se pune valoarea parametrului.

Procedure ProcA(i:integer; var j:integer); external;- presupunem ca apelul este de tip NEAR Stiva dupa executia

codului de apel pt ProcAProcA PROC NEAR PUBLIC ProcA j EQU DWORD PTR [BP+4] i EQU WORD PTR [BP+8] PUSH BP ; cod de intrare in ProcA MOV BP, SP ... MOV AX, i ; încarcă în AX valoarea parametrului i LES DI, j MOV ES:[DI], AX ; j:=i …

Turbo Pascal – Turbo Assembler

BP iniţial

offset. adr. revenire

offset j

adr. seg. j

valoarea lui i

BP+2

BP+4

BP+6

BP=SP

BP+8

! Turbo Pascal – parametri transmisi prin referinta sunt de tip far

Turbo

Assembler *

Turbo

Pascal

TIP CE SE PUNE ÎN STIVĂ

Char - octet fără semn

Boolean - octet (valoare 0 sau 1)

tip enumerare - octet fără semn, dacă enumerarea are cel mult 256 de valori- cuvânt fără semn, în caz contrar

Real - 6 octeţi în stivă (excepţie !)

tip reprezentat în virgulă flotantă

- 4, 6, 8, 10 octeţi în stiva coprocesorului numeric

Pointer - 2 cuvinte în stivă

String - pointer (far) la valoare

tip mulţime - adresa unei mulţimi care ocupă 32 de octeţi

Array, Record - valoarea în stivă, dacă lungimea este de 1, 2 sau 4 octeţi- pointer la valoare, în caz contrar

Cerinţe ale editorului de legături. Intrarea în procedură. Nealterarea valorilor unor regiştri. Transmiterea şi accesarea parametrilor. Alocarea de spaţiu pentru datele locale (opţional). Întoarcerea unui rezultat (opţional). Revenirea din procedură.

Parametri transmisi prin valoare

Cerinţe ale editorului de legături. Intrarea în procedură. Nealterarea valorilor unor regiştri. Transmiterea şi accesarea parametrilor. Alocarea de spaţiu pentru datele locale (opţional). Întoarcerea unui rezultat (opţional). Revenirea din procedură.

- Dacă valoarea lor nu trebuie să se păstreze între două apeluri consecutive ale procedurii atunci acestea vor fi alocate în segmentul de stivă şi le vom numi date volatile.

- În caz contrar spunem că este vorba despre date statice şi spaţiul pentru ele va fi alocat într-un segment diferit de segmentul de stivă, de exemplu în segmentul de date. Alocarea de spaţiu pentru datele statice se face folosind directivele cunoscute DB, DW, DD ş.a.

- Alocarea unui număr de n octeţi (n fiind număr par) pentru datele locale volatile se poate face cu următoarea instrucţiune:

sub sp, n

“Definire” si alocare pt 2 variabile locale in cadrul unei proceduri externe TP (scrisa in limbaj de asamblare si utilizata in Turbo Pascal)

push bpmov bp, spsub sp, 4minim EQU [bp-2]maxim EQU [bp-4]...mov ax, 1mov minim, axmov maxim, ax…

Întoarcerea unui rezultat

- prin intermediul registrilor, daca valoarea intoarsa este reprezentata pe mai putin de 4 octeti- exceptie: valorile de tip real, având lungimea de 6 octeţi, sunt returnate tot prin

intermediul regiştrilor (în DX:BX:AX).

- dacă valoarea întoarsă este mai lungă există alte metode de transmitere a rezultatului către apelator

- rezultat scalar : • 1 octet în AL• 2 octeţi în AX• 4 octeţi În DX:AX (DX conţine partea high)

- rezultat real : în DX:BX:AX

- rezultat reprezentat în virgulă flotantă: în regiştrii coprocesorului numeric;

- rezultat string : într-o zonă temporară alocată de Turbo Pascal în momentul compilării programului care conţine un apel de astfel de funcţie; un pointer la această zonă este pus în stivă înainte de a începe să pună parametrii. Acest pointer nu face parte din lista de parametri, deci nu afectează numărul de octeţi ce trebuie scoşi din stivă la revenirea din procedură (vezi codul de ieşire);

- rezultat pointer: în DX se pune adresa de segment, iar în AX se pune deplasamentul.

Turbo Pascal – Turbo Assembler

Cerinţe ale editorului de legături. Intrarea în procedură. Nealterarea valorilor unor regiştri. Transmiterea şi accesarea parametrilor. Alocarea de spaţiu pentru datele locale (opţional). Întoarcerea unui rezultat (opţional). Revenirea din procedură.

- refacerea valorilor regiştrilor

- refacerea stivei astfel încât în vârf să conţină adresa de revenire.

MOV SP, BPPOP BP

- dacă limbajul de nivel înalt pretinde apelatorului eliberarea spaţiului ocupat în stivă deparametri, aceasta se face cu instrucţiunea

ret nunde n este numărul de octeţi care sunt ocupaţi de către parametri

ExempluModulul M1 (Turbo Pascal) Modulul M2 (asamblare)

var glob:string; s:string;

function Asmf (s:string):string; far; external;

function CitSir:string;far;

s:=CitSir;s := Asmf(s);

Asmf proc (s:string):string; far; public;extrn CitSir: far

CitSir;

Declaraţii variabile Declaraţii variabile

Definiţii şi declaraţii subrutine

Definiţii şi declaraţii subrutine

Apeluri subrutine Apeluri subrutine

P.pas

program TPandASM;var glob: string; s: string;{$L asmf.obj}

function Asmf (s: string): string; far; external;

function CitSir: string; far;var Strn: string; begin

write ('Sirul: ');readln (Strn);CitSir := Strn;

end;

begins := CitSir;glob := 'abc123';s := Asmf(s);writeln(s);readln;

end.

• directiva de compilare $L

• declararea funcţiei Asmf ca fiind externă; această funcţie este definită în modulul scris în limbaj de asamblare dar va fi folosită în acest modul;

• prezenţa directivei far indică modul de apel al acestui subprogram, şi anume prin specificarea atât a adresei de segment cât şi a deplasamentului în cadrul acestui segment}

• nu este nevoie de prezenţa vreunei directive Turbo Pascal pentru a face această funcţie vizibilă în modulul scris în limbaj de asamblare, deoarece un modul scris în limbaj de asamblare poate accesa orice procedură, funcţie, variabilă sau constantă cu tip declarată la nivelul cel mai exterior al unui program sau al unei unităţi Pascal, inclusiv rutinele din biblioteci, prin folosirea declaraţiei extrn în modulul asamblare

Asmf.asmassume cs:_TEXT, ds:_DATA_DATA segment

extrn glob:byte _DATA ends_TEXT segment

extrn CitSir: farAsmf proc far

public Asmfpush bpmov bp, spsub sp, 100hsub sp, 100hrez equ dword ptr [bp+10]copieSir equ byte ptr [bp-100h]sloc equ byte ptr [bp-200h]push dslds si, [bp+6]mov bx, ssmov es, bxlea di, copieSircld mov cx, 00FFh rep movsb

• pentru a se putea face legătura între acest modul şi modulul scris în Turbo Pascal, modulul scris în limbaj de asamblare trebuie să îndeplinească următoarele condiţii:- toate procedurile şi funcţiile trebuie să se afle într-un segment numit CODE sau CSEG, sau într-un segment al cărui nume se termină cu _TEXT;- toate datele declarate trebuie să fie plasate într-un segment numit CONST sau într-un segment al cărui nume se termină cu _DATA;

• declaraţia variabilei glob, definită în modulul Turbo Pascal

• declaraţia funcţiei CitSir, care a fost definită în modulul Turbo Pascal, dar va fi folosită în modulul curent; tipul subrutinei este far

• funcţia Asmf este definită în acest modul dar va fi folosită în modulul Turbo Pascal

• izolarea stivei

• se alocă în stivă 100h octeţi pentru copia parametrului de tip string transmis prin valoare

• se alocă în stivă 100h octeţi pentru rezultatul de tip string întors de către funcţia CitSir, care va fi apelată în acest subprogram

BP iniţial

offset adr. revenire

seg. adr. revenire

offset s

adr. seg. s

offset rez

adr. seg. rez

BP+0

BP+2

BP+6

BP

BP+10

Adresa de revenire

Adresa şirului transmis ca parametru

Adresa zonei de memorie unde va fi stringul

rezultatîntors de către funcţia Asmf

256 octeţi pentru copia parametrului de tip string

transmis funcţiei Asmf

SP

Efect al codului de intrareîn Asmf, scris explicit de catre programator pentru ca procedura este scrisa in asamblare si codul de intrare nu este generat automat

Efect al codului de apel al funcţiei Asmf, generat automat de catre compilatorul Turbo Pascal pentru ca apelul subprogramului are loc in Turbo Pascal

BP-100h(copieSir)

BP-200h(sloc)256 octeţi pentru

rezultatul de tip string întors de

funcţia CitSir

Fig. 8.2. Organizarea stivei după apelul şi intrarea în funcţia Asmf.

Asmf.asm

push ss

lea ax, sloc

push ax

call CitSir

. . .

offset adr. revenire

seg. adr. revenire

offset sloc

adr. seg. sloc (SS)

. . .

Efect al lui call CitSir

Generat explicit de către programator

Efect al codului de apel al funcţiei CitSir (faţă de apelul funcţiei Asmf, aici lipsesc parametri deoarece CitSir nu are parametri), scris explicit de catre programator pentru ca procedura este apelata in asamblare si codul de apel nu este generat automat

Stackframe-ul rutinei apelante Asmf (vezi figura 8.2.)

• spaţiul pentru şirul rezultat este alocat în stivă, aşadar adresa de segment a şirului rezultat este ss• salvăm în stivă această adresă si deplasamentul• apelul funcţiei CitSir, care citeşte un şir şi îl depune la adresa ss:sloc

Fig. 8.3. Organizarea stivei după apelul rutinei CitSir.

Asmf.asmpop axpop axles di, rezcldmov bx, ss mov ds, bxlea si, copieSirmov ch, 0mov cl, byte ptr [si]inc sipush diinc dicmp cx, 10jb et1mov cx, 10et1:

rep movsbpush sspop ds lea si, slocmov cl, byte ptr [si]inc sicmp cx, 10jb et2

• eliberarea zonei din stivă în care s-a pus adresa şirului rezultat este responsabilitatea apelatorului

• alternativ add sp, 4

• numărul de elemente al şirului transmis ca parametru se află în primul octet al şirului

• în continuare vom copia în şirul rezultat primele 10 caractere din şirul returnat de către funcţia CitSir (şirul sloc)• în acest scop, încărcăm în ds:si adresa de început a şirului sloc

• instrucţiunea movsb se va executa de cx ori; această instrucţiune copiază la adresa es:di (unde se află şirul rezultat) un octet de la adresa ds:si (unde se află copia şirului transmis ca parametru)

Asmf.asmet2:

rep movsblea si, globmov ax, _DATAmov ds, axmov cl, byte ptr [si]inc sicmp cx, 10jb et3mov cx, 10

et3:rep movsbpop axmov bx, disub bx, axdec bxles di, rezmov es:[di], blpop ds

mov sp, bppop bpret 4

asmf endp_TEXT endsend

• restaurăm valoarea pe care ds o avea la intrarea în subrutină

• refacem valorile lui sp şi bp (parte a codului de ieşire din subrutina Asmf• cu această ocazie se eliberează cei 200h octeţi alocaţi pentru stringul întors de CitSir şi pentru copia parametrului transmis către Asmf

• ieşire din funcţie cu scoaterea din stivă a 4 octeţi (este vorba despre scoaterea din stivă a parametrului – 2 octeţi pentru adresa de segment şi 2 octeţi pentru deplasament)

• eliberarea spaţiului din stivă ocupat de parametri face parte tot din codul de ieşire din subrutină

Cod de iesire din functia Asmf, scris explicit de catre programator, deoarece functia este scrisa in asamblare si codul de iesire nu este generat automat