Sunteți pe pagina 1din 170

Arhitectura x86

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)

• Unele registre au utilizări speciale


 ECX este numărator pentru instrucțiunea loop

Curs 02 - 03 5
x86 registre pe 32 biți

• Două registre index


 16 sau 32 biți
 Instrucțiuni pe stringuri
 source (SI); destination
(DI)
 Pot fi folosite în scop
general

• Două registre pointer


 16 sau 32-biți
 Exclusiv pentru stivă

Curs 02 - 03 Chapter 3: Page 6 6


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)

• DF (Direction Flag) – este utilizat de instrucțiunile pe şiruri şi


specifică direcția de parcurgere a acestora:
 0 – şirurile se parcurg de la adrese mici spre adrese mari;
 1 – şirurile sunt parcurse invers.
• IF (Interrupt Flag) – acest indicator controlează acceptarea
semnalelor de întrerupere externă. Dacă IF = 1 este activat sistemul
de întreruperi, adică sunt acceptate semnale de întrerupere
externă (mascabile, pe linia INTR); altfel, acestea sunt ignorate.
Indicatorul nu are influență asupra semnalului de întrerupere
nemascabilă – NMI.
• TF (Trace Flag) – este utilizat pentru controlul execuției
instrucțiunilor în regim pas cu pas (instrucțiune cu instrucțiune), în
scopul depanării programelor. Dacă indicatorul este 1, după
execuția fiecărei instrucțiuni se va genera un semnal de
întrerupere intern (pe nivelul 1). Evident, execuția secvenței de
tratare a acestei întreruperi se va face cu indicatorul TF = 0.

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

Nu le folosim acest semestru :-)

Curs 02 - 03 Chapter 3: Page 11


Adrese logice și fizice

• Segmentarea&paginarea = translatare adrese 32 biți


• Segmentarea: adrese logice → adrese lineare
• Paginarea: adrese lineare → adrese fizice
• Segmentare, paginare → cursurile SO, SO2

(cea din program)

IHS, PC, SD, SO, SO2 CN1, CN2, PM


Restul facultății

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

calculul adresei logice

Registru Registru de Registru


segment :[ baza + +
index
] ]
Deplasament ]

Adresa de segment Adresa de offset

Curs 02 - 03 14
Adresarea memoriei

mov eax, [mybuffer + ebx + esi*4 + 9]


; ebx = bază
; esi = index
; mybuffer + 9 = deplasament

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)

 destination și source NU sunt alterate


 Testează relația de ordine între operanzi
 Se efectuează scăderea, se setează EFLAGS
 Nu se reține rezultatul scăderii
 Se folosește cu salturi condiționale
• Exemple
cmp EBX, EAX
cmp dword [count], 10

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

• Exemplu: ciclu infinit


mov EAX,1
inc_again:
inc EAX
jmp inc_again
mov EBX,EAX ; nu se ajunge aici

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

• Exemplu: Verificare \r (Carriage Return)


GetCh
AL
cmp AL,0DH ; 0DH = ASCII carriage return
je CR_received
inc CL
...
CR_received:

Curs 06 - 07 7
Instrucțiuni de salt (jump)
Salt condiționat
 Acestea depind de valoarea unui flag din registrul EFLAGS

jz jump if zero (ZF == 1)


jnz jump if not zero (ZF == 0)
jc jump if carry (CF == 1)
jnc jump if not carry (CF == 0)
jo jump if overflow (OF == 1)
js jump if sign (SF == 1)
jp jump if parity (PF == 1)

 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)

Instructiuni ce tratează operanzii ca nr. cu semn.


je if equal (ZF==1)
jne if not equal (ZF==0)
jg if greater (ZF==0 && SF==OF)
jl if less (SF != OF)
jge if greater or equal (SF==OF)
jle if less or equal (ZF==1||SF!=OF)
Curs 06 - 07 9
Instrucțiuni de salt (exemple)
 Exemplu 1
mov ah, 1
cmp ah, -1
ja fara ; no jump 1 < 255
jg cu ; jump 1 > -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

• Se poate specifica un target printr-o adresă de


memorie sau un registru

• 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

• Îndată ce un flag este setat, rămâne setat până când


o altă instrucțiune îi modifică starea

• Instrucțiunile afectează în mod diferit indicatorii


 add și sub le pot schimba pe toate șase
 inc și dec le pot schimba pe toate mai puțin CF
 mov, push, și pop nu afectează nici un indicator

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

• Cu/fără semn: de unde știe sistemul?


 Procesorul nu știe interpretarea
 El setează indicatorii carry și overflow pentru ambele
interpretarefărăsemn interpretare cu semn
mov AL,72H mov AL,72H
add AL,0EH add AL,0EH
jc depasire jo depasire
nu_depasire: nu_depasire:
.... ....
depasire: depasire:
.... ....

Curs 06 - 07 Chapter 7: Page 30


Instrucțiuni aritmetice
• Pentium are o serie de instrucțiuni ce pot lucra la
nivel de 8, 16 sau 32 de biți
» Adunare: add, adc, inc
» Scădere: sub, sbb, dec, neg, cmp
» Înmulțire: mul, imul
» Împărțire: div, idiv
» Instrucțiuni ce se folosesc în conjuncție cu cele de mai sus: cbw,
cwd, cdq, cwde, movsx, movzx

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

