Documente Academic
Documente Profesional
Documente Cultură
De citit: Dandamudi
Capitolul 3: 3.1, 3.2
Modificat: 4-Nov-21
Curs 02 - 03 1
Cuprins
• Familia x86
• Registrele • Modul real
Data • Segmentare, Paginare
Pointer, index
• Întreruperi
Control
Segment
• Demo sasm, gdb
• Modul protejat • Instrucțiuni mov, add,
Registrele Segment
jmp
Descriptori de segment
Tabele de descriptori
Modele de segmentare
Curs 02 - 03 2
Istoricul procesoarelor Intel
Procesor An Frecvența Tranzistoare Registre Bus date Max addr
4004 1969 0.74 2.3K 4 12 4K
8080 1974 2 4.5K 8 16 64K
8086 1978 8 29K 16 16 1 MB
80386 1985 20 275K 32 32 4 GB
Pentium 1993 60 3.1M 32 40? 4GB
Pentium 4 2000 1500 42M 32 64GB
Core 2 2006 3000 291M 64 64GB
Core i7 2008 3400 1.4G 64 64GB
Xeon E5 2012 3600 5.5G 64 768GB
Curs 02 - 03 3
Arhitectura x86
Curs 02 - 03 4
x86 registre pe 32 biți
• Registre de 32 biți pot fifolosite
Pe 32 biți (EAX, EBX, ECX, EDX)
Pe 16 biți (AX, BX, CX, DX)
Pe 8 bit biți (AH, AL, BH, BL, CH, CL, DH, DL)
Curs 02 - 03 5
x86 registre pe 32 biți
Curs 02 - 03 7
EFLAGS (Indicatorii de stare)
• CF (Carry Flag) - indicator de transport - reflecta transportul in exterior al bitului
cel mai semnificativ al rezultatului operatiilor aritmetice. Astfel, acest indicator
poate fi folosit in cazul operatiilor in dubla precizie. Valoarea CF = 1 semnifica fie
transport la adunare fie imprumut la scadere. De asemenea, indicatorul CF este
modificat si de instructiunile de deplasare si rotatie.
• PF (Parity Flag) - indicator de paritate - este 1 daca rezultatul are paritate para
(contine un numar par de biti 1). Acest indicator este folosit de instructiunile de
aritmetica zecimala.
• AF (Auxiliary Carry Flag) - indicator de transport auxiliar - este 1 daca a fost
transport de la jumatatea de octet inferioara la jumatatea de octate superioara
(de la bitul 3 la bitul 4). Acest indicator este folosit de instructiunile de aritmetica
zecimala.
• ZF (Zero Flag) - indicatorul de zero - este 1 daca rezultatul operatiei a fost zero.
• SF (Sign Flag) - indicatorul de semn - este 1 daca cel mai semnificativ bit al
rezultatului (MSb) este 1, adica in reprezentarea numerelor in complement fata
de 2 (C2) rezultatul este negativ (are semn -).
• OF (Overflow Flag) - indicatorul de depasire aritmetica (a gamei de valori posibil
de reprezentat) - este 1 daca dimensiunea rezultatului depaseste capacitatea
locatiei de destinatie si a fost pierdut un bit (indica la valorile cu semn faptul ca se
"altereaza" semnul).
Curs 02 - 03 Capitol 05 8
EFLAGS(Indicatorii de control)
Curs 02 - 03 Capitol 05 9
x86 registre pe 32 biți
• registre de control
EIP
» Instruction pointer (instrucțiunea curentă)
EFLAGS
» Status flags
– Se actualizează după operații aritmetice/logice
» Direction flag
– Forward/backward direcția copierii
» System flags
– IF : activare intreruperi
– TF : Trap flag (pentru debugging)
Curs 02 - 03 10
x86 registre pe 32 biți
• Registre segment
16 biți
Memoria segmentată
Conținut distinct
» Code
» Data
» Stack
Curs 02 - 03 12
Imaginea unui proces în memorie
Adrese logice
(în program)
http://duartes.org/gustavo/blog/post/anatomy-of-a-program-in-memory/
Curs 02 - 03 13
Adresarea memoriei
Curs 02 - 03 14
Adresarea memoriei
Curs 02 - 03 15
Demo
• Programul bc – conversii numerice (obase, ibase)
• https://github.com/systems-cs-pub-ro/iocla
• curs-03-x86/demo/ – gdb hello
Registrele EAX, AX, AH, AL
EFLAGS
EIP
Instrucțiunile MOV, ADD, JMP
Comenzile b main, r, n
set $eax = 0xffffffff
set $eip = main
Decomentați instrucțiunea jmp și reasamblați
• Atenție la ~/.gdbinit
Curs 02 - 03 16
Intrebări?
Curs 02 - 03 17
Instrucțiuni x86
De citit: Dandamudi
Capitole 4.5, 7, 8, 9, 10
Modificat: 3-Nov-21
Curs 06 - 07 1
Instrucțiuni aritmetice
INC și DEC
Format:
» inc destination
» dec destination
Semantică:
» destination = destination +/- 1
» destination poate fi pe 8, 16, sau 32-biți memorie/registru
» Nu putem folosi operanzi imediați
» Nu seteaza CF
• Exemple
inc BX ; BX = BX+1
dec word [value] ; value = value-1 (16 biți)
Curs 06 - 07 2
Instrucțiuni aritmetice
ADD/SUB
Format:
» add destination,source
» sub destination,source
Semantică:
» destination = (destination)+/-(source)
• Exemple
add EBX,EAX
add byte [value],10H
sub EBX, EAX
• Observatii:
inc EAX e mai bun decât add EAX,1
dec EAX e mai bun decât sub EAX,1
generează mai puțin cod
Curs 06 - 07 3
Setare indicatori de conditie
CMP
Format:
cmp destination,source
Semantică:
(destination)-(source)
Curs 06 - 07 4
Setare indicatori de conditie
• Unii indicatori pot fi setati in mod explicit prin
operatii specifice:
Carry
» STC (Set Carry Flag)
» CLC (Clear Carry Flag)
» CMP (Complement Carry Flag)
Interrupt
» STI (Set Interrupt Flag)
» CLI (Clear Interrupt Flag)
Direction
» STD (Set Direction Flag)
» CLD (Clear Direction Flag)
Curs 06 - 07 5
Instrucțiuni de salt (jump)
Salt necondiționat
Format:
jmp label
Semantică:
» Execuția transferată la instrucțiunea identificată de label
» Se retine deplasamentul relativ fata de intructiunea curenta
Curs 06 - 07 6
Instrucțiuni de salt (jump)
Salt condiționat
Format:
j<cond> label
Semantică:
» Execuția transferată la instrucțiunea referită de label doar
dacă condiția<cond>este îndeplinită
» Depinde de o combinație de flag-uri din EFLAGS
Curs 06 - 07 7
Instrucțiuni de salt (jump)
Salt condiționat
Acestea depind de valoarea unui flag din registrul EFLAGS
jz este echivalent cu je
Analog jnz și jne
Curs 06 - 07 8
Instrucțiuni de salt (jump)
Instructiuni ce tratează operanzii ca nr. fara semn.
je if equal (ZF==1)
jne if not equal (ZF==0)
ja if greater (CF==0 && ZF==0)
jae if greater or equal (CF==0)
jb if less (CF==1)
jbe if less or equal (CF==1||ZF==1)
Exemplu 2
mov ah, -1
add ah, 10
jo over ; no jump (-1+10)=9
js semn ; no jump 9 > 0
jc carry; jump 255+10 > 255
Curs 06 - 07 10
Salt indirect
• Se face salt la o adresă care nu este specificată
direct în corpul instrucțiunii
• Exemplu:
» Presupunând că ECX conține adresa targetului
jmp [ECX]
Notă: În cazul acesta, ECX trebuie să conțină adresa în
valoare absolută, nu relativă ca în cazul saltului direct.
Curs 06 - 07 11
Apel de procedură direct/indirect
Format:
CALL label
Semantică:
» Execuția transferată la instrucțiunea identificată de label
» Inainte de apel se salveaza adresa de retur pe
stiva
» Revenirea se face la apelul instructiunii RET care extrage adresa
de retur de pe stiva si executa salt la acea locatie
• Exemplu: EBX conține un pointer la o procedură
CALL Calculeaza
… ;aici se revine dupa call
Calculeaza:
… ;aici este corpul rutinei
RET ;aici se termina rutina si se
;revine in programul principal
Curs 06 - 07 12
Apel de procedură direct/indirect
Call
• apel direct: adresa imediată a procedurii apelate
• apel indirect: adresa procedurii apelate în registru
sau memorie
• Exemplu ASM:
dword la target_proc_ptr conține un pointer
call [target_proc_ptr]
• Exemplu C:
int inc(int x){ return x+1;}
int (*fa)(int);
fa = &inc;
printf("%d\n", (*fa)(2));
Curs 06 - 07 13
Instrucțiuni de ciclare
LOOP
Format:
loop target
Semantică:
» Decrementează ECX și face salt la target dacă ECX 0
» ECX trebuie inițializat cu numărul de repetări
• Exemplu (execută <loop body> de 50 de ori):
mov ECX,50
repeat:
<loop body>
loop repeat ...
• Exemplul anterior este echivalent cu:
mov ECX,50
repeat:
<loop body>
dec ECX
jnz repeat ...
Curs 06 - 07 14
Instrucțiuni de ciclare
• Următoarele două verifică, în plus, și indicatorul ZF
loope/loopz target
Action: ECX = ECX - 1
Jump to target if (ECX 0 and ZF = 1)
loopne/loopnz target
Action: ECX = ECX - 1
Jump to target if (ECX 0 and ZF = 0)
Curs 06 - 07 15
Instrucțiuni logice
AND/OR/XOR (Toate instr. logice actualizează EFLAGS)
and destination,source
Prin măști de biți, setează anumiți biți să fie 0
or destination,source
Prin măști de biți, setează anumiți biți să fie 1
Copiază anumiți biți dintr-un byte, cuvânt, dublu-cuvânt
xor destination,source
Comutare de biți
Inițializare registre la 0, de exemplu:
xor AX,AX
not destination
Complementul față de 2 al unui număr pe 8 biți, de exemplu:
not AL
inc AL
Curs 06 - 07 16
Instrucțiuni logice
TEST
test destination,source
Face AND non-destructiv
» Nu se reține rezultatul, nu se modifică destination
» Similar cu cmp
Exemplu: Verificarea parității unui număr reținut în AL
test AL,01H ; test the least significant bit
je even_number
odd_number:
<process odd number>
jmp skip1
even_number:
<process even number>
skip1:
Curs 06 - 07
. . .
17
Instrucțiuni de shiftare
• Două tipuri de shiftări
Logică
» shl (SHift Left)
» shr (SHift Right)
» Altă interpretare:
– Se aplică pe numere fără semn
Aritmetică
» sal (Shift Arithmetic Left)
» sar (Shift Arithmetic Right)
» Altă interpretare:
– Se aplică pe numere cu semn
Curs 06 - 07 18
Shiftare logică
Shift left
shl destination,count
shl destination,CL
Shift right
shr destination,count
shr destination,CL
Semantică: Shiftare stânga/dreapta a destination cu valoarea din count
sau registrul CL (nu modifica CL). destination poate fi pe 8, 16 sau 32
de biți; se poate afla în memorie sau într-un registru
Exemplu: prelucrare pe biți
; AL contains the byte to be encrypted
mov AH,AL
shl AL,4 ; move lower nibble to upper
shr AH,4 ; move upper nibble to lower
or AL,AH ; paste them together
; AL has the encrypted byte
Înmulțire și împărțire
» Puteri ale lui 2
» Mai eficient decât mul/div
Curs 06 - 07 19
Shiftare logică
• Ultimul bitul care iese în afară ajunge în CF
» biți de 0 sunt inserați la celălalt capăt
Curs 06 - 07 20
Shiftare logică
• Efect asupra indicatorilor:
Auxiliary flag (AF): undefined
Zero flag (ZF) și parity flag (PF) sunt actualizate
Carry flag
» Conține ultimul bit shiftat în afară
Overflow flag
» Pentru shiftări pe mai mulți biți
– Undefined
» Pentru shiftări cu un singur bit
– Se setează dacă în urma shiftării se schimbă semnul
– Altfel devine 0
Curs 06 - 07 21
Shiftare aritmetică
• Două variante, ca la cea logică:
sal/sar destination,count
sal/sar destination,CL
Curs 06 - 07 22
Instrucțiuni de rotire
• Problemă la shiftare
Biții shift-ați în afară sunt pierduți
Instrucțiunile de rotire îi inserează la loc
• Două tipuri
Fără Carry
» rol (ROtate Left)
» ror (ROtate Right)
Cu Carry
» rcl (Rotate through Carry Left)
» rcr (Rotate through Carry Right)
Formatul este similar cu cel al instrucțiunilor de shiftare
» Două variante (la fel ca la shiftare)
– Cu operand imediat
– Cu numărul de rotiri pasat prin CL
Curs 06 - 07 23
Rotire fără carry
Format:
rol destination,count
ror destination,count
count– analog shift, valoare imediată sau prin CL
Curs 06 - 07 24
Rotire cu carry
Format
rcl destination,count
rcr destination,count
count– analog shift, valoare imediată sau prin CL
Curs 06 - 07 25
Indicatori de stare
• Șase indicatori ne spun câte o proprietate a rezultatelor
instrucțiunilor aritmetice.
Curs 06 - 07 26
Indicatori de stare
• Sunt actualizați pentru a evidenția o proprietate a
rezultatelor
Exemplu: Dacă rezultatul este 0, se setează Zero Flag
Curs 06 - 07 27
Indicatori de stare
• Exemplu:
; initially, assume ZF = 0
mov EAX,55H ; ZF is still zero
sub EAX,55H ; result is 0
; ZF is set (ZF = 1)
push EBX ; ZF remains 1
mov EBX,EAX ; ZF remains 1
pop EDX ; ZF remains 1
mov ECX,0 ; ZF remains 1
inc ECX ; result is 1
; ZF is cleared (ZF=0)
Curs 06 - 07 28
Indicatori de stare
Cum utilizam flaguri-le ref. la operatii aritmetice?
• Studiu de caz: Carry Flag. Reține dacă în urma unei operații
aritmetice pe numere fără semn s-a produs depășire
CF e setat în următoarele exemple
mov AL,0FH mov AX,12AEH
add AL,0F1H sub AX,12AFH
Propagare ”împrumut” în adunarea pe mai multe cuvinte
1 carry from lower 32 bits
x = 3710 26A8 1257 9AE7H
y = 489B A321 FE60 4213H
7FAB C9CA 10B7 DCFAH
• Studiu de caz: Overflow flag. Analog CF, dar pentru numere
cu semn
Exemple (setează OF, dar nu și CF)
mov AL,72H ; 72H = 114D
add AL,0EH ; 0EH = 14D
Curs 06 - 07 29
Indicatori de stare
Curs 06 - 07 31
Instrucțiuni aritmetice
• Înmulțire
Mai complexă (costisitoare) ca add/sub
» Produce rezultate de lungime dublă
– E.g. Înmulțirea a două numere pe 8 biți produce un rezultat
ce are nevoie de 16 biți pentru reprezentare
» Nu putem folosi o singură instrucțiune de înmulțire atât pentru
numere cu semn cât și pentru cele fără semn
– add și sub funcționează grație reprezentării în
complement față de 2!
– Pentru înmulțire, avem nevoie de instrucțiuni separate
mul numere fără semn
imul numere cu semn
Curs 06 - 07 32
Instrucțiuni aritmetice
• Înmulțire fără semn
mul source
» Rezultatul și al doilea operand depind de dimensiunea
operandului source
Curs 06 - 07 33
Instrucțiuni aritmetice
Exemplu
mov AL,10
mov DL,25
mul DL
obținem250D în AX (rezultatulîncape înAL)
• Instrucțiunea imul folosește aceeași sintaxă
Exemplu
mov DL,0FFH ; DL = -1
mov AL,0BEH ; AL = -66
imul DL
Obținem 66D în AL
Curs 06 - 07 34
Instrucțiuni aritmetice
• Împărțirea produce două rezultate
– Câtul
– Restul
La înmulțire se evită situația de overflow cu registre duble
întrerupere software ce se declanșează atunci când se
produce overflow la împărțire (câtul nu încape)
• Sintaxa analogă cu înmulțirea
div source numere fără semn
idiv source numere cu semn
Curs 06 - 07 35
Instrucțiuni aritmetice
• Deîmpărțitul este de două ori mai lung ca împărțitorul
• Deîmpărțitul se consideră implicit reținut în:
AX (pentru împărțitor pe 8 biți) => AL, AH
DX:AX (pentru împărțitor pe 16 biți) => AX, DX
EDX:EAX (pentru împărțitor pe 32 biți) => EAX, EDX
Curs 06 - 07 36
Instrucțiuni aritmetice
• Exemplu
mov AX,251
mov CL,12
div CL
avem 20D în AL și 11D drept rest în AH
• Exemplu
sub DX,DX ; clear DX
mov AX,141BH ; DXAX = 5147D
mov CX,012CH ; CX = 300D
div CX
Avem 17D în AX și 47D rest în DX
Curs 06 - 07 37
Instrucțiuni aritmetice
• La împărțirea cu semn e nevoie de extensie de semn
» La numere fără semn, având un număr de 16 biți, făceam
completare cu la stânga cu 0-uri până la 32 de biți
» Nu mai funcționează în cazul numerelor cu semn
» Solutie: Trebuie făcută extensie la stânga a bitului de semn
• Instrucțiuni ajutătoare
» Două instrucțiuni mov
movsx dest,src (move sign-extended src to dest)
movzx dest,src (move zero-extended src to dest)
» În ambele cazuri, dest trebuie să fie un registru
» src poate fi registru sau locație de memorie
– Dacă src are 8 biți, dest trebuie să fie de 16 sau 32 de biți
– Dacă src are 16biți, dest trebuie să fie de 32 de biți
Curs 06 - 07 38
Structuri de decizie de nivel înalt
• Citiți secțiunea 8.5 din carte pentru a vedea cum se
implementează:
if-then-else
if-then-else with a relational operator
if-then-else with logical operators AND and OR
while loop
repeat-until loop
for loop
Curs 06 - 07 39
if-then-else
if (value1 > value2) mov AX, [value1]
bigger = value1; cmp AX, [value2]
else jle else_part
bigger = value2; then_part:
jmp end_if
else_part:
mov AX,value2
end_if:
mov [bigger], AX
. . .
Curs 06 - 07 40
if-then-else cu operatori logici
if (ch >= ’a’&& ch <= ’z’) cmp DL,’a’
ch = ch – 32; jb not_lower_case
cmp DL,’z’
ja not_lower_case
lower_case:
mov AL,DL
add AL,224
mov DL,AL
not_lower_case:
. . .
Curs 06 - 07 41
Bucle while, for
while(total < 700){ jmp while_cond
<loop body> while_body:
} < loop body >
. . .
while_cond:
cmp BX,700
jl while_body
end_while:
. . .
for(i = SIZE-1; i>= 0; i--) mov SI,SIZE-1
jmp for_cond
{
loop_body:
<loop body>
< loop body >
};
dec SI
for_cond:
or SI,SI
jge loop_body
. . .
Curs 06 - 07 42
SET condițional
SET{cond} reg8/mem8
• Condiție = testează biți din EFLAGS (z, ge, c, o, …)
• destinația trebuie să fie de 8biți
• dacă condiția este îndeplinită, se setează la 1
• dacă condiția NU este îndeplinită, se setează la 0
• EFLAGS nu este afectat
cmp edx,ecx
setge al
al = ((int)edx >= (int)ecx) ? 1 : 0
Curs 06 - 07 43
MOV condițional
CMOV{cond} dst, src
• Condiție = testează biți din EFLAGS (z, ge, c, o, …)
• destinația trebuie să fie un registru
• dacă condiția este îndeplinită, se execută MOV
• dacă condiția NU este îndeplinită, dst rămâne
neschimbat
• EFLAGS nu este afectat
Curs 06 - 07 44
MOV condițional
Curs 06 - 07 45
int adjust(int x){ adjust: adjust_nojump:
if(x > max){ enter 0,0 enter 0,0
max = x; mov edx, [ebp+8];x mov ecx, [max]
return 1; cmp edx, [max] mov eax, 0
} jg update_max cmp [ebp+8], ecx
return 0; mov eax, 0 cmovg ecx, [ebp+8]
} jmp ret_adj mov [max], ecx
update_max: setg al
mov [max], edx leave
mov eax, 1 ret
ret_adj:
leave
ret
Curs 06 - 07 46
MOV condițional
Avantaje performanță
• Mai bun pentru pipeline (fetch, decode, execute)
• Permite execuția secvențială pură
• Benchmarks https://github.com/xiadz/cmov
Limitări
• Doar pentru atribuiri simple – operatorul ?:
• nu poate înlocui secvența if..then..else - sunt
necesare salturi condiționale
• doar pentru registre, doar 16, 32, 64 biți
Curs 06 - 07 47
Directive, Instrucțiuni,
Adresare, Declarare
De citit:
Capitolele 4.1 -
4.4, 4.6 - 4.8, 6.1
Modificat: 3-Nov-21
- 6.3
Curs 07 1
Cuprins
• Sintaxa instrucțiunilor • Moduri de adresare
• Reguli sintactice • Declararea variabilelor
• Semnificatia entitatilor • Pseudo-operatori
unei linii de program • Macro-uri
Curs 07 2
Declarații
1. Directive
» Îi spun asamblorului ce să facă
» Ne-executabile
» Nu generează cod mașină
2. Instrucțiuni
» Îi spun CPU-ului ce să facă
» Operațiune + operanzi
3. Macrouri
» Notație scurtă pentru un grup de declarații
» Substituții cu parametri
Curs 07 3
Directive
• Directive care descriu structura programului
text, data, rodata, bss
Import/export nume
Curs 07 4
Variabile globale
• Trei zone de memorie
∗ .data: initializate
∗ .bss: neinitializate (zero @load-time)
.rodata: initializate, read-only
• .data: int a = 10;
• .bss: int a;
• .rodata: const int a = 10;
• Variabile locale declarate ‘static’ in C
Curs 07 5
Directiva GLOBAL
• Directiva GLOBAL marcheaza etichetele vizibile
global
» etichetele pot fi accesate si din alte module ale programului
• Formatul este
global label1, label2, . . .
• Aproape orice label poate fi declarat global
» Nume de proceduri
» Nume de variabile
» equated labels
∗ Intr-o constructie GLOBAL, nu este necesar sa mentionam
tipul labelului
Curs 07 6
Directiva EXTERN
• Directiva EXTERN ii spune asamblorului ca anumite
labeluri nu sunt definite in modulul curent
∗ Asamblorul rezerva spatiu in fisierul obiect pentru a fi
utilizat ulterior de linker
• Formatul este
extern label1, label2, . . .
unde label1 si label2 sunt declarate global
folosind directiva GLOBAL in alte module
Curs 07 7
Istrucțiuni
Curs 07 9
Sintaxa instrucțiunilor
• Registre interne:
Registre generale:
» (8 biti) AH,AL,BH,BL,CH,CL,DH,DL
» (16 biti) AX, BX,CX,DX, SI,,DI,SP, BP
» (32 biti) EAX, EBX,ECX,EDX, ESI,EDI,ESP, EBP
registrespeciale: CS,DS, SS, ES, FS,GS, GDTR, LDTR , CR0,..CR4,
PSW
• Date imediate (constante):
expresie aritmetico-logica evaluabila la un numar Valoarea este
conținută in codul instrucțiunii
Lungimea constantei – in acord cu lungimea celui de al doilea
operand (octet, cuvant sau dublu-cuvant)
ex: 0, -5, 1234h, 0ABCDh, 11001010b, 1b, 8* 4 – 3
Adresele variabilelor din .data, .bss sunt cunoscute = imediate
Curs 08 - 09 10
Sintaxa instrucțiunilor x86
Instrucțiuni fara operand
» NOP
» MOVSB
instrucțiuni cu un operand
» PUSH EAX
» ROR DX
instrucțiuni cu doi operanzi
» MOV AX, BX
linie cu eticheta instrucțiune si comentariu
» START: MOV AX,BX ;mută conținut AX in BX
linie de comentariu
» ; aceastaeste o linie de comentariu
linie cu eticheta
» ETICHETA:
Curs 07 11
Reguli sintactice
• o singură instrucțiune/directivă per linie
• o linie poate conține:
nici o entitate de instrucțiune (camp) – linie goală
Numai etichetă
Numai comentariu
eticheta, instrucțiune, directivă și comentariu
• Comentariu incepe cu ';' si se încheie la sfârșitul liniei
• o instrucțiune x86 poate conține maxim 2 operanzi:
op1 – destinația și primul termen al operației
op2 – sursa sau al doilea termen al operației
Curs 07 12
Reguli sintactice - Exemple
NOP
» Instrucțiune fara operanzi
MOVSB
» instrucțiune cu operanzi impliciti
MUL CL
» instrucțiune cu primul operand implicit (AX := AL * CL)
MOV AX, BX
» AX := BX adică AX – destinatia , BX sursa transferului
INC SI
» SI := SI + 1
ADD CX, DX
» CX := CX + DX
ADD AX, BX, CX
» Instrucțiune incorecta, prea multi operanzi
Curs 07 13
Reguli sintactice
• “case insensitive”
• Separarea câmpurilor se face cu spații, TAB-uri
• Pentru lizibilitate: separare coloane cu TAB:
eticheta: mnemonic operanzi ;comentariu
• Nume simbolice în loc de valori numerice
adrese de variabila =>nume_variabila;
adrese de instrucțiune =>eticheta;
valori de constante numerice=>nume_constanta
Curs 07 14
Reguli sintactice- simboluri
• Simboluri, identificatori, etichete:
secventa de litere, cifre si unele caractere speciale (ex: _, $, @),
?), care nu incepe cu o cifra
Lungimea simbolului este arbitrara, dar se considera primele 31
caractere
Exista simboluri rezervate, predefinite in limbaj (cuvinte cheie,
mnemonice, directive, nume registre)
exemple:
» L1 BletchRightHereRight_Here Item1 __Special
» $1234 @Home $_1 Dollar$ WhereAmI? @1234
erori:
» 1TooMany – incepe cu o cifra
» Hello.There – contine punct
» $ - $ sau ? nu poate sa apara singur
» LABEL – cuvant rezervat.
Curs 07 15
Reguli sintactice - constante
• Constante:
intregi: 12, 21d, 123h, 0fffh, 1011b
reale (virgulă mobila): 1.5, 1.0e10, 23.1e-12
Șir de caractere: "text", 'Text', 'TEXT''TEXT'
Constante simbolice:
» În asm: unu equ 1
» În C: #define unu 1
Curs 07 16
Reguli sintactice - operanzi
• Operanzii trebuie să aibă aceeași lungime
exceptii: operatii de inmultire si impartire)
• Cel mult un operand de tip locatie de memorie
Cum facem operații între două locatii de memorie?
Operatiile între registre – viteză mare
• Instrucțiunile sunt structural atomice
Sunt independente între ele
nu există forme de programare structurată
Structurarea programului: la nivel logic, prin directive
Curs 07 17
Sintaxa instrucțiunilor, macro-uri
Adresare
De citit:
capitolele4.1-
4.4, 4.6-4.8,
Modificat: 3-Nov-21
6.1-6.3
Curs 08 - 09 18
Cuprins
• Moduri de adresare • Pseudo-operatori
• Declarare date • Macro-uri
Curs 08 - 09 19
Moduri de adresare
Curs 08 - 09 20
Moduri de adresare
• Locații de memorie: indicate cu [ adresă ]
Operatorul [] semnifică dereferențierea
Lungimea variabilei:
» in acord cu al doilea operand (dacă exista)
» se indica in mod explicit ('byte', 'word', 'dword')
» Nu există tipuri
» Adresa este pentru un octet (0..4GB)
Adresa variabilei seg:offset
» adresa de segment:
– specificata in mod implicit – continutul registrului DS
– exprimata in mod explicit: <reg_segment>:<variabila>
– ex: CS: [Var1], ES: [100h]
» adresa de offset – adresa relativa in cadrul segmentului
Curs 08 - 09 21
Moduri de adresare
• adresa de offset
pe 32 biți (acest semestru)
exprimabilă in mai multe moduri:
» Imediat sau adresă cunoscută la momentul linkeditării
– MOV AX, [100h] ; se încarcă doi octeți de la adresa 0x100
– MOV AX, [v1] ; AL:=octetul de la v1, AH:=octetul de la v1+1
– MOV AX, [v1+1] ; AL:=octetul de la v1+1, AH:=octetul de la v1+2
– După linkeditare v1 și v1+1 au valori cunoscute ~ imediate
» Expresie evaluată la momentul execuției
– '[<reg_baza>] [+<reg_index>*scale] [<deplasament>']'
– MOV AX, [EBX+ECX*4+100h]
<reg_baza>:= EAX|EAX|ECX|EDX|ESI|EDI|EBP|ESP
<reg_index>:= EAX|EAX|ECX|EDX|ESI|EDI|EBP
scale := 1|2|4|8
Expresia produce adresa primului octet al unei variabile
Curs 08 - 09 22
Moduri de adresare
Adresarea imediata:
Operandul este o constanta
Operandul este continut in codul instrucțiunii
Operandul este citit o data cu instrucțiunea
Instrucțiunea poate lucra cu o singura valoare
Lungimea constantei este in acord cu celalalt operand
Curs 08 - 09 24
Moduri de adresare
• Adresarea directa cu deplasament:
Operandul este specificat printr-o adresa de memorie
Adresa operandului este continuta in codul instrucțiunii
Instrucțiunea poate lucra cu o singura locatie de memorie
(octet, cuvânt, sau dublu-cuvânt)
Necesita pasul data-fetch cu memoria =>timp mai mare
exemple:
MOV AL, [100h]
MOV EBX, var1
MOV CX, [1234h]
MOV var2, SI ; eroare
Curs 08 - 09 25
Moduri de adresare
• Moduri indirecte de adresare:
• Adresarea indirecta prin registru:
» Adresa operandului se specifica intr-un registru
» Registrele folosite pt. adresare: ESI, EDI, EBX, EBP
» Instrucțiunea contine adresa registrului
» mod flexibil de adresare
» exemple:
» MOV AL, [ESI]
» MOV [EBX], CX
Curs 08 - 09 26
Moduri de adresare
• Adresarea (indirecta) indexata:
Adresa operandului se exprima printr-o adresa de baza, data de
<deplasament>si un index dat de continutul unui registru
mod de adresare folosit pentru structuri de date de tip sir,
vector, tablou
sintaxa:
<nume_var>'['<reg_index>']' <reg_index>:=SI|DI
'['<reg_index>+<deplasament>']'
exemple:
MOV AX, [var + EBX]
MOV CX, [ESI+100H]
MOV [var + EDI], AL
MOV word [var + 10H], 1234H
Curs 08 - 09 27
Moduri de adresare
• Adresarea bazat indexata:
Adresa operandului se exprima printr-o adresa de baza, data de un
registru, un index dat de un registru si o adresa relativa data de
<deplasament>
Modul cel mai flexibil de adresare, dar necesita 2 adunari
sintaxa: <nume_var>'['<reg_baza>+<reg_index>']'
'['<reg_baza>+<reg_index>+<deplasament>']'
'['<reg_baza>']''['<reg_index>']''['<deplasament>']'
exemple:
MOV AX, [var+EBX+ESI]
MOV CX, [EBX+ESI+100H]
MOV [var + EBP+EDI], AL
MOV [var + EBP+ESI], 1234H
MOV [var + BP + DI], AL - eroare, necesită adresa pe 32biți
MOV [100h + EBP + ESI], 1234H
Curs 08 - 09 28
Moduri de adresare (32 biți)
• Adresarea indexata, scalata:
Permite multiplicarea registrului index cu un factor egal
cu lungimea unui element din sir:
» 1 pt. octet, 2 pt. cuvant, 4 pt. Dcuvant si 8 pt. qcuvant
Util pentru tablourilor cu elemente de 2/4/8 octeți
» '['<reg_index>*n']'
» '['<reg_index>*n + <deplasament> ']'
» '[' <reg_baza> + <reg_index>*n']'
» '[' <reg_baza> + <reg_index>*n + <deplasament> ']'
» MOV AX, [ESI*2]
» MOV DX, [EAX*4+12h]
» MOV CX, [100h + EBX + AX*1]; eroare dimensiune operanzi
Curs 08 - 09 29
• Moduri de adresare, observații
• nu există tipuri
• toate declarațiile (db, dw, dd, …) sunt pointeri!
numele este adresa primului octet al variabilei
folosim numele când e necesară adresa
folosim dereferențierea cu [ ] când e necesar conținutul
z dw 0x1234 short z = 0x1234;
; z = adresa octetului 0x34 // z este variabilă cu tip 16bit
; z nu are tip
p = &z;
mov ebx, z // p conține adresa lui z,
; ebx conține adresa // necesită 4 octeți
short a = z;
mov ax, [z] // se copiaza 2 octeți (tipul)
; ax conține 0x1234 // a conține 0x1234
; se cer explicit 2 octeți
; nu există tipuri
Curs 08 - 09 30
demo
• Se folosește un schelet simplu hello.asm (curs-02) cu
variabilele
v1 dd 0xabcd1234
v2 dd 0x7890aabb
Curs 08 - 09 31
demo
$ objdump –s ./hello.o ; adresele alocate
$ objdump –s ./hello ; adresele după link
$ objdump –M intel –d hello
Se observă codul generat pentru
• Instrucțiuni 1 & 2
• Diferența între 2 și 3
Rulare în gdb:
• Observare efect instrucțiuni
• Examinarea memoriei cu x/8xb &v1
Ce este v1?
• este un imediat (calculat la momentul linkeditării)
• este adresa primului octet al unei variabile (instr. 2)
• este un pointer (instr. 3)
• Operatorul [] indică un acces la memorie
Curs 08 - 09 32
Declararea variabilelor
• Scopul:
Utilizarea unor nume simbolice in locul unor adrese fizice
rezervarea de spatiu in memorie si initializarea variabilelor
pt. verificarea utilizarii corecte a variabilelor (verificare de tip)
• Modul de declarare: - prin directive
• Directiva (pseudo-instrucțiune):
entitate de program utilizata pentru controlul procesului de
compilare, editare de legaturi si lansarea programului
directivele NU SE EXECUTA; in programul executabil nu exista
cod aferent pentru directive
se folosesc pentru:
» Declararea variabilelor si a constantelor
» Declararea segmentelor si a procedurilor
» Controlul modului de compilare, editare de legaturi, etc.
Curs 08 - 09 33
Declararea variabilelor
• define byte:
<nume_var> DB ?|<valoare>
Curs 08 - 09 34
Declararea variabilelor
• define word :
<nume_var> DW ?|<valoare>
Curs 08 - 09 35
Declararea variabilelor
• define double word:
<nume_var> DD ?|<valoare>
Curs 08 - 09 36
Exemple de declaratii de variabile simple
• m db ? erori
• I db 6 l db 260
• j db -7 al dw 23
• l db 255 tt db -130
• k db -23
• bits db 10101111b
• car db 'A'
• Cuv dw 1234h
• Var dw 0FFFFh
• Dcuv dw 12345678h
Curs 08 - 09 37
Declararea variabilelor
Variabile simple lungi:
dq (define QWORD/quad-word)
» variabilape 8 octeti; folosit pentru pastrarea intregilor f. mari sau
a valorilor in flotant (dubla precizie)
dt (define TBYTE/ten-bytes)
» Variabila pe 10 octeti; format folosit pt. coprocesorul matematic;
se reprezinta 10 cifre BCD (despachetat) sau nr. flotant pe 80 biti
Curs 08 - 09 38
Declararea variabilelor
Exemple comentate:
Curs 08 - 09 39
Declararea constantelor
• Scop: - nume simbolic dat unei valori des utilizate
• Sintaxa:
<nume_constanta>equ|= <expresie>
• Semnificatia:
la compilare<numeconstanta> se inlocuieste cu
<expresie> ; este o constructie de tip MACRO
sintaxa se verificadoar la inlocuire
<expresie>este o expresiea ritmetico-logica evaluabila in
momentul compilarii =>termenii sunt constante sau
operatorul '$'
'$' – reprezinta valoarea contorului curent de adrese
Curs 08 - 09 40
Declararea constantelor
• Exemple:
trei equ 3
true equ 0
Curs 08 - 09 41
Repetarea declaratiilor sau a instrucțiunilor
• TIMES
Este un prefix ce produce repetarea de un numar
specificat de ori a instrucțiunii sau a declaratiei de
date
• Exemple:
Alocare 64 octeti:
zerobuf: times 64 db 0
Initializare si alocare pana la 64 octeti:
buffer: db ’hello, world’
times 64 − $ + buffer db ’ ’
Executie multipla a unei instrucțiuni (loop unrolling
trivial)
times 100 movsb
Curs 08 - 09 42
Pseodo-operatori
• Expresii aritmetico-logice
trebuie sa se evalueze in procesul de compilare
contin constante si variabile de compilare
• $ - contorul de alocare la linia curentă
buffer: db ’hello, world’
len equ $ - buffer
Echivalent cu
buffer: db ’hello, world’
endbuf:
len equ endbuf - buffer
Curs 08 - 09 43
Pseudo-operatori
• Operatori logici, la fel ca in C.
• In ordinea cresterii prioritatilor:
• Operatori pe biți
|, ^ , AND
• Operatori shiftare de biți
<<, >>
• Operatori binari:
+, -
*, /, // (signed), %, %% (signed)
• Operatori unari:
+, −, ~, !, SEG (obtine segmentul unui simbol)
Curs 08 - 09 44
Forțare de tip (coercion)
• <tip>poate fi: Exemplu
BYTE (1 octet) mov dword [z], -1
;0x5655902a <z>: 0xff 0xff 0xff 0xff
WORD (2 octeți) add byte [z], 1
DWORD (4 octeți) ;0x5655902a <z>: 0x00 0xff 0xff 0xff + ZF CF PF AF
Curs 08 - 09 47
Macro-uri vs Proceduri
• Macro-uri: • Proceduri:
la fiecare apel se copiaza o singura copie pt. mai
secventa de instrucțiuni multe apeluri
nu sunt necesare se folosesc instrucțiuni
instrucțiuni de apel de apel si de revenire
(CALL) si de revenire din se utilizeaza stiva la apel
rutina (RET) si la revenire
nu se foloseste stiva transferul de parametri
transferul de parametri se face prin registri sau
se realizeaza prin stiva
copierea numelui
Curs 08 - 09 48
Avantajele si dezavantajele macro-uri
• Avantaje:
pot fi create “instrucțiuni” noi
poate duce la o programare mai eficienta
executie mai eficienta in comparatie cu apelurile de
proceduri
• Dezavantaje:
pot ascunde operatii care afecteaza continutul registrilor
utilizarea extensiva a macrourilor ingreuneaza intelegerea
si mentenanta programului
Curs 08 - 09 49
Intrebari?
Curs 08 - 09 50
Stiva
De citit [Danadamudi]:
Capitole 5.1-5.4
Modificat: 13-Dec-21
Curs 09 1
Cuprins
• Ce este stiva?
• Implementarea stivei
pentru x86(Pentium)
• Instrucțiuni de lucru
• Utilizările stivei
Curs 09 2
Ce este stiva?
• Stiva este o coadă last-in-first-out (LIFO)
• Daca vizualizăm stiva ca un vector de elemente,
atunci inserția și ștergerea sunt restricționate la unul
din capetele vectorului
• Numai elementul din vârful stivei (en. top-of-stack
a.k.a TOS ) este direct accesibil
• Structura implementează două operații de baza:
∗ push (inserție)
∗ pop (stergere)
Curs 09 3
Ce este stiva? (cont’d)
• Exemplu
∗ Inserarea elementelor in stivă
» Săgeata pointează către vârful stivei
Curs 09 4
Ce este stiva? (cont’d)
• Exemplu
∗ Ștergerea elementelor din stivă
» Săgeata pointează către vârful stivei
Curs 09 5
Implementarea stivei pentru x86
• La x86 este utilizat un registru segment rezervat:
∗ Registrul SS (Stack Segment) indică adresa de start a
segmentului, iar registrul ESP (Extended Stack Segment)
indica deplasamentul față de adresa start a vârfului stivei
∗ Impreuna SS:ESP indică vârful stivei
• Caracteristicile implementării pentru x86:
1. Date de tip word/16-bit sau doubleword/32-bit
2. Stiva crește spre adrese mai mici “in jos”
3. TOS pointează către ultimul element introdus in stivă
Curs 09 6
Harta memoriei pentru un proces in Linux
Curs 09 7
Instrucțiuni de lucru cu stiva
• x86 perimite doua instrucțiuni de bază:
push sursa
pop destinatie
• Sursa și destinatia pot fi
∗ registre de uz general 16- sau 32-bit (ex: ax sau eax)
∗ resistru de segment (ex: DS, SS, CS, etc...)
∗ un word sau double word din memorie (ex: word [var+2])
• source în plus poate fi și o data imediata pentru
instrucțiunea push de lungime 8, 16, sau 32 bit
∗push 0xAB
Curs 09 8
Exemplu de lucru cu stiva pentru x86 - 1
D68C
D68A
D686
Curs 09 9
Instructiuni de lucru cu stiva: Exemple
• Pentru o stivă goală următoarea secvență de
instrucțiuni push
push word 21ABH
push 7FBD329AH
rezultă în starea prezentata la (c) în figura anterioara
• Dupa execuția instrucțiunii:
pop EBX
Rezultă în starea stivei de la (b) din figura următoare, iar EBX
va conține valoarea 7FBD329AH
Curs 09 10
Exemplu de lucru cu stiva pentru x86
D68A
D688
D686
Curs 09 11
Demo
z dd 0x1020304
; starea stivei
0xffffd2ec f7de4b41 EBP+4
0xffffd2e8 ffffd2ec EBP+0 <-- ESP
0xffffd2e4 f7fa4000 EBP-4
Curs 09 12
Instrucțiuni adiționale
Operații de stiva asupra fanioanelor
• Instrucțiunile push si pop nu pot fi utilizate cu
registrul de stare (EFLAGS)
• Doua instructiuni speciale in acest sens sunt:
pushfd (push 32-bit flags)
popfd (pop 32-bit flags)
• Operanzii nu sunt necesari
• Se folosesc pushfw and popfw pentru 16-bit
(FLAGS)
Curs 09 13
Instructiuni aditionale
Operatii de stiva asupra la toti registrii de uz general
• Instrucțiunile pushad si popad sunt folosite pentru a salva
si a restaura 8 registre de uz general
EAX, ECX, EDX, EBX, ESP, EBP, ESI, and EDI
• pushad executa o operație de push pentru fiecare din
registrii anteriori în ordinea data (EAX primul și EDI ultimul)
• popad restaureaza toti registrii exceptand registrul ESP
• Se folosesc pushaw si popaw pentru a executa aceeași
operație pentru registre la nivel de 16-bit (AX primul și DI
ultimul)
Curs 09 14
Utilizările stivei
• Trei utilizari de baza:
1. Stocarea datelor temporare
2. Transferarea controlului
3. Transmiterea parametrilor
Curs 09 15
Utilizarea stivei (cont’d)
• Des utilizata pentru eliberarea unor registre
;salveaza EAX & EBX pe stiva
push EAX
push EBX
;EAX si EBX pot fi acum folositi
mov EAX,value1
mov EBX,value2
mov value1,EBX
mov value2,EAX
;restaureaza EAX & EBX din stiva
pop EBX
pop EAX
. . .
Curs 09 16
Utilizarile stivei (cont’d)
2. Transferarea Controlului
• Pentru proceduri și întreruperi adresa de retur este
salvata pe stiva
• Discuția pentru apelul procedurilor va clarifica în
detaliu acesta utilizare
3. Transmiterea Parametrilor
• Stiva este extensiv utilizata pentru transmiterea
parametrilor către proceduri
• Discuția de mai târziu va arata cum se realizează
acest proces
Curs 09 17
Funcții
De citit [Dandamudi]:
Capitole 5.5, 16
Modificat: 13-Dec-21
Curs 10 - 11 1
Proceduri
• Doua tipuri
∗ Apelul-prin-valoare
» Primește numai valori
» Similar functiilor matematice
∗ Apelul-prin-referință
» Primește pointeri
» Manipulează direct zona de memorie a parametrilor
Curs 10 - 11 2
Instrucțiuni de lucru cu Procedurile
• x86 dispune de doua instructiuni: call si ret
• Instrucțiunea call este utilizata pentru a apela o
procedura, iar formatul acesteia este:
call proc-name
nexti: …
proc-name - numele procedurii (adresa acesteia)
nexti - adresa instructiunii urmatoare
• Acțiunile realizate la apelul unei proceduri:
push nexti ; push return address
jmp proc-name ; EIP of the procedure
Curs 10 - 11 3
Instrucțiuni de lucru cu Procedurile (cont’d)
• Instrucțiunea ret este utilizata pentru a transfera
controlul către procedura apelanta
• De unde stie procesorul unde sa se intoarca?
∗ Foloseste adresa de retur salvata pe stiva la executia
instructiunii call
∗ Este important ca TOS sa arate către acesta adresa în
momentul execuției instrucțiunii ret
• Actiunile realizate la executia lui ret sunt:
add ESP, 4 ; pop return address
jmp [ESP-4] ; from the stack
Curs 10 - 11 4
Instrucțiuni de lucru cu proceduri
• Putem specifica un intreg optional instructiunii ret
∗ Formatul acesteia este
ret optional_uint
∗ Exemplu:
ret 8
• Acțiunile realizate in acest caz sunt :
add ESP, 4 + optional_uint
jmp [ESP – 4 - optional_uint ]
Curs 10 - 11 5
Cum este transferat controlul in program?
Offset machine code main:
00000002 E816000000 call sum
00000007 9C3 mov EBX,EAX
. . . .
1D-07 = 16 ; end of main procedure
sum:
0000001D 55 push EBP
. . .
ret
; end of sum procedure
2D-1D=10 avg:
. . . .
00000028 E8F0FFFFFF call sum
0000002D 89D8 mov EAX,EBX
. . . .
; end of avg procedure
Curs 10 - 11 6
Transmiterea parametrilor
• Transmiterea parametrilor este diferita fata de
limbajele de nivel înalt (C / C++ / Java)
• In limbaj de asamblare
» Toți parametrii necesari trebuie dispuși într-o zona de stocare
care poate fi accesata mutual de apelant și apelat (caller vs
callee)
» Apoi se apeleaza procedura (a.k.a. call proc_name)
• Tipuri zone de stocare
» Registre (se utilizeaza registrii de uz general)
» Memorie (este folosita stiva)
• Doua metode de transmitere a parametrilor:
» Metoda prin registre
» Metoda care utilizeaza stiva
Curs 10 - 11 7
Transmiterea parametrilor prin registre
• Procedura apelantă plasează toți parametrii
necesari în registre de uz general înainte de a realiza
apelul propriu-zis prin instrucțiunea call
• Exemple:
∗ Demo: PROCEX1.ASM
» apelul-prin-valoare utilizand metoda registrelor
» o procedura care realizeaza o suma simpla
∗ Demo: PROCEX2.ASM
» apelul-prin-referenta folosind metoda registrelor
» procedura pentru calculul lungimii unei string
Curs 10 - 11 8
pro și contra pentru metoda registrelor
• Avantaje:
∗ Simplu si convenabil
∗ Mai rapid
• Dezavantaje:
∗ Numai un număr limitat de parametri poate fi transferat
prin registre
– Un număr foarte mic de registre este accesibil
∗ Cel mai adesea registrele nu sunt libere
– eliberarea acestora prin salvarea lor pe stiva neaga al doilea
avantaj al metodei
Curs 10 - 11 9
Transmiterea parametrilor prin stivă
• Toate valorile sunt puse pe stiva înainte de a apel
• Example:
Curs 10 - 11 10
Accesarea parametrilor de pe stivă
• Valorile parametrilor se găsesc pe stiva
• Putem folosi următoarea instrucțiune pentru a
accesa valoarea parametrului number2
mov BX, [ESP+4]
Atenție:
» ESP se schimbă cu operațiile push/pop
»A se evita indexarea dupa ESP
Curs 10 - 11 11
Folosirea lui EBP pentru acces la parametri
• Abordarea preferată pentru a accesa parametrii:
mov EBP, ESP
mov AX, [EBP+4]
pentru a accesa number2 din exemplul anterior
• Problema: Continutul lui EBP este pierdut!
∗ Trebuie salvat conținutul lui EBP... pe stivă
push EBP
mov EBP, ESP
Curs 10 - 11 12
Eliberarea stivei de parametri
Curs 10 - 11 13
Eliberarea stivei de parametri (cont’d)
• Două moduri pentru eliberarea stivei de parametri:
1. Folosirea intregului optional pentru instructiunea ret
ret 4
pentru exemplul anterior (2 parametri de 16biți)
Curs 10 - 11 14
Probleme de întreținere a stivei
• Cine ar trebui sa curețe stiva de parametri?
Curs 10 - 11 15
Probleme de întreținere a stivei
Curs 10 - 11 16
Probleme de întreținere a stivei
Curs 10 - 11 17
Probleme de întreținere a stivei
Curs 10 - 11 18
Probleme de întretinere a stivei
Curs 10 - 11 19
Variabile locale
• au natură dinamică
∗ intra în existenta la invocarea unei proceduri și se distrug
odată cu terminarea execuției acesteia
• nu pot fi în segmentul de date (.data) :
» Alocarea spațiului este statica (rămâne persistent intre apelurile
unei proceduri)
» Nu funcționează cu proceduri recursive
• variabilele locale sunt pe stivă
Curs 10 - 11 20
Instrucțiuni pentru cadrul de stivă
• Instrucțiunea ENTER
∗ Facilitează alocarea unui cadru de stivă
enter bytes,level
bytes = spatiu local de stocare
level = nivelul de intercalare (folosim nivelul 0)
∗ Exemplu
enter XX,0
este echivalent cu
push EBP
mov EBP,ESP
sub ESP,XX
Curs 10 - 11 21
Instrucțiuni pentru cadrul de stivă
• Instructiunea LEAVE
∗ Dealoca un cadru de stiva
leave
» Nu are operanzi
» Echivalenta cu
mov ESP,EBP
pop EBP
Curs 10 - 11 22
Schita unei proceduri tipice
proc-name:
enter XX,0
. . . . . .
<procedure body>
. . . . . .
leave
ret YY
Curs 10 - 11 23
Transmiterea parametrilor prin stiva - demo
• PROCEX3.ASM
∗ apelul prin valoare folosind stiva
∗ o procedura pentru calculul sumei
• PROCSWAP.ASM
∗ apelul prin referința folosind stiva
∗ primele doua caractere ale string-ului de input sunt inter-
schimate
• BBLSORT.ASM
∗ Implementează algoritmul de sortare prin metoda bulelor
∗ utilizeaza pusha si popa
Curs 10 - 11 24
Număr variabil de parametri
• Cele mai multe proceduri au număr fix de parametri
∗ La fiecare apel același număr de parametri este transmis
Curs 10 - 11 25
Număr variabil de parametri
∗ Numărul de parametri
trebuie sa fie unul din
parametri transmiși
Curs 10 - 11 26
Stack frame = activation record = cadru de stivă
void f(int b, int a){
int temp=1, N;
…
return;
}
...
call f
add ESP, 8
...
f:
enter 8, 0
mov [EBP-4],1
…
leave
ret
Curs 10 - 11 27
Activation record
• Datele de pe stivă despre procedura curentă
» parametri
» adresa de retur cadru de stivă
» vechiul EBP
» registre salvate == frame stack
» variabile locale == activation record
• Fiecare apel de funcție necesită aceste informații
• EBP este denumit base pointer
∗ EBP cunoscut => acces la toate datele din stack frame
∗ Lista înlănțuită de stack frame-uri
∗ [EBP] = EBP din funcția apelantă
Curs 10 - 11 28
Variabile locale – exemple
• curs11/procfib1.asm
∗ In cazul procedurilor simple, registrele pot fi folosite
pentru stocarea variabilelor locale
∗ Utilizarea registrelor pentru stocarea variabilelor locale
∗ Afisarea celui mai mare numar Fibonacci mai mic decat un
numar dat ca input
• curs11/procfib2.asm
∗ Parametru în EDX, rezultat în EAX
∗ stiva pentru stocarea variabilelor locale
∗ Aspecte legate de performanta utilizarii registrelor vs
stiva vor fi discutate ulterior
Curs 10 - 11 29
Performanță în apeluri de funcții
Stiva versus Registre curs11/bblsort.asm
• Fara procedura swap (Program 5.5, lines 95-99)
swap:
mov [ESI+4],EAX
mov [ESI],EBX
mov EDX,UNSORTED
• Procedura SWAP (inlocuieste codul de mai sus)
swap_proc:
mov [ESI+4],EAX
mov [ESI],EBX
mov EDX,UNSORTED
ret
Curs 10 - 11 30
Performanță în apeluri de funcții
Cu procedura swap
Curs 10 - 11 31
Performanta: Overhead variabile locale
Curs 10 - 11 32
Recursivitate
Chapter 16
S. Dandamudi
Curs 10 - 11 33
Introducere
• funcție recursivă = care se apelează pe sine însăși
∗ Direct, sau indirect
• aplicații exprimate natural prin recursivitate
factorial(0) = 1
factorial (n) = n * factorial(n−1) for n > 0
Fibonacci, Ackerman, etc
• Din punct de vedere al implementarii
Similar cu orice alt apel de functie
La fiecare apel se creează un stack frame
Curs 10 - 11 34
Introducere (cont’d)
Curs 10 - 11 35
Recursivitate
• Doua exemple
∗ Factorial curs-11/fact_pentium.asm
∗ Quicksort curs-11/qsort_pentium.asm
Exemplu 1
∗ Factorial
factorial(0) = 1
factorial (n) = n * factorial(n−1) for n > 0
• Activation record
∗ Consta doar în stocarea adresei de retur pe stivă cu
ajutorul instructiunii call
∗ Parametru în BL
Curs 10 - 11 36
Recursivitate
Exemplu 2
• Quicksort
∗ Sortarea unui vector de N elemente
∗ Algoritm
» Selectam un element pivot x
» Presupunem ca ultima aparitie a lui x este array[i]
» Mutam toate elementele mai mici decat x pe pozitiile
array[0]…array[i−1]
» Mutam toate elementele mai mari decat x pe pozitiile
array[i+1]…array[N−1]
» Aplicam quicksort recursiv pentru a sorta cele doua subliste
Curs 10 - 11 37
Recursiv vs Iterativ
• Recursiv
∗ Concis
∗ Mentenanta mai usoara a programului
∗ Alegerea naturala pentru unele probleme
• Posibile probleme
∗ Ineficient
» Apelurile recursive produc overhead
» Calcule duplicate
∗ Necesita mai multa memorie
∗ Cadre de stivă
Curs 10 - 11 38
Recursivitatea la coadă
•Tail recursion
•Numai când ultima instrucțiune este apelul recursiv
•se poate optimiza apelul recursiv ca un jmp
•nu se mai creează o activare pe stivă
•Exemplu chap-07/03-recursive-tail
•make && make asm
•Examinare fact.s și fib.s
•https://gcc.godbolt.org/
Cu opțiunile -O1 -O2 -m32 -march=native se examinează
codul generat pentru recursivitate
Curs 10 - 11 39