Laborator 6 - Suport teoretic
Operatii pe siruri de bytes/words/doublewords/quadwords
Operatii pe siruri
- Instructiunile pe siruri au operanzi impliciti.
- care folosesc un sir sursa si un sir destinatie (MOVSB, MOVSW, MOVSD, CMPSB, CMPSW, CMPSD)
- care folosesc numai un sir sursa (LODSB, LODSW, LODSD)
- care folosesc numai un sir destinatie (STOSB, STOSW, STOSD, SCASB, SCASW, SCASD)
- Move String = MOVS
- Compare String = CMPS
- Load String = LODS
- Store String = STOS
- Scan String = SCAS
- tipul elementelor (octeti, cuvinte sau dublucuvinte) => este indicat de ultima litera a instructiunii folosite (B=byte, W=word, D=doubleword), ambele siruri avand acelasi tip
- adresa primului element => este o adresa FAR memorata astfel:
- in DS:ESI - pentru sirul sursa
- in ES:EDI - pentru sirul destinatie
- directia de parcurgere => este indicata de valoarea din flagul DF (0 - de la adrese mai mici la adrese mai mari, 1 - de la adrese mai mari la adrese mai mici.)
- numărul de elemente => cand este nevoie de el, se pune în CX sau ECX
Instructiuni pentru transfer de date
LODSB | In AL se incarcă octetul de la adresa <DS:ESI> Daca DF=0 atunci inc(ESI), altfel dec(ESI) |
LODSW | In AX se incarcă cuvantul de la adresa <DS:ESI> Daca DF=0 atunci ESI:=ESI+2, altfel ESI:=ESI-2 |
LODSD | In EAX se incarcă dublucuvantul de la adresa <DS:ESI> Daca DF=0 atunci ESI:=ESI+4, altfel ESI:=ESI-4 |
STOSB | La adresa <ES:EDI> se incarcă octetul din AL Daca DF=0 atunci inc(EDI), altfel dec(EDI) |
STOSW | La adresa <ES:EDI> se incarcă cuvantul din AX Daca DF=0 atunci EDI:= EDI+2, altfel EDI:= EDI-2 |
STOSD | La adresa <ES:EDI> se incarcă dublucuvantul din EAX Daca DF=0 atunci EDI:= EDI+4, altfel EDI:= EDI-4 |
MOVSB | La adresa <ES:EDI> se incarca octetul de la adresa <DS:ESI> Daca DF=0 atunci inc(SI), inc(DI), altfel dec(SI), dec(DI) |
MOVSW | La adresa <ES:EDI> se incarca cuvantul de la adresa <DS:ESI> Daca DF=0 atunci ESI:= ESI+2, EDI:= EDI+2, altfel ESI:= ESI-2, EDI:= EDI-2 |
MOVSD | La adresa <ES:EDI> se incarca dublucuvantul de la adresa <DS:ESI> Daca DF=0 atunci ESI:= ESI+4, EDI:= EDI+4, altfel ESI:= ESI-4, EDI:= EDI-4 |
- Obs. Avand in vedere utilizarea modelului de memorie flat, la orice inceput de executie a programului, SO va initializa cu aceeasi valoare registrii segment DS = ES, programatorul neavând nici o responsabilitate de incarcare/actualizare/modificare a acestor valori. In cadrul codului sursa ce utilizeaza instructiuni pe siruri programatorul va trebui sa gestioneze doar offset-urile acestor siruri.
Exemplu:
;Avem un sir sursa (cuvinte). Sa se copieze intr-un sir destinatie. Stim cate elemente avem.
mov ECX, dim_sir ; nr de elemente din sir
mov ESI, sir_sursa ; incarcare offset sir_sursa in ESI
mov EDI, sir_dest ; incarcare offset sir_dest in EDI
CLD
Again:
LODSW
STOSW
LOOP Again
- Avand in vedere ca LODS + STOS = MOVS bucla de mai sus se mai poate scrie:
Again:
MOVSW
LOOP Again
- sau ( a se vedea sectiunea prefixelor de instructiune de mai jos)
rep MOVSW
Instructiuni pentru consultarea si compararea datelor
SCASB | CMP AL, <ES:EDI> Daca DF=0 atunci inc(EDI), altfel dec(EDI) |
SCASW | CMP AX, <ES:EDI> Daca DF=0 atunci EDI:= EDI+2, altfel EDI:= EDI-2 |
SCASD | CMP EAX, <ES:EDI> Daca DF=0 atunci EDI:= EDI+4, altfel EDI:= EDI-4 |
CMPSB | CMP <DS:ESI>, <ES:EDI> Daca DF=0 atunci inc(ESI), inc(EDI), altfel dec(ESI), dec(EDI) |
CMPSW | CMP <DS:ESI>, <ES:EDI> Daca DF=0 atunci ESI:= ESI+2, EDI:= EDI+2, altfel ESI:= ESI-2, EDI:= EDI-2 |
CMPSD | CMP <DS:ESI>, <ES:EDI> Daca DF=0 atunci ESI:= ESI+4, EDI:= EDI+4, altfel ESI:= ESI-4, EDI:= EDI-4 |
Exemplu:
;Se da un sir de octeti. Sa se găsească ultimul caracter "0".
;... se incarca toate datele despre sirul "destinatie"
MOV AL, '0'
MOV ECX, lung_sir
STD
Cont_caut: ;continui cautarea...
SCASB
JE Gasit
LOOP Cont_caut
;...
Gasit:
INC EDI;ma intorc la caracterul gasit inainte sa se fi facut decrementarea lui EDI
Prefixe de instructiune pentru executia repetata a unei instructiuni
prefix_de_instructiune instructiune_pe_sir
- echivalenta cu
Again:
instructiune_pe_sir
LOOP Again
- unde prefix_de_instructiune poate fi REP, echivalent cu REPE (Repeat While Equal), REPZ (Repeat While Zero) - care provoaca executia repetata a instructiunilor SCAS sau CMPS pana cand ECX devine 0 sau pana cand apare o nepotrivire ( => ZF=0)
- sau poate fi REPNE (Repeat While Not Equal) sau REPNZ (Repeat While Not Zero) - care provoaca executia repetata a instructiunii SCAS sau CMPS pana cand ECX devine 0 sau pana cand apare o potrivire ( => ZF=1)
- instructiunile pe siruri nu afecteaza flagurile in urma actiunii asupra registrilor ESI, EDI sau ECX
- LODS, STOS, MOVS - nu afecteaza nici un flag, in timp ce SCAS si CMPS modifica flagurile doar ca rezultat al comparatiilor efectuate