Laborator 7 - Suport teoretic

Operatii pe siruri de bytes/words/doublewords/quadwords

Operatii pe siruri

  • Instructiunile pe siruri au operanzi impliciti.
Tipuri de instructiuni pe siruri:
  • 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)
Pentru a fi retinute mai usor
  • Move String = MOVS
  • Compare String = CMPS
  • Load String = LODS
  • Store String = STOS
  • Scan String = SCAS
Un sir este caracterizat de:
  • 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:(E)SI>
Daca DF=0 atunci inc((E)SI), altfel dec((E)SI)
LODSW In AX se incarcă cuvantul de la adresa <DS:(E)SI>
Daca DF=0 atunci (E)SI:=(E)SI+2, altfel (E)SI:=(E)SI-2
LODSD In EAX se incarcă cuvantul de la adresa <DS:(E)SI>
Daca DF=0 atunci (E)SI:=(E)SI+4, altfel (E)SI:=(E)SI-4
STOSB La adresa <ES:(E)DI> se incarcă octetul din AL
Daca DF=0 atunci inc((E)DI), altfel dec((E)DI)
STOSW La adresa <ES:(E)DI> se incarcă cuvantul din AX
Daca DF=0 atunci (E)DI:= (E)DI+2, altfel (E)DI:= (E)DI-2
STOSD La adresa <ES:DI> se incarcă cuvantul din EAX
Daca DF=0 atunci (E)DI:= (E)DI+4, altfel (E)DI:= (E)DI-4
MOVSB La adresa <ES:(E)DI> se incarca octetul de la adresa <DS:(E)SI>
Daca DF=0 atunci inc(SI), inc(DI), altfel dec(SI), dec(DI)
MOVSW La adresa <ES:(E)DI> se incarca cuvantul de la adresa <DS:(E)SI>
Daca DF=0 atunci (E)SI:= (E)SI+2, (E)DI:= (E)DI+2, altfel (E)SI:= (E)SI-2, (E)DI:= (E)DI-2
MOVSD La adresa <ES:(E)DI> se incarca cuvantul de la adresa <DS:(E)SI>
Daca DF=0 atunci (E)SI:= (E)SI+4, (E)DI:= (E)DI+4, altfel (E)SI:= (E)SI-4, (E)DI:= (E)DI-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:(E)DI>
Daca DF=0 atunci inc((E)DI), altfel dec((E)DI)
SCASW CMP AX, <ES:(E)DI>
Daca DF=0 atunci (E)DI:= (E)DI+2, altfel (E)DI:= (E)DI-2
SCASD CMP EAX, <ES:(E)DI>
Daca DF=0 atunci (E)DI:= (E)DI+4, altfel (E)DI:= (E)DI-4
CMPSB CMP <DS:(E)SI>, <ES:(E)DI>
Daca DF=0 atunci inc(SI), inc(DI), altfel dec(SI), dec(DI)
CMPSW CMP <DS:(E)SI>, <ES:(E)DI>
Daca DF=0 atunci (E)SI:= (E)SI+2, (E)DI:= (E)DI+2, altfel (E)SI:= (E)SI-2, (E)DI:= (E)DI-2
CMPSD CMP <DS:(E)SI>, <ES:(E)DI>
Daca DF=0 atunci (E)SI:= (E)SI+4, (E)DI:= (E)DI+4, altfel (E)SI:= (E)SI-4, (E)DI:= (E)DI-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)
Observatii:
  • 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