Excepție dacă câtul


nu încape în AL

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

• CMOVNE, CMOVBE, CMOVA, CMOVG, ...

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

• Reminder(curs 2): structura procesului

• Va urma(curs 6): structura binarului

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

[eticheta:] mnemonic [operanzi] [;comentariu]

• eticheta – șir de litere si cifre, care începe cu o literă


• mnemonic – nume care simbolizează o instrucțiune
 nop
 jz begin
 add eax, 1
begin:
 mov [buffer + ebx], ax
• operanzi – registru | locație memorie| imediat
 0 – 2 operanzi
Curs 07 8
Sintaxa instrucțiunilor
• registru := EAX|EBX|AX|BX|AL|BL|..|ESI|..|EBP|ESP
• imediat:= număr sau expresie evaluată de asamblor
 Adresa unei variabile este un imediat
• locație:= [expresie care produce o adresă logică]
 Între paranteze drepte [expresie]
 [variabilă + reg_index + reg_bază + deplasament]
 deplasament = imediat
• mov [ceva + esi + ebx*4 + 9], ax
• Locație = adresa variabilei ceva
• Locație += 9; ceva + 9 este cunoscut la momentul asamblării
• Locație += (ESI + EBX << 2)
• La adresa indicată de Locație se stochează 16 biți din AX

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

 MOV AL, 12h


 MOV AL, 120
 MOV AX, 12ABh
 MOV AL, 260 – warning, ajunge 4 în AH
 MOV EAX, ceva ; adresa lui ceva este cunoscută
Curs 08 - 09 23
Moduri de adresare
• Adresarea de tip registru:
 Operandul este continut intr-un registru
 timp de acces mic; nu necesita transfer pe magistrala
 Instrucțiune scurta (nu specifică operand)
 Numar limitat de registre interne => nu toate variabilele
pot fi pastrate in registre
 Exista limitari in privinta registrelor speciale (ex: segment)
 MOV EAX, EBX
 MOV DS,AX
 MOV BX, AL – eronat
 MOV DS, 1234H - eronat

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

Se adaugă instrucțiuni care exemplifică adresarea


1. mov ebx, 0x56559026
2. mov ebx, v1
3. mov ebx, [v1]
4. mov eax, v2
5. mov bx, [eax]

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>

– se rezerva o locatie de memorie de 1 octet;


– Locatia este initializata cu <valoare>, sau este neinitializata
daca apare '?'
– <nume_var> - eticheta ce simbolizeaza adresa variabilei
– <valoare> - valoare in intervalul [0..255] sau [-128..127]
– Poate pastra: un numar intreg fara semn, un numar intreg cu
semn, un cod ASCII, 2 cifre BCD

Curs 08 - 09 34
Declararea variabilelor
• define word :

<nume_var> DW ?|<valoare>

– se rezerva o locatie de memorie de 2 octeti;


– Locatia este initializata cu <valoare>, sau neinitializata '?'
– <nume_var> - eticheta ce simbolizeaza adresa variabilei
– <valoare> - valoare in intervalul [0..2^16-1] sau [- 2^15.. 2^15-1]
– Poate pastra: un numar intreg fara semn, un numar intreg cu
semn, 2 coduri ASCII, 4 cifre BCD

Curs 08 - 09 35
Declararea variabilelor
• define double word:

<nume_var> DD ?|<valoare>

– se rezerva o locatie de memorie de 4 octeti (int în C);


– Locatia este initializata cu <valoare>, sau neinitializata '?'
– <nume_var> - eticheta ce simbolizeaza adresa variabilei
– <valoare> - valoare numerica in intervalul [0..2^32-1] sau [-
2^31.. 2^31-1]
– poatepastra: un numar intreg fara semn, un numar intreg cu
semn, 4 coduri ASCII, 8 cifre BCD,

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:

db 0x55 ; just the byte 0x55


