Transferul parametrilor pentru proceduri
description
Transcript of Transferul parametrilor pentru proceduri
• Transferul parametrilor pentru proceduriProgramele scrise în LNI folosesc anumite convenţii pentru
transmiterea parametrilor către subprograme. Compilatorul translatează o instrucţiune de apel a unui subprogram astfel: depune în stivă (push) argumentele subprogramului şi apelează apoi subprogramul, cu o instrucţiune de apel (call). În funcţie de compilator argumentele sunt puse în stivă într-o anumită ordine.
În cazul în care se leagă o procedură scrisă în LA cu un program scris într-un LNI trebuie cunoscut modul de transmitere a parametrilor şi convenţiile stabilite de limbajul respectiv pentru apel de subprogram (nume externe, valori returnate).
Parametrii pot fi transmişi prin valoare sau prin referinţă.În Pascal şi în C se cunosc ambele mecanisme de transmitere a
parametrilor. Limbajele de nivel înalt folosesc pentru returnarea de valori către programul apelant, următoarele registre:(AL) - pentru valori de 1 octet;(AX) - pt. valori de 2 octeţi, sau adresă de tip NEAR;(EAX)- valori de 4 octeţi sau adresă de tip NEAR la 386/486;(DX,AX)- valori de 4 octeţi sau pointer FAR, pt. 286;(EDX,EAX)- valori de 8 octeţi sau pointer FAR, pt. 386/486;
Pentru valori mai mari de 4 octeţi, limbajul C consideră valoarea întoarsă în zona de memorie alocată pentru segmentul de date, şi returnează în (DX:AX) pointerul către acea zonă.
Limbajul PASCAL rezervă o zonă de date în stivă: zona rezervată în stivă şi offsetul către aceasta se realizează de către programul apelant; procedura returnează în (DX:AX) pointerul la zonă.
Descărcarea stivei se face în programul apelant, procedura terminându-se cu RET, sau pentru descărcarea unor argumente se poate termina cu RET număr_argumente*dimensiune.
Deci, în principiu, programul apelant realizează operaţiile:- depune argumentele în stivă;- apelează procedura;- descarcă stiva;
Variabilele locale într-o procedură se folosesc pentru a economisi spaţiu de memorie (cu menţiunea că valorile lor nu se transmit în afara procedurii). Spaţiul de memorie necesar pentru variabilele locale se rezervă în stivă şi el este eliberat la terminarea execuţiei procedurii.
Alocarea de spaţiu pentru variabilele locale se realizează cu o secvenţă de forma:
push bpmov bp,spsub sp,n ; n = număr de octeţi alocaţi;
Pentru accesarea variabilelor locale se vor utiliza adresări de forma: [BP - 2], [BP - 6], etc.
iar pentru argumente, de forma: [ BP + 2 ], [ BP + 4 ], etc.argument equ <[bp+6]>var_loc equ <[bp-2]>p1 proc far
push bp ; salvare valoare BPmov bp,sp ; iniţializare cu vârful curent al stiveisub sp,2 ; rezervare spaţiu pt. var_loc, 2 octeţi mov var_loc,0 ; iniţializare varaibilă locală. . . . . . . . . . mov ax,argument ; se ia argumentul transmis prin stivăadd var_loc,ax ; utilizarea variabilei locale. . . . . . . . . .
mov sp,bp ; eliberarea spaţiului rezervat var_locpop bp ; refacerea valorii lui BPret ; sau ret 2, dacă se descarcă stiva în procedură
p1 endp
Dacă descărcarea stivei nu se face în procedură, atunci în programul apelant trebuie descărcată stiva cu:
add sp, 2
• Convenţiile utilizate de limbajele de nivel înaltpentru transferul parametrilor pentru proceduri
Să considerăm o procedură, definită în PASCAL:procedure modul (a : integer; var b : real);begin. . . . . . end;
iar apelul de forma:modul (x, y);
Pentru această procedură se va genera secvenţa:push bpmov bp,sp BP salvare BP. . . . . . + 2 adresa de reveniremov ax,[bp+8];(AX)x + 4 adr_off var. b. . . . . . + 6 adr_seg var. bles di,[bp+4] + 8 valoarea var. a;(ES):(DI) adresa lui y. . . . . .
; în final se va descărca stivapop bpret 6
Pentru apelul acestei proceduri se va genera secvenţa următoare:mov ax,xpush ax ; depune în stivă valoarea parametrului xmov di, offset ypush ds ; depune adresa de segment a parametrului ypush di ; depune offsetul parametrului ycall modul ; apelul procedurii
În limbajul C, argumentele sunt puse în ordine inversă faţă de ordinea din lista de apel, în care apar (adică de la dreapta la stânga). Adresele de revenire pot fi de tip NEAR, ca în exemplul anterior, sau de tip FAR, în funcţie de modul de definire al procedurii.
Pointerii salvaţi în stivă, ca referinţă de parametru sau ca adresă de revenire respectă definiţia modelului de memorie stabilit în directiva model.
De exemplu stiva va arăta astfel, pentru un singur argument:
- modelul medium
push bp SP, BP salvare bp
mov bp,sp + 2 adr revenire - offset
mov di,[bp+6] adr revenire - segment
mov ax,[di] ; acces argument + 6 adresa argument
; tip cuvânt
- modelul large
push bp SP, BP salvare bp
mov bp,sp + 2 adr revenire - offset
les di,[bp+6] adr revenire - segment
mov ax,es:[di] ; acces argument + 6 adr argument – offset
; tip cuvânt adr arg. – segment
Pentru a nu modifica prea multe linii, în funcţie de modelul utilizat se pot utiliza directivele de asamblare condiţionată:
Ptr_FAR equ 1
. . . . . . . .
push bp
mov bp,sp
. . . . . . . .
ifdef Ptr_FAR
les di,[bp+6]
mov ax,es:[di]
else
mov di,[bp+6]
mov ax,[di]
endif
care dacă este definită va considera modelul large, iar dacă nu este definită va considera modelul medium.
Transferul parametrilor pentru subprograme în PASCAL şi C
program schimba_vectori;type
tip_vector = array [1..20] of real;var
vector1, vector2 : tip_vector;n,i : integer;
{$F+}{$L SCHIMB.OBJ}procedure InterSchimb (var v1, v2 : tip_vector; lung: word);
External;begin
{ se citesc : dimensiunea şi cei doi vectori }InterSchimb (vector1, vector2, sizeof(vector1));{ se afişează cei doi vectori după interschimbare }
end.
Procedura Interschimb (fişierul SCHIMB.OBJ) este următoarea:.model TPascal ; sau model large,Pascal.codestiva struc
val_BP dw ?IP_revdw ? ; sau adr_rev dd ?CS_rev dw ?lung dw ?offs_sir2 dw ? ; sau adr_sir1dd ?seg_sir2 dw ?offs_sir1 dw ? ; sau adr_sir2dd ?seg_sir1 dw ?
stiva endspublic InterShimbInterSchimb proc far
push bpmov bp, sppush ds ; se salvează registrele de lucru
push sipush es push dipush axpush cx ; urmează iniţializările de adrese şi contormov es, [bp].seg_sir1 ; sau les di, [bp].adr_sir1, saumov di, [bp].offs_sir1 ; les di, [bp+8]mov ds, [bp].seg_sir2 ; sau lds si, [bp].adr_sir2, saumov si, [bp].offs_sir2 ; lds si, [bp+12]mov cx, [bp].lung ; sau mov cx, [bp+6]
iar:mov al, ds:[si]xchg al, es:[di]mov ds:[si], alinc siinc diloop iar
pop cx ; refacerea registrelor salvate în stivăpop axpop dipop espop sipop dsret 10 ; se descarcă stiva de cei 10 octeţi
InterSchimb endpend
Linia de declarare a procedurii poate fi şi de forma:
InterSchimb proc far Ad_sir1:dword, Ad_sir2:dword, lung:word
iar în acest caz preluarea parametrilor se poate face mai simplu:
les di,Ad_sir2
lds si,Ad_sir1
mov cx,lung
;function Suma (sir: tip_vector; n:word):integer;External;.model large, Pascalpublic Suma.codeSuma proc far
adr_sir equ <[bp+8]>n equ <[bp+6]>s equ <[bp-2]> ; variabila locală pt. sumăpush bpmov bp, spsub sp, 2 ; rezervare spaţiu pt. variabila locală spush ds ; salvarea registrelor de lucrupush sipush cxlds si, adr_sir ; iniţializare adresă, contor, şi sumamov cx, nmov ax, 0mov s, ax
cld ; direcţia de parcurgere a şiruluijcxz gata ; dacă contorul a fost 0 s-a terminat
adun:lodswadd s, axloop adun
gata:mov ax, spop cxpop sipop dsmov sp, bp ; eliberarea spaţiului alocat variabilei locale s pop bpret 6 ; descărcarea stivei de parametrii
Suma endpend
Să considerăm, acum, şi cazul limbajului C. Vom rescrie funcţia suma(). Întrucât codul generat de compilatorul C transformă denumirile parametrilor funcţiei suma() adăugându-le caracterul ”_” la începutul lor, codul modulului apelat cu numele suma() se va numi de fapt _suma(); acelaşi lucru se întâmplă şi pentru ceilalţi parametri utilizaţi în ambele module.
.model small, C
.codepublic _suma
_suma procpush bpmov bp, sppush cxpush dspush simov cx, [bp+8]lds si, [bp+4]mov ax, 0 ; iniţializarea sumei cu 0
aduna:add ax, [si]add si, 2loop adunapop sipop dspop cxpop bpret
_suma endpend
#include <stdio.h>extern "C" int suma (int vect[], int dim);void main(void)
{int i, dim, vect[100];printf("Numarul de elemente din vector:");scanf("%d", &dim);printf("Elementele vectorului:\n");for (i=0; i<dim; i++)
{printf("vect[%d]=", i+1);scanf("%d", &vect[i]);}
printf("Suma elementelor vectorului este: %d\n",suma(vect, dim));
}
• Avantajele utilizării limbajului de asamblare- multe medii şi compilatoare LNI prezintă facilităţi de inserare de
linii scrise în limbaj de asamblare (C, Pascal, LabView, etc.).- componente ale sistemului de operare, şi ale altor aplicaţii, care
sunt considerate drept critice şi performante sunt realizate în LA.- programele sunt hibride: ele conţin linii scrise în LNI, dar pot
conţine şi linii în LA. - cunoaşterea mecanismelor fine ale procesorului, pentru a le folosi
în diferite aplicaţii. -> prog. mai eficiente în limbajele evoluate.- depanarea unui program poate trece de sursă, şi ajunge la
depanarea codului obiect, în care caz e necesar cunoaşterea LA. - motivul pentru care secvenţele critice se scriu în LA, şi nu în
limbaje de nivel înalt: compilatorul are "cunoştinţe limitate" asupra întregului program, dar el trebuie să genereze un set generalizat de instrucţiuni maşină, care vor lucra în toate situaţiile, dar nu vor fi optime în situaţii particulare.
Exemplu: Să se însumeze elementele unui vector, iar rezultatul să se depună într-o variabilă de memorie.
mov var_mem, 0 ; varianta LNImov si, lung_vect*2 - 2 ; ultimul element: vect + lungime*2 - 2
iar:mov ax, vect[si]add var_mem, axsub si, 2jnz iar
mov ax, 0 ; varianta LAmov si, lung_vect* - 2 ; ultimul element: vect + lungime*2 - 2
iar:add ax, vect[si]sub si, 2jnz iarmov var_mem, ax
Un alt exemplu, tot foarte simplu, dacă considerăm secvenţa generată, în C, pentru o secvenţă de program ce realizează rotirea biţilor dintr-o variabilă.
În timp ce secvenţei în C îi vor corespunde cam 7÷8 instrucţiuni limbaj de asamblare, celei de-a doua secvenţe, scrisă direct în asamblare, îi vor corespunde doar 2 instrucţiuni (respectiv: mov cl,n / rol ax,cl).
În C, pentru o rotire cu n poziţii stânga, trebuie scrise instrucţiunile pentru a realiza următoarele operaţii:
deplasare stânga cu n ranguri a variabilei:variabila1 = variabila << n;
deplasare dreapta cu “dimensiune_variabila – n” ranguri a variabilei:
variabila2 = variabila >> 8*sizeof variabila - n;rezultatul final se obţine printr-un sau logic între cele două
deplasări:variabila = variabila1 | variabila2;
Din punct de vedere al vitezei de execuţie sunt evidente trei lucruri:- instrucţiunile mai scurte, ca dimensiune, se execută mai rapid;- instrucţiunile fără referire la memorie se vor executa mai rapid;- instr. cu moduri de adresare complexe se vor executa mai lent;Din acest motiv se recomandă să păstraţi variabilele în registre.
nmov ax, 100hmov bx, 100hmov cx, 100hadd ax, 100h ; această secvenţă ocupă 12 octeţi în memorie
Putem reduce dimensiunea acestei secvenţe:mov ax, 100hmov bx, axmov cx, axadd ax, ax ; această secvenţă ocupă doar 6 octeţi
În cazul instrucţiunilor de salt condiţionat, programatorul poate determina care condiţie este mai des îndeplinită, şi să aranjeze progr. astfel încât condiţia care este îndeplinită mai des să fie pusă pentru continuarea progr., decât să se realizeze saltul condiţionat.
O altă observaţie utilă în scrierea programelor este legată de hazardurile ce pot să apară. Un tip de hazard este cel legat de date, care apare când operandul sursă al unei instrucţiuni a fost şi operand destinaţie al instrucţiunii anterioare:
mov dx, 400hmov bx, [200h] ; se încarcă în BX cuv. de la adresa 200hmov ax, [bx] ; se încarcă în AX cuv. de la adresa din BX
Este clar că în acest mod de scriere a secvenţei anterioare, instrucţiunea mov ax,[bx] va fi întârziată pe banda de asamblare, cu două cicluri, până când conţinutul lui BX va fi actualizat.
Se poate însă reduce efectul hazardului ce există în această secvenţă de cod, prin simpla rearanjare a instrucţiunilor:
mov bx, [200h] ; se încarcă în BX cuv. de la adresa 200hmov dx, 400hmov ax, [bx] ; se încarcă în AX cuv. de la adresa din BX
Dacă se mai inserează încă o instrucţiune între instrucţiunile mov bx,[200h] şi mov ax,[bx], atunci se poate elimina complet efectul hazardului.
• Definirea şi utilizarea de macroinstrucţiuni• O macroinstrucţiune (MI) reprezintă o secvenţă de instrucţiuni
căreia i se asociază un nume. Apariţia macroinstrucţiunii în textul programului este înlocuită, automat, de către asamblor, cu secvenţa de instrucţiuni asociată. Ea poate să fie parametrizată, adică poate fi definită în funcţie de o serie de parametrii formali, care sunt actualizaţi la utilizarea macroinstrucţiunii, fiind, deci, înlocuiţi cu parametrii actuali.
• Diferenţe între MI şi proc: codul obiect al unei proceduri apare o singură dată în program, în schimb codul obiect generat pentru o MI este repetat în program, ori de câte ori apare numele macroinstrucţiunii. Proc. reduce atât dimensiunea prog. sursă, cât şi pe cea a celui obiect, în timp ce MI nu reduce codul obiect, ci doar dimensiunea programului sursă. MI nu modifică timpul de execuţie al programului, pe când utilizarea procedurilor creşte timpul de execuţie.
• Utilizare macroinstrucţiunilor:- simplificarea şi reducerea secvenţelor de cod ce se repetă;- reducerea erorilor cauzate de codul repetitiv;- program în limbaj de asamblare mai uşor de urmărit.
< nume_macro > MACRO [ lista_parametri_formali ]< declaraţii/ corpul macroinstrucţiunii > [;comentarii]
ENDM
aduna macro t1,t2,sumamov ax, t1add ax, t2mov suma, ax
endm
Utilizarea se poate face astfel:aduna a, b, c mov ax, a
add ax, bmov c, ax
sauaduna bx,cx,dx mov ax, bx
add ax, cxmov dx, ax
• Dacă în definirea unei macro, se utilizează etichete, acestea trebuie declarate LOCAL. De exemplu dacă dorim să realizăm un ciclu, o secvenţă de forma:
mov cx, durata_cicluiar: loop iar
va genera erori de multidefinire a etichetei la utilizările ulterioare.delay macro durata
LOCAL iarpush cx ;; se salvează registrul CXmov cx, durata
iar: loop iar pop cxendm
LOCAL < lista_etichete >• Rolul său este de a declara simbolurile din listă ca locale pentru
fiecare apel. Directiva se poate utiliza numai în MI, şi precede instrucţiunile din corpul MI. Pentru aceste etichete asamblorul va genera, la expandare, nume de etichete succesive:??0000, ??0001, etc.
1) Calculul puterii întregi a unui număr întreg.putere macro numar, exponent
local iar, gatapush cx ; salvare (CX) şi (BX)push bxxor dx, dx ; rezultatul este returnat în (DX, AX)mov ax, 1 ; pregătire rezultat, dacă exponentul e 0mov cx, exponentjcxz gata ; dacă CX=0, puterea este 1mov bx, numar ; înmulţitorul în BX
iar: mul bxjc gata ; dacă apare eroare la *, se poziţionează
CFloop iar
gata: pop bx ; refacerea registrelor salvatepop cxendm ; programul ce utilizează această macro, va testa
; valoarea lui CF, dacă este 0 valoare corectă în; (DX,AX), dacă însă CF=1, a apărut depăşire
2) Înmulţirea unei valori cu 10.ori10 macro xlocal gata
push axpush bxmov ax, xshl ax, 1 ; * 2jc gatamov bx, ax shl ax, 1 ; * 4jc gatashl ax, 1 ; * 8jc gataadd ax, bxjc gata ; după utilizare macro ori10 se vamov x, ax ; testa indicatorul CF pentru a testa
gata: pop bx ; o eventuală depăşirepop axendm
• Macroinstrucţiunea de repetareREPT <expresie_contor>< corpul macroinstrucţiuni >ENDM
1) Alocarea unor valori consecutive la o anumită adresă:alocare macro tabela, lungime, vi, pas
tabela label bytevaloare = vi ; valoare iniţialărept lungime
valoare = valoare + pasdb valoare
endm endm
Utilizare:alocare tab1, 3, 0, 2 tab1 db 2, 4, 6alocare tab2, 10, 0, 1 tab2 db 1 , . . , 10
2) Generarea alfabetului, pentru litere mari, la o anumită adresă.generare_alfabet macro nume
nume label bytei = 0 rept 26
db 'A' + ii = i + 1
endmendm
alocare macro tab, dimtab label byte
i = 0rept dim
if (i gt 255)exitm ;; ieşire forţată din macro
else ;; înainte de execuţia tuturor
db i ;; instrucţiunilor secvenţeiendif
i = i + 1endm
endm
• Macroinstrucţiuni de repetare condiţionată (Indefinite RePeat)
IRP <nume>,<<lista>>< corpul macroinstrucţiunii >
ENDM <nume>, va fi înlocuit, în corpul MI cu valorile din <lista>.1) irp val, <1, 2, 3, 4, 5>
dw val*valendm
dw 1, 4, 9, 16, 25 2) suma label byte
irp x, <1, 3, 5, 7, 9>db x+x
endmsuma db 2, 6, 10, 14, 18
3) irp reg, <ax, cx, dx, bx, sp, bp, si, di>push reg
endm
IRPC (Indefinite RePeat Character) - rolul valorilor numerice din IRP este preluat de caractere.
1) irpc c, 12345dw c*c
endm2) Memorarea, la o adresă a unei valori în zecimal neîmpachetat:
scrie_val macro adresa, valoarelea si, adresairpc v, valoare
mov byte ptr [si], vinc si
endmendmPentru o utilizare de forma:
scrie_val adr1, 1997se va genera secvenţa, de cod, care va 1, 9, 9, 7, în format zec.
Dacă dorim să depunem o anumită secvenţă de caractere ASCII, se modifică doar linia:
mov byte ptr [si], '&v'
Utilizarea operatorilor &, % şi !Operatorul & este utilizat pentru substituirea simbolurilor, pe care le precede, cu valoarea numerică sau subşirul de caractere asociat simbolului respectiv (sau, altfel spus, concatenează valoarea asociată simbolului), în cazul utilizării simbolurilor respective ca argumente (parametrii) ale utilizării unei macroinstrucţiuni.
1) Declararea unor mesaje, iterative, în cadrul unui program:mesaj macro n
msg&n db 'mesaj nr.&n'endm
mesaj 5va genera: msg5 db 'mesaj nr.5'
mesaj 11va genera: msg11 db 'mesaj nr.11’
Dacă MI are 2 parametri sau mai mulţi, atunci ea se defineşte astfel:meserr macro n, o
err&n&o db 'eroare &n&&o'endm
Utilizarea acestei macro de forma: meserr 2,2va genera: err22 db 'eroare 22'
Dublarea caracterului &, a amânat evaluarea şirului &&o, pentru momentul evaluării MI IRP.
2) Compararea reg. AL cu caracterele 'a'..'f', şi execuţia pentru fiecare dintre ele unei anumite secvenţe (eticha, etichb, ..., etichf):irpc car, abcdef
cmp al, '&car'jz etich&car
endm
3) Definirea unei MI pentru rotirea conţinutului unei destinaţii, cu un număr de biţi şi o direcţie, specificate ca parametrii:rotire macro sens, nr_rot, dest
push cx ; salvare CX ; NU salv/reface CXmov cl, nr_rot ; sau reptnr_rot
ro&sens dest, cl ; ro&sens dest, 1
pop cx ; refacere CX ; endmendm
• Operatorul % realizează conversia simbolului care urmează, de la o valoare numerică la un şir de caractere, ce poate fi utilizat pentru a substitui un argument, pentru un apel de MI. Acest operator, de expansiune (%), forţează evaluarea imediată a expresiei ce urmează şi converteşte rezultatul expresiei la un şir de cifre.
mesaj5 macro nume,valdb '&nume = &val'
endmşi declaraţia:
const1 equ <LOW>pentru a defini mesajul
db 'const1 = LOW'se va utiliza MI anterioară, cu următorii parametrii:
mesaj5 const1, %const1Parantezele unghiulare < > se utilizează pentru a specifica că textul dintre ele este un singur şir. Aceste paranteze se utilizează şi când se doreşte transmiterea unui parametru actual, pentru un apel intern de macro (apelul unei macro în altă macro).
Generarea de mesaje multiple, care respectă o anumită regulă:meserr macro n
err&n db 'eroare&n’, 0Dh, 0Ah, ‘$'endmdiferr macro x
m = 0rept x
m = m + 1meserr %m
endmendm
Un apel al acestei macroinstrucţiuni, de forma:diferr 3
va genera mesajele:err1 db 'eroare1’, 0Dh, 0Ah, ‘$'err2 db 'eroare2’, 0Dh, 0Ah, ‘$'err3 db 'eroare3’, 0Dh, 0Ah, ‘$'
Un exemplu de utilizare pentru parantezele unghiulare:mesaj7 macro sir
db '&sir',0 ;; definire şir de caractere ASCIIZendm
apelul: mesaj7 <sir caractere>va genera db 'sir caractere',0
• Alt operator important pentru macroinstrucţiuni este operatorul literal, semnul exclamării (!). Acest simbol comandă asamblorului ignore interpretarea caracterului următor. Acest simbol poate fi utilizat atunci când este nevoie ca unul din următoarele caractere să fie inclus într-un şir de caractere, într-o MI: ! & > %
Dacă dorim să transmitem ca argument pentru o MI un şir de caractere ce conţine şi caracterul '>', atunci el va fi precedat de caracterul !, pentru a evita interpretarea lui '>' ca sfârşit de şir.
mesaj7 <a!>b>care va genera mesajul
db 'a>b',0
• Directive de asamblare condiţionată• Asamblorul permite utilizatorului să realizeze asamblarea doar a
unei anumite părţi a liniilor care compun modulul sursă. Este important de reţinut că aceste directive evaluează expresiile lor la momentul asamblării şi nu la cel al execuţiei programului.
• Motivele asamblării condiţionate:- un program general trebuie 'adaptat' pentru o anumită aplicaţie, funcţie de parametrii actuali incluzându-se anumite module, sau dimensionându-se zone de memorie, corespunzător aplicaţiei; altfel, prin includerea tuturor modulelor sau prin dimensionarea la maxim a zonelor de memorie, indiferent de aplicaţie, se ajunge la dimensionări neeconomice;- includerea doar a unora dintre instrucţiunile prezente, în textul sursă, datorită unor diferenţe între procesoarele aceleiaşi familii (286, 386, 486, etc.).
• Directivele de asamblare condiţionată sunt importante deoarece permit generarea de diferite coduri obiect pentru diferite medii de operare şi diferite situaţii. Pe durata asamblării, programatorul poate alege condiţionat dacă asamblorul să asambleze, de exemplu, versiunea pentru 386 sau pentru Pentium.
Sintaxa pentru directiva IF este următoarea:IF condiţie ; condiţia este o expresie ce poate
secvenţa 1 ; fi evaluată, în momentul asamblării[ELSE ; la o constantă 'TRUE' sau 'FALSE'
secvenţa 2] ; clauza ‘else’ este opţionalăENDIF
În mod asemănător sunt definite directivele:IFE exp ; dacă expresia este zero se execută secv1
; altfel se execută secv2IFB arg ; dacă argumentul este blanc (' ') se
; executa secv1, altfel se execută secv2IFNB <arg ; adică argumentul <> blanc se execută secv1,
; altfel, argument =' ', execută secvenţa 2.IFDIF <arg1>, <arg2> ; se compară cele două argumente,
; (senzitiv la tipul literelor: mari şi mici), şi; dacă sunt diferite execută secv1, altfel secv2
IFDIFI <arg1>, <arg2>; este asemănătoare cu dir. anterioară, ; cu deosebirea că ignoră tipul literelor.
IFIDN <arg1>, <arg2> ; se compară cele două argumente, ; (senzitiv la tipul literelor: mari şi mici), şi; dacă sunt identice exec. secv1, altfel secv2
IFIDNI <arg1>, <arg2> ; este asemănătoare cu dir. anterioară, ; cu deosebirea că ignoră tipul literelor.
IFDEF <argument> ; dacă simbolul prezent ca arg. este; definit execută secv.1, altfel secv.2
IFNDEF <argument> ; dacă simbolul prezent ca arg. nu ; este definit execută secv.1.
tip_car macro car ; utilizare:ifb <car> tip_car 'x' ;generează
mov dl, ' ' mov dl, 'x'else mov ah, 2mov dl, car int 21h
endif tip_car ; va generamov ah, 2 mov dl, ' 'int 21h mov ah, 2
endm int 21h
MI recursivă care depune registre în stivă; depunerea va înceta când în lista registrelor apare blancul.push_reg macro r1, r2, r3 ; utilizare:
ifnb <r1> push_reg ax, bx, cxpush r1 push axpush_reg r2, r3 push bx
endif push cxendmMI ce generează diferite instrucţiuni în funcţie de un param.movt macro tip
ifidn <tip>, <B> ; utilizare: movt Drep movsd ; sau: movt Wexitm ; sau: movt
endififidn <tip>, <W>
rep movswelse rep movsb ; implicit, dacă nu are paramteruendif
endm
• Directive pentru generarea condiţionată a erorilor
În conjuncţie cu directivele de asamblare condiţionată, există un set de directive pentru generarea de mesaje de eroare, în aceleaşi condiţii ca primele. Asamblorul generează mesajul de eroare la întâlnirea unei astfel de directive, dacă este îndeplinită condiţia respectivă. Ele sunt utilizate, cu predilecţie, în cadrul MI.
.ERR - generează mesaj de eroare, de exemplu:
if var1 lt var2
.err ; va genera mesaj dacă: var1 < var2
endif
.ERRE expresie
.ERRNZ expresie
.ERRB <argument>
.ERRNB <argument
.ERRDIF<arg1>,<arg2>
.ERRDIFI <arg1>,<arg2>