db 0x55,0x56,0x57 ; three bytes in succession
db 'a',0x55 ; character constants are OK
db 'hello',13,10,'$' ; so are string constants
dw 0x1234 ; 0x34 0x12
dw 'a' ; 0x61 0x00 (it's just a number)
dw 'ab' ; 0x61 0x62 (character constant)
dw 'abc' ; 0x61 0x62 0x63 0x00 (string)
dd 0x12345678 ; 0x78 0x56 0x34 0x12
dd 1.234567e20 ; floating-point constant
dq 0x123456789abcdef0 ; eight byte constant
dq 1.234567e20 ; double-precision float
dt 1.234567e20 ; extended-precision float

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

 text db 'acesta este un text'


 lung_text equ $-text

 Adr_port equ 378h

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

QWORD (8 octeți) mov dword [z], -1


;0x5655902a <z>: 0xff 0xff 0xff 0xff
TBYTE (10 octeți) add word [z], 1
;0x5655902a <z>: 0x00 0x00 0xff 0xff + ZF CF PF AF
mov dword [z], -1
;0x5655902a <z>: 0xff 0xff 0xff 0xff
add dword [z], 1
;0x5655902a <z>: 0x00 0x00 0x00 0x00 + ZF CF PF AF

 Care este diferența față de cast în C?


Curs 08 - 09 45
Macro-uri
• forme prescurtate de scriere a unor secvențe de
program care se repeta
• sintaxa:
%macro macro_name[para_count]
<macro body>
%endmacro
• Exemplu definire:
%macro multEAX_by_16
sal EAX,4
%endmacro
• Exemplu utilizare:
...
mov EAX,27
multEAX_by_16
...
Curs 08 - 09 46
Macro-uri cu parametri
• <para_count>specifica numarul de parametri
• <%n>identifica al n-lea parametru
• Exemplu definire:
%macro mult_by_16 1
sal %1,4
%endmacro
• Exemplu utilizare:
mult_by_16 DL
• macro-ul se expandeaza la:
sal DL,4

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

push dword [z]


; în gdb x/4ub $esp răspunde 0xffffd2e4: 4 3 2 1
; esp pointează la octetul LSB al ultimului element
; inserat
mov ebx, [esp]
pop eax
; ebx și eax conțin 0x1020304
mov esi, 0x0a0b0c0d
mov [esp-4], esi ; esp-4 pointează la primul spațiu liber
sub esp, 4 ; echivalent cu push esi
pop edi
; edi = esi
; stiva are aceeași stare ca la început
; sub esp e spațiu liber

0xffffd2ec f7de4b41 EBP+4


0xffffd2e8 ffffd2ec EBP+0 <-- ESP
0xffffd2e4 0a0b0c0d 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

1. Stocarea datelor temporare


Exemplu: Inter-schimbarea variabilelor value1 si value2
poate fi realizata utilizând stiva pentru a salva datele
temporare
push value1
push value2
pop value1
pop value2

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:

push word number1


Stiva
push word number2 “crește”,
call sum adresele
scad

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

• Există o alternativa mai buna?


∗ Folosirea lui EBP pentru a accesa parametrii de pe stivă

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

Stiva după Stiva după Stiva după


salvarea lui EBP pop EBP executia lui ret

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)

2. Adunarea unei constante la ESP în procedura


apelantă (C folosește aceasta metodă)
push word number1
push word number2
call sum
add ESP,4

Curs 10 - 11 14
Probleme de întreținere a stivei
• Cine ar trebui sa curețe stiva de parametri?

∗ Procedura apelată (callee)


» Codul devine modular (exemplul precedent cu ret 4)
» Nu poate fi utilizata cu un număr variabil de parametri

∗ Procedura apelantă (caller)


» Trebuie sa actualizeze ESP la fiecare apel de procedura
» permite număr variabil de parametri ( C )

Curs 10 - 11 15
Probleme de întreținere a stivei

• Trebuie salvat conținutul pentru procedura


apelantă
» Stiva este utilizata in acest scop
• Care dintre registre trebuie salvate?
∗ Se salvează acele registre care sunt utilizate de
procedura apelantă și sunt modificați de cea apelată
» Atenție: setul de registre utilizat variază în timp

∗ Se salvează toti registrii utilizand pusha


» Latența crescuta (pusha se executa în 5 cicluri de ceas, în
timp ce salvarea unui sigur registru se executa într-unul)

Curs 10 - 11 16
Probleme de întreținere a stivei

• Unde se menține starea procedurii apelante?


∗ Procedura apelantă (caller)
» Trebuie cunoscute registrele utilizate de procedura apelata
» Trebuie incluse instrucțiuni de salvare și restaurare a
registrelor la fiecare apel de procedura
» Cauzeaza probleme de mentenanta a programului
∗Procedura apelată (callee)
» Metoda preferata deoarece codul devine modular
(prezervarea stării se relizează într-un singur loc)
» Se evita problemele de mentenanță

Curs 10 - 11 17
Probleme de întreținere a stivei

• Conservarea stării apelantului în timpul apelului


» Pe stivă
• Ce registre ar trebui salvate?
∗ Se salvează acele registre care sunt utilizate de
apelant (caller) și modificate de apelat (callee)
» Poate cauza probleme
∗ Se salveaza toate registrele (metoda brute force)
» folosind pusha
» Latență crescută
– pusha se execută în 5 cicluri de ceas, iar salvarea unui
registru doar într-unul sigur

Curs 10 - 11 18
Probleme de întretinere a stivei

Starea stivei după


pusha

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

• Proceduri cu număr variabil de parametri


∗ La fiecare apel numărul de parametri poate fi diferit
» C folosește acest tip de proceduri
∗ Ușor de implementat folosind transmiterea prin stivă

Curs 10 - 11 25
Număr variabil de parametri

∗ Numărul de parametri
trebuie sa fie unul din
parametri transmiși

∗ Acest număr trebuie sa


fie ultimul parametru
pus pe stiva

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

Fără procedura swap

Curs 10 - 11 31
Performanta: Overhead variabile locale

Variabile locale pe stivă

Variabile locale în registre

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

S-ar putea să vă placă și