lab 9. instrucţiuni de manipulare a șirurilor

18
LAB 9. Instrucţiuni de manipulare a șirurilor 9.1. Instrucţiuni pentru operaţii primitive Există 7 operaţii primitive specifice șirurilor, suportate încă de la 8086↑, acestea sunt date de instrucţiunile MOVS, LODS, STOS, CMPS, SCAS; INS, OUTS Aceste instrucţiuni operează asupra unui octet (8 biţi) sau cuvânt (16 biţi) din memorie (deci asupra unor locaţii succesive). Începând cu 386↑, acestea au fost suportate și la nivel de dublucuvânt (32 biţi), iar de la modul pe 64 biţi, pentru procesoare Pentium 4↑ sau Core 2↑, sunt suportate chiar şi la nivel de cvadruplucuvânt (64 biţi). Tipul operanzilor (adică la ce nivel se operează: de byte, de word, de doubleword sau de quadword) poate fi: - detectat automat de către asamblor prin specificarea operanzilor în mod explicit (la instrucţiunile MOVS, CMPS, SCAS, etc de exemplu o instrucţiune MOVS la nivel de octet va fi automat înlocuită cu MOVSB) - precizat în mod explicit în mnemonica instrucţiunii (MOVSB, CMPSB, etc); Distincţia între dimensiunea operanzilor se realizează prin folosirea sufixelor: B (byte), W (word), D (doubleword), respectiv Q (quadword). Sintaxa instrucțiunii movs de exemplu poate lua formele: movs {mem8,16,32,64},{mem8,16,32,64} sau movsb sau movsw sau movsd sau movsq Adresa din memorie (unde începe şirul) va fi specificată de : ES:DI pt operandul „destinațieşi DS:SI pt operandul „sursăAstfel, adresele fiind deja stabilite pentru destinație şi sursă, mai e necesară doar precizarea dimensiunii operanzilor sau numărul de locații afectate - aceasta poate fi: un octet - va fi vizată o singură locație, un cuvânt - vor fi vizate 2 locații, începând de la acele adrese. Dimensiunea operanzilor se va putea deduce fie din operanzii expliciți - byte pt mem8 - word pt mem16 fie din tipul mnemonicii folosite: - byte pt MOVSB, LODSB, STOSB, CMPSB, SCASB - word pt MOVSW, LODSW, STOSW, CMPSW, SCASW Instrucţiunile pentru şiruri realizează inclusiv actualizarea adreselor, însă acestea nu ştiu să repete operaţia de un număr de ori câte elemente are şirul de prelucrat. Astfel, se folosește combinarea instrucţiunii pt lucrul cu şiruri cu algoritmi de repetare, gen: prefixe de repetare (rep/repe/repz/repne/repnz) sau bucle cu salt condiţionat (cu loopz, loopnz, loope, etc); uneori se poate folosi loop pentru repetarea operației de CX ori. În mod implicit, la instrucţiunile pe şiruri, se consideră următoarele: Observații: Sursa şi destinația sunt implicite: - perechea de regiştrii DS:SI se foloseşte pentru adresarea sursei; - perechea de regiştrii ES:DI se foloseşte pentru adresarea destinaţiei; Segmentul implicit ES nu poate fi modificat prin specificarea explicită a unui alt registru segment în instrucţiune (de exemplu DS:DI), dar DS poate fi schimbat.

Upload: others

Post on 24-Apr-2022

3 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: LAB 9. Instrucţiuni de manipulare a șirurilor

LAB 9. Instrucţiuni de manipulare a șirurilor

9.1. Instrucţiuni pentru operaţii primitive

Există 7 operaţii primitive specifice șirurilor, suportate încă de la 8086↑, acestea sunt date de instrucţiunile MOVS, LODS, STOS, CMPS, SCAS; INS, OUTS Aceste instrucţiuni operează asupra unui octet (8 biţi) sau cuvânt (16 biţi) din memorie (deci asupra unor locaţii succesive). Începând cu 386↑, acestea au fost suportate și la nivel de dublucuvânt (32 biţi), iar de la modul pe 64 biţi, pentru procesoare Pentium 4↑ sau Core 2↑, sunt suportate chiar şi la nivel de cvadruplucuvânt (64 biţi).

Tipul operanzilor (adică la ce nivel se operează: de byte, de word, de doubleword sau de quadword) poate fi:

- detectat automat de către asamblor prin specificarea operanzilor în mod explicit (la instrucţiunile MOVS, CMPS, SCAS, etc de exemplu o instrucţiune MOVS la nivel de octet va fi automat înlocuită cu MOVSB)

- precizat în mod explicit în mnemonica instrucţiunii (MOVSB, CMPSB, etc);

Distincţia între dimensiunea operanzilor se realizează prin folosirea sufixelor:

B (byte), W (word), D (doubleword), respectiv Q (quadword).

Sintaxa instrucțiunii movs de exemplu poate lua formele:

movs {mem8,16,32,64},{mem8,16,32,64} sau movsb sau movsw sau movsd sau movsq

Adresa din memorie (unde începe şirul) va fi specificată de : ES:DI pt operandul „destinație” şi DS:SI pt operandul „sursă”

Astfel, adresele fiind deja stabilite pentru destinație şi sursă, mai e necesară doar precizarea dimensiunii operanzilor sau numărul de locații afectate - aceasta poate fi: un octet - va fi vizată o singură locație, un cuvânt - vor fi vizate 2 locații, începând de la acele adrese. Dimensiunea operanzilor se va putea deduce fie din operanzii expliciți - byte pt mem8

- word pt mem16

fie din tipul mnemonicii folosite: - byte pt MOVSB, LODSB, STOSB, CMPSB, SCASB - word pt MOVSW, LODSW, STOSW, CMPSW, SCASW

Instrucţiunile pentru şiruri realizează inclusiv actualizarea adreselor, însă acestea nu ştiu să repete operaţia de un număr de ori câte elemente are şirul de prelucrat. Astfel, se folosește combinarea instrucţiunii pt lucrul cu şiruri cu algoritmi de repetare, gen: prefixe de repetare (rep/repe/repz/repne/repnz) sau bucle cu salt condiţionat (cu loopz, loopnz, loope, etc); uneori se poate folosi loop pentru repetarea operației de CX ori.

În mod implicit, la instrucţiunile pe şiruri, se consideră următoarele:

Observații:

Sursa şi destinația sunt implicite:

- perechea de regiştrii DS:SI se foloseşte pentru adresarea sursei; - perechea de regiştrii ES:DI se foloseşte pentru adresarea destinaţiei;

Segmentul implicit ES nu poate fi modificat prin specificarea explicită a unui alt registru segment în instrucţiune (de exemplu DS:DI), dar DS poate fi schimbat.

Page 2: LAB 9. Instrucţiuni de manipulare a șirurilor

Şirul poate fi stocat în memorie:

- în sens crescător (de la adrese mai mici -> adrese mai mari) dacă DF=0, mod auto-incrementare: dinspre primul -> înspre ultimul

- în sens descrescător (de la adrese mai mari -> adrese mai mici) dacă DF=1, mod auto-decrementare: dinspre ultimul -> înspre primul

La parcurgerea şirului în sens crescător

=> SI sau/ şi DI vor fi actualizaţi prin incrementare,

iar la parcurgerea şirului în sens descrescător

=> SI sau/ şi DI vor fi actualizaţi prin decrementare;

Numărul de octeţi cu care se incrementează/ decrementează regiştrii SI şi DI este dat de dimensiunea elementelor şirului: d=1 pt octeţi, d=2 pt cuvinte,

9.1.1. Instrucţiunile MOVS şi MOVS B/W

Instrucţiunile de copiere sau transfer (MOVe String) MOVS[-B/W] transferă un octet sau un cuvânt din şirul sursă (adresat de DS:SI în şirul destinaţie (adresat de ES:DI, transfer

urmat de actualizarea adreselor. mod pe 16biți,

mov ES:[DI], DS:[SI] și actualizeazӑ

DI = DI ± d şi SI = SI ± d,

unde operaţia e cu “+” dacă DF=0, respectiv cu ”-“ dacă DF=1,

iar d = {1-octet, 2-cuvânt} Observații: Instrucţiunile MOVS şi MOVS B/W nu afectează flagurile.

9.1.2. Instrucţiunile LODS şi LODS B/W

Instrucţiunile de încărcare a elementelor din şir (LOaD String) LODS[-/B/W] încarcă în „Acc” (AL sau AX), un octet sau un cuvânt (cel de la adresa DS:SI), iar apoi se actualizează adresa pentru a accesa următorul element al şirului.

mod pe 16biți,

mov AL/AX, [DS:SI]

SI = SI ± d,

unde operaţia e cu “+” dacă DF=0, respectiv cu ”-“ dacă DF=1,

iar d = {1-octet, 2-cuvânt} Observații: Instrucţiunile LODS şi LODS B/W nu afectează flagurile.

Page 3: LAB 9. Instrucţiuni de manipulare a șirurilor

9.1.3. Instrucţiunile STOS şi STOS B/W

Instrucţiunile de memorare şir (STOre String) STOSB/W încarcă valoarea din AL sau AX în octetul sau cuvântul de la adresa DS:DI, iar apoi se actualizează adresa. mod pe 16biți,

mov [ES:DI], AL/AX

DI = DI ± d,

unde operaţia e cu “+” dacă DF=0, respectiv cu ”-“ dacă DF=1,

iar d = {1-octet, 2-cuvânt } Observații: Instrucţiunile STOS şi STOS B/W nu afectează flagurile. movs, lods, stos dest, sursa cmps, scas sursa, dest

9.1.4. Instrucţiunile CMPS şi CMPS B/W

Instrucţiunile de comparare şir (CoMPare String) CMPSB/W testează egalitatea şirurilor prin comparare element cu element. Se execută o scădere fictivă între octeții,resp.

cuvintele, de la adresele DS:SI şi ES:DI, fără modificarea operanzilor, dar cu poziţionarea tuturor flagurilor. mod pe 16biți,

cmp [DS:SI], [ES:DI] ; rez=[DS:SI] – [ES:DI]-> flag

setează FLAGS şi apoi

DI = DI ± d, SI = SI ± d,

unde operaţia e cu “+” dacă DF=0, respectiv cu ”-“ dacă DF=1,

iar d = {1-octet, 2-cuvânt } Observații: Instrucţiunile CMPS şi CMPS B/W afectează flagurile OF, SF, ZF, AF, PF, CF.

9.1.5. Instrucţiunile SCAS şi SCAS B/W

Instrucţiunile de scanare (SCAn String) SCASB/W testează/ caută un anumit octet sau cuvânt, într-un şir. Se execută diferenţa fictivă dintre AL sau AX şi octetul,resp. cuvântul,

de la adresa DS:DI, fără modificarea operanzilor, dar cu poziţionarea tuturor flagurilor. mod pe 16biți,

cmp AL/AX, [ES:DI] setează FLAGS şi apoi

DI = DI ± d,

unde operaţia e cu “+” dacă DF=0, respectiv cu ”-“ dacă DF=1, iar d = {1-octet, 2-cuvânt}

Page 4: LAB 9. Instrucţiuni de manipulare a șirurilor

Observații: Instrucţiunile SCAS şi SCAS B/W afectează flagurile OF, SF, ZF, AF, PF, CF.

9.2. Instrucţiuni cu şiruri pe port

Instrucţiunile INS (Input String) şi OUTS (Output String) (implementate de la procesoarele 80186↑) preiau/ trimit un şir de elemente (octet, word sau doubleword) de la/ la un port de intrare/ieşire. Instrucţiunile INSB/W/D şi OUTSB/W/D nu au operanzi şi sunt formele scurte ale instrucţiunilor INS şi OUTS, furnizând implicit dimensiunea datelor de pe port: octet, cuvânt sau dublucuvânt. Registrul DX în mod implicit este adresa portului, iar destinaţia implicită este dată de perechea de regiştri ES:DI, respectiv DS:SI.

Exemple de instrucţiuni ilegale:

movsb EAX, EBX ; instrucţiunile pe şiruri au operanzii impliciţi, aceştia nu trebuie precizaţi în instrucţiune

Exemple de instrucţiuni legale:

Exemplele care urmează au rolul de a fixa anumite noţiuni ale instrucţiuilor pe şiruri şi de a se însuşi deprinderea lucrului cu acestea. In secţiunile următoare aceste exemple vor fi reluate în cadrul unor exemple de programe complete.

Exemple 9-1.1: În mod pe 16 biți: movsb ; ES:[DI]=DS:[SI]; DI=DI±1, SI=SI±1 (transfer la nivel de byte) movsw ; ES:[DI]=DS:[SI]; DI=DI±2, SI=SI±2 (transfer la nivel de word) Exemple 9-1.2: stosb ; ES:[DI]=AL, DI=DI±1 lodsb ; AL=DS:[SI], SI=SI±1 insb ; ES:[DI]=[DX], DI=DI±1 outsb ; [DX]=DS:[SI], SI=SI±1

Exemplul 9-1.3 Secvenţa următoare defineşte 2 şiruri: unul sursă şi unul destinaţie, poziţionează regiştrii index pe zonele de început ale şirurilor (vor pointa spre primul element din fiecare şir), iar apoi execută instrucţiunea MOVSB: SIRs DB 1,2,3,4,5 ; se def. şirul destinaţie cu 5 elem. octet, iniţilizat cu 1,2,3,4,5 SIRd DB 5 DUP(0) ; se def şirul sursă cu 5 elemente pe octet, neiniţilizat ... lea SI, SIRs ; SI=adresa de început a SIRs = 102h lea DI, SIRd ; DI=adresa de început a SIRd = 107h cld ; DF=0, şirurile vor fi parcurse în sens crescător movsb ; se mută doar primul elem. din şir şi se poziţionează pe cel de-al doillea element din cadrul fiecărui şir Exemplul 9-1.4 Exemplul anterior poate fi rescris fol. instrucţiunile LODSB şi STOSB, iar astfel elementul din şirul sursă este preluat în registrul acumulator şi abia apoi depus în şirul destinaţie. lodsb ; AL = element curent din SIRs stosb ; din AL se depune elementul curent în SIRd Exemplul 9-1.5 Secvenţa următoare verifică în cadrul unui şir cu 10 elemente definite pe octet dacă primul element este egal cu valoarea din registrul AL, prin utilizarea instrucţiunii SCASB: SIRd DB 0,1,2,3,2,4,2,5,2,6 ; se def şirul destinaţie cu 10 elem. pe octet, iniţilizat cu 0,1,2,3,2,4,2,5,2,6 ... mov AL, 2 ; numărul (elementul) de căutat lea DI, SIRd ; DI=adresa de început a SIRd

Page 5: LAB 9. Instrucţiuni de manipulare a șirurilor

cld ; DF=0, şirul va fi parcurs în sens crescător scasb ; se verifică egalitatea elem: cel din şir şi cel căutat şi se poziţionează pe următorul elem din şir Exemplul 9-1.6 Exemplul anterior s-ar putea transpune pentru verificarea egalităţii primului element din 2 şiruri prin utilizarea instrucţiunii CMPSB: SIRd DB 0,1,2,3,2,4,2,5,2,6 ; se def şirul destinaţie cu 10 elemente pe octet, iniţilizat cu 0,1,2,3,2,4,2,5,2,6 SIRs DB 0,1,2,3,2,4,2,5,2,6 ; se def şirul sursă cu 10 elemente pe octet, iniţilizat cu 0,1,2,3,2,4,2,5,2,6 ... lea SI, SIRs ; SI=adresa de început a SIRs lea DI, SIRd ; DI=adresa de început a SIRd cld ; DF=0, şirul va fi parcurs în sens crescător cmpsb ; se verifică egalitatea primului element din cele 2 şiruri şi se poziţionează pe următ. elem. din şir Exemplul 9-1.7 insb ; preia un şir de octeţi de pe portul ce are adresa specificată în registrul DX şi îl depune în memorie

; la adresa dată de ES:DI, DI=DI±1 din memorie, de la adresa dată de DS:SI trimite outsw ; un şir de cuvinte pe portul cu adresa specificată în registrul DX, SI=SI±1 Observaţii:

Trebuie acordată atenţie sporită la valorile CX la intrarea în buclă, pentru a evita buclarea de 216ori sau o eventuală buclare infinită (şi nedorită). Cele 2 de mai jos sunt echivalente semantic, dar nu au acelaşi efect ! (Instrucţiunea DEC afectează flagurile O,Z,S,P, dar LOOP nu le afectează. )

LOOP eti dec CX

jnz eti Exemplul 9-2.1 Pentru a realiza copierea unui şir (SIRs) de 5 elemente într-un alt şir (SIRd) se poate pleca de la secvenţa de instrucţiuni din Exemplul 9-1.3 (inserate în culoare mai deschisă în exemplul curent) şi se poate adapta pentru repetarea acţiunii la numărul de elemente al şirului.

Pentru aceasta, va trebui la început să poziţionăm regiştrii index pe zonele de început ale şirurilor (să pointeze spre primul element din fiecare şir), iar apoi pentru fiecare element să execute instrucţiunea MOVSB/W, să decrementeze numărul de elemente pentru care se repetă algoritmul şi să reia algoritmul până când nr. de elemente pentru care se repetă algoritmul a ajuns la zero. Astfel, vom obţine secvenţa:

SIRs DB 1,2,3,4,5 ; se def. şirul destinaţie cu 5 elem. octet, iniţilizat cu 1,2,3,4,5 SIRd DB 5 DUP(0) ; se def şirul sursă cu 5 elemente pe octet, neiniţilizat ... lea SI, SIRs ; SI=adr de început a SIRs lea DI, SIRd ; DI=adr de început a SIRd mov CX,5 ; CX=5 numărul de elemente cld ; DF=0, şirurile vor fi parcurse în sens crescător et: movsb ;eticheta et se fol. pt a asigura revenirea în acest punct dec cx ;după execuţia mosvb (mută element şi

; actualizează adresa), CX=CX-1 jnz et ; dacă încă CX nu a ajuns să fie zero

; (jump if not ZF-> dacă ZF=0, face salt), se reia bucla

Page 6: LAB 9. Instrucţiuni de manipulare a șirurilor

Exemplul 9-2.2 Exemplul precedent poate fi rescris folosind instrucţiunile LODSB şi STOSB, iar astfel fiecare element al şirului sursă este preluat în registrul acumulator, şi abia apoi depus în şirul destinaţie. Bucla de repetiţie se va rescrie astfel: et: lodsb ; AL = element curent din SIRs stosb ; din AL se depune elementul curent în SIRd dec cx ; după execuţia mosvb (mutare element şi actualizare adrese), CX=CX-1 jnz et ; dacă încă CX nu a ajuns să fie zero, se reia bucla

Exemplul 9-2.3 Pentru a realiza căutarea (prin scanare) unui anumit caracter într-un şir de elemente va trebui la început să repetăm raţionamentul descris în primul exemplu adaptat la operaţia SCASB: condiţia de repetare nu se mai referă la un anumit număr de elemente, ci la o anumită condiţie (egalitatea a 2 elemente). Astfel, vor interveni flagurile, mai exact ZF care se setează doar în momentul când cei 2 operanzi ce se compară sunt egali. In secvenţa următoare se caută primul element de valoare 2 din acest șir:

SIR DB 0,1,7,3,2,4,2,5,2,6 ; se def şirul destinaţie cu 10 elem. pe octet, lungSIR equ ($-SIRd) ... mov AL, 2 ; numărul (elementul) de căutat lea DI, SIR ; DI=adr de început a SIR mov CX, lungSIR ; CX= nr. de elemente, determinat cu operatorul $ cld ; DF=0, şirul va fi parcurs în sens crescător

et: scasb ; eticheta et se fol. pt a asigura revenirea în acest punct jz gasit ; se verifică egalitatea elementelor (cel din şir cu cel căutat) şi în funcţie de ZF se face salt dec CX jnz et ; dacă s-a găsit,sare la eticheta gasit, altfel ajunge aici şi face salt la et, atât timp cât CX încă nu a ajuns la

; sfârşit, deci reia căutarea pt următorul element din şir mov DI,0 ; dacă elementul nu există în şir, pun 0 în registrul DI jmp exit ; sar la eticheta care duce la sfârşitul programului gasit: dec DI ; din cauză că instrucţ. scasb a actualizat deja adresa pe următorul element al şirului,

; trebuie să ne întoarcem o poziţie înapoi mov BX, DI ; în BX vom avea poziția elementului cӑutat

exit: ... scas AL/AX - ??? DI

Exemplul 9-2.4 Pentru a testa egalitatea a 2 şiruri vor trebui comparate şirurile element cu element, iar dacă înainte de a ajunge la sfârşitul celor 2 şiruri (se pp. că au acelaşi nr de elem.) se întâlneşte o nepotrivire, concluzionăm că şirurile nu sunt egale (şi în registrul DI se va obţine poziţia primei nepotriviri). Astfel, asemănător cu exemplul precedent, vom obţine: SIRd DB 0,1,2,3,2,4,2,5,2,6 ; se def şirul destinaţie cu 10 elemente pe octet, lungSIRd equ ($-SIRd) ; se def. imediat după variabila corespunzătoare SIRs DB 0,1,2,3,2,4,2,5,2,6 ; se def şirul sursă cu 10 elemente pe octet,

; iniţializat cu 0,1,2,3,2,4,2,5,2,6 ... lea SI, SIRs ; SI=adr de început a SIRs

Page 7: LAB 9. Instrucţiuni de manipulare a șirurilor

lea DI, SIRd ; DI=adr de început a SIRd mov CX, lungSIRd ; CX= numărul de elemente, determinat cu operatorul $ cld ; DF=0, şirul va fi parcurs în sens crescător et: cmpsb ;eticheta et se fol. pt a asigura revenirea în acest punct jnz nepotrivire ; se verifică egalitatea elementelor din cele 2 şiruri şi

; în funcţie de ZF se face salt dec CX jnz et ;dacă s-a găsit o inegalitate, sare la eticheta nepotrivire, altfel ajunge aici şi

; face salt la et, (doar dacă încă nu s-a ajuns la sfârşitul şirurilor) și deci repetӑ compararea a 2 elemente;

potrivire: call AfisMesaj ; dacă s-a ajuns aici, înseamnă că s-au parcurs şirurile până la sfârşit şi nu s-a găsit nici o nepotrivire, ; deci şirurile sunt egale, astfel că se afişează mesajul corespunzător

nepotrivire: dec DI ; deoarece instrucţ. scasb a actualizat deja adresa pe următ. elem al şirului, ; trebuie să ne întoarcem o poziţie

Exemplul 9-2.5 Secvenţa de buclare din exemplul 9-2.3: et: movsb ; eticheta et se fol. pt a asigura revenirea în acest punct dec CX ; după execuţia mosvb (mută element şi actualizează adresa), CX=CX-1 jnz et ; dacă încă CX nu a ajuns să fie zero (jump if not ZF-> dacă ZF=0, face salt),

; se reia bucla ;se poate înlocui cu: et: movsb loop et ; reg. CX e automat decrementat şi verificat prin folosirea loop

Exemplul 9-2.6 Secvenţa de buclare poate fi rescrisă: et: scasb ; eticheta et se fol. pt a asigura revenirea în acest punct jz gasit ; se verifică egalitatea elementelor (cel din şir cu cel căutat) şi în funcţie de ZF se face salt dec CX jnz et ; dacă s-a găsit,sare la eticheta gasit, altfel ajunge aici şi face salt la et, atât timp cât CX încă nu a ajuns la

; sfârşit, deci reia căutarea pt următ. element din şir ;se poate înlocui cu: et: scasb je gasit loop et ; reg.CX e automat decrementat şi verificat prin folosirea loop Exemplul 9-3.1 Secvenţa de buclare din exemplul 6.2-1: et: movsb ;eticheta et se fol. pt a asigura revenirea în acest punct dec cx ; după execuţia mosvb (mută element şi actualizează adrese), CX=CX-1 jnz et ; dacă încă CX nu a ajuns să fie zero (jump if not ZF-> dacă ZF=0, face salt), se reia bucla ;se poate înlocui cu: rep movsb ; registrul CX este automat decrementat şi verificat prin folosirea prefixului rep.

Page 8: LAB 9. Instrucţiuni de manipulare a șirurilor

Exemplul 9-3.2 Secvenţa de buclare din exemplul 6-2.3: et: scasb ;eticheta et se fol. pt a asigura revenirea în acest punct jz gasit ; se verifică egalitatea elementelor (cel din şir cu cel căutat) şi în funcţie de ZF se face salt dec CX jnz et ; dacă s-a găsit,sare la eticheta gasit, altfel ajunge aici şi face salt la et, atât timp cât CX încă nu a ajuns la

; sfârşit, deci reia căutarea pt următ. element din şir mov DI,0 ; dacă elementul nu există în şir, pun 0 în registrul DI jmp exit ; sar la eticheta care duce la sfârşitul programului ;se poate înlocui cu: repnz scasb ; prefixul repnz face ca instrucţ. scasb să se repete până când CX=0 sau până găseşte elementul căutat jcxz exit ; dacă CX a ajuns în 0, am terminat şi nu s-a găsit

9.4. Instrucţiuni pentru control indicatori (flags)

Instrucţiunile pentru controlul indicatorilor sau flagurilor – se folosesc în general atunci când programatorul doreşte să modifice / controleze modul de execuţie al unor instrucţiuni care exploatează acele flaguri (de exemplu direcţia de parcurgere a elementelor octet/ cuvânt, etc la instrucţiunile pe şiruri).

Instrucţiune Efect Instrucţiune Efect

CLC CF=0 STC CF=1

CMC CF=/CF

CLD DF=0 STD DF=1

CLI IF=0 STI IF=1

CLAC ACF=0 (EFLAGS|b18) STAC ACF=1 (EFLAGS|b18)

Sinteza: adresa primului (DF=0)/ ultimului element (DF=1) => este o adresa FAR memorata astfel:

in DS:SI - pentru sirul sursa in ES:DI - pentru sirul destinatie

directia de parcurgere => - indicata de valoarea din flagul DF (0 – CLD - adrese mai mici -> adrese mai mari, 1 – STD - adrese mai mari -> adrese mai mici.) numărul de elemente => cand este nevoie de el, se pune în CX (daca folosim loop sau prefix de repetare)

1. MOVS(B/W): mov ES:[DI], DS:[SI], cu DI = DI ± d şi SI = SI ± d

2. LODS(B/W): mov AL/AX, DS:[SI], cu SI = SI ± d

3. STOS(B/W): mov ES:[DI], AL/AX, cu DI = DI ± d

LODS + STOS = MOVS

4. CMPS(B/W): cmp DS:[SI], ES:[DI] cu DI = DI ± d şi SI = SI ± d si seteaza FLAGS , scade sursa-dest

5. SCAS(B/W): cmp AL/AX, ES:[DI] cu DI = DI ± d si seteaza FLAGS , scade Acc-dest

operaţia e cu “+” dacă DF=0, resp. cu ”-“ dacă DF=1, iar d = {1-octet, 2-cuvânt}

Page 9: LAB 9. Instrucţiuni de manipulare a șirurilor

PR9-1. Să se scrie un program care să realizeze copierea unui şir (SIRs) de 5 elemente de tip octet într-un alt şir (SIRd) cu instrucţiuni pe şiruri.

Elementele se vor copia în aceeaşi ordine în şirul destinaţie cum au fost în şirul sursă.

Rezolvare: Se poate folosi instrucţiunea specifică operaţiilor pe şiruri, movsb. Pentru repetarea acţiunii la numărul de elemente al şirului, va trebui la început

să poziţionăm regiştrii index pe zonele de început ale şirurilor (să pointeze spre primul element din fiecare şir), pentru fiecare element să execute instrucţiunea

movsb, iar apoi să decrementeze numărul de elemente de prelucrat până când acest număr devine 0. Astom obţine secvenţa:

org 100h ; p9_01

.data def. şirul sursă cu 5 elemente octet

lung equ $-SIRs

SIRd db lung DUP(0) ; se def şirul destinaţie cu 5 elemente pe octet, neiniţilizat

.code

lea SI, SIRs ; SI=adresa de început a SIRs

lea DI, SIRd ; DI=adresa de început a SIRd

mov CX, lung ; CX=5 numărul de elemente

cld ; DF=0, şirurile vor fi parcurse în sens crescător

et: movsb ; eticheta et se fol. pt a asigura revenirea în acest punct

loop et ; se reia bucla de lung ori

Figura 9-1. Datele problemei PR9-1 (stânga), respectiv PR9-2 (dreapta)

PR9-2. Să se scrie un program care să realizeze copierea unui şir (SIRs) de 5 elemente de tip octet într-un alt şir (SIRd) cu instrucţiuni pe şiruri. Elementele

se vor copia în ordine inversă în şirul destinaţie faţă de cum au fost în şirul sursă.

Rezolvare: Se pot folosi instrucţiunile specifice operaţiilor pe şiruri, movsb.

org 100h ; p9_02

.data

SIRs DB 1,2,3,4,5 ; se def. şirul sursă cu 5 elemente octet

lung equ $-SIRs

SIRd db lung DUP(0) ; se def şirul destinaţie cu 5 elemente pe octet, neiniţilizat

.code

lea SI, SIRs ; SI=adresa de început a SIRs

lea DI, SIRd+lung-1 ; DI=adresa ultimului element din SIRd

mov CX, lung ; CX=5 numărul de elemente

et: cld ; DF=0, şirul SIRs va fi parcurs în sens crescător

lodsb ; încarcă în AL elementul curent din SIRs

std ; DF=1, şirul SIRd va fi parcurs în sens descrescător

stosb ; încarcă din AL în SIRd

loop et ; se reia bucla de lung ori

Page 10: LAB 9. Instrucţiuni de manipulare a șirurilor

PR9-3. Se dau două șiruri de câte 5 elemente, reprezentate pe octet, în segmentul de date. Să se genereze un al treilea șir prin interclasarea elementelor

celor două șiruri. Se presupune că cele 2 şiruri sursă au aceeaşi lungime.

Exemplu: SIR1: 1,3,5,7,9

SIR2 : 2,4,6,8,10 => SIR3 va fi 1,2,3,4,5,6,7,8,9,10

Rezolvare: Interclasarea se referă la întrepătrunderea elementelor: astfel, în şirul destinaţie se va depune un element din primul șir, apoi un element din al

doilea şir, apoi iar un element din primul şir, şi tot aşa. Astfel, se depun mai întâi elementele din șirul 1 în șirul 3, pe pozițiile impare; după terminarea

elementelor din primul şir, se depun elementele din șirul 2 în șirul 3, în pozițiile pare.

org 100h ; p9_03

.data

SIR1 DB 1,3,5,7,9

SIR2 DB 2,4,6,8,10

lung equ $-SIR2

SIR3 db lung*2 DUP(0)

.code ; se depun elementele din șirul 1 în șirul 3:

mov CX, lung

mov SI, offset sir1 ; şirul sursă1

mov DI, offset sir3 ; şirul destinație

iar1: movsb

inc DI ; o dată DI se incrementează automat de la movsb,

; se mai incrementează încă o dată, pt că

loop iar1 ; elementele se pun din două în două poziții

; se depun elementele din șirul 2 în șirul 3:

mov CX, lung

mov SI, offset sir2 ; şirul sursă2

mov DI, offset sir3 ; şirul destinație

inc DI ; pentru a începe de la poziția a doua

iar2: movsb ; o dată DI se incrementează automat de la movsb,

inc DI ; se mai incrementează încă o dată, pt că

loop iar2 ; elementele se pun din două în două poziții

PR9-4. Se dă un şir de octeţi interpretaţi ca numere fără semn. Să se scrie o secvenţă de program care să găsească maximul dintr-un şir atât folosind

instrucţiuni pe şiruri cât şi fără utilizarea acestora.

Rezolvare: ; cu jge găsim maximul pt numere cu semn

; cu jae găsim maximul pt numere fără semn

Page 11: LAB 9. Instrucţiuni de manipulare a șirurilor

Fără instrucţiuni pe şiruri Cu instrucţiuni pe şiruri

org 100h ; p9_04_a

.data

sir db 4h, 0FFh,3h,0FEh,5h,7h,6h

; 4,-1,3,-2,5,7,6

lung EQU $-sir

max db ?

index dw 0

.code

mov SI, 0 ; index pt parcurgere

mov CX, lung-1 ; nr de comparări

mov AL, sir[0] ; AL=sir[0]

start:

inc SI ; poziţionare pe sir[1]

cmp AL, sir[SI] ; cmp sir[0] cu sir[1]

jae et1 ; dacă e > trece la următ

mov AL, sir[SI] ; altfel, înlocuieşte

mov BX, SI ; păstrează indexul

et1:

loop start ; reia de lung-1 ori

mov max, AL ; depune maximul

mov index, BX ; şi indexul lui

ret

org 100h ; p9_04_b

.data

sir db 4h, 0FFh,3h,0FEh,5h,7h,6h

; 4,-1,3,-2,5,7,6

lung EQU $-sir

max db ? ; maximul gasit

index db ? ; ce indexul maximului

adresa dw ? ; adresa maximului

.code

cld ; DF=0

mov SI, offset sir ; SI=offset sir

mov CX, lung-1 ; nr de comparări

lodsb ; AL=sir[0]

mov max, AL ; max=sir[0]

mov BX, offset sir+1; poate fi primul

start:

lodsb ; AL=sir[1]

cmp max, AL ; cmp sir[0] cu sir[1]

jae et1 ; dacă e > trece la următ

mov max, AL ; altfel, înlocuieşte

mov BX, SI ; păstrează offsetul

et1:

loop start ; reia de lung-1 ori

dec BX ; merge înapoi o poz.

mov adresa, BX ; calcul index

sub BX, offset sir

mov index, BL

ret

Figura 9-2. Datele problemei PR9-3

Figura 9-3. Datele problemei PR9-4

PR9-5 (de analizat). Se dau 2 șiruri de câte 8 elemente fiecare, reprezentate pe octet, în segmentul de date. a) Să se verifice dacă cele două șiruri sunt

identice (ca valori). Să se rezolve atât folosind instrucţiuni pe şiruri cât şi fără utilizarea acestora.

b) Să se realizeze şi un program de tip EXE, nu COM. Rezolvare:

Page 12: LAB 9. Instrucţiuni de manipulare a șirurilor

a) Se realizează compararea șirurilor, element cu element, cât timp elementele sunt egale; dacă am ajuns la sfârşitul şirurilor şi nu s-a găsit o pereche de

elemente diferite, atunci şirurile sunt identice. Pentru rezolvare, s-a folosit şablon de program de tip COM, acesta având specific faptul că toate segmentele

sunt înghesuite într-o singură zonă de maxim 64k şi toţi regiştrii segment încep la aceeaşi adresă. Astfel, şirurile date de indecşii SI şi DI se vor găsi în

acelaşi segment (nu a fost nevoie de poziţionarea lui ES şi DS pe aceeaşi zonă).

Fără instrucţiuni pe şiruri

org 100h ; p9_05_a

.data

sir1 db 1,2,3,4,5,6,7,8

sir2 db 1,2,3,4,5,7,7,8

lung equ $-sir2

var db 0 ;variabilă indicator:

; var=1 => șiruri identice

; var=0 => șiruri diferite

Cu instrucţiuni pe şiruri

org 100h ; p9_05_b

.data

sir1 db 1,2,3,4,5,6,7,9

sir2 db 1,2,3,4,5,6,7,9

lung equ $-sir2

var db 0 ;variabilă indicator:

; var=1 => șiruri identice

; var=0 => șiruri diferite

.code

mov CX, lung

mov SI, offset sir1

;mov AX, seg sir1

;mov DS, AX

mov DI, offset sir2

;mov AX, seg sir2

;mov ES, AX

iar: mov AL, [SI]

mov BL, [DI]

inc SI

inc DI

cmp AL, BL

jne sf

loop iar

mov var, 1 ; șiruri identice

sf: ret

.code

mov CX, lung

mov SI, offset sir1

;mov AX, seg sir1

;mov DS, AX

mov DI, offset sir2

;mov AX, seg sir2

;mov ES, AX

iar:

cmpsb

jne sf

loop iar

mov var,1 ; șiruri identice

sf: ret

Figura 9-4. Datele problemei PR9-5

Următoarele (secvenţe de ) instrucţiuni sunt echivalente:

iar:

cmpsb

jne sf

repe cmpsb

Page 13: LAB 9. Instrucţiuni de manipulare a șirurilor

b) Un program EXE trebuie să respecte un anumit format pentru a funcţiona în simulator, aşa cum se poate observa mai jos:

; program cu mai multe segmente (program de tip EXE) ; p9_05_c

data segment ; segment de date

sir1 db 1,2,3,4,8,6,7,9

sir2 db 1,2,3,4,8,6,7,9

lung equ $-sir2

var db 0

ends

stack segment ; segment de stivă

dw 128 dup(0)

ends

code segment ; segment de cod

start:

; setarea regiştrilor segment pe aceeaşi zonă a datelor

mov ax, data

mov ds, ax

mov es, ax

mov CX, lung

mov SI, offset sir1

mov AX, seg sir1

mov DS, AX

mov DI, offset sir2

mov AX, seg sir2

mov ES, AX

iar:

cmpsb

jne sf

loop iar

mov var,1 ; şiruri identice

sf:

mov ax, 4c00h ; exit

int 21h

ends

end start ; punctul de intrare în program e start

PR9-6. Să se scrie o secvenţă de program prin care să se caute un anumit caracter într-un şir de caractere. Să se rezolve atât folosind instrucţiuni pe şiruri

cât şi fără utilizarea acestora. Rezolvare:

Page 14: LAB 9. Instrucţiuni de manipulare a șirurilor

Pentru a realiza căutarea (prin scanare) unui anumit caracter într-un şir de elemente, va trebui să repetăm instrucţiunea scasb: condiţia de repetare nu se

referă la un anumit număr de elemente, ci la o anumită condiţie (egalitatea a 2 elemente: unul din AL şi unul din şir). Astfel, vor interveni flagurile, mai exact

ZF care se setează doar în momentul când cei 2 operanzi ce se compară sunt egali.

Fără instrucţiuni pe şiruri Cu instrucţiuni pe şiruri

org 100h ; p9_06_a

.data

sirCar db 'Programare in limbaj asm'

lung equ $-sirCar ; lungimea şirului

car db 's' ; caracterul de cautat;

mesA db "caracterul a fost gasit", '$'

mesF db "caracterul NU a fost gasit", '$'

.code

mov SI, offset sirCar

mov CL, lung

mov AL, car

; caracterul de căutat este în AL

repeta: cmp AL, [SI]

je gasit

inc SI ; trece la următorul

loop repeta ; caută până la sfârşit

mov DX, offset mesF

jmp afis

gasit: mov DX, offset mesA

afis: mov AH,09h ; afişare mesaj

int 21h

ret

org 100h ; p9_06_b

.data

sirCar db 'Programare in limbaj asm'

lung equ $-sirCar ; lungimea şirului

car db 's' ; caracterul de cautat;

mesA db "caracterul a fost gasit", '$'

mesF db "caracterul NU a fost gasit", '$'

.code

cld ; DF=0

mov DI, offset sirCar

mov CL, lung

mov AL, car

; caracterul de căutat este în AL

repeta: scasb ; scasb foloseşte DI

je gasit ; sau jz

; inc DI ; se realiz. automat.

loop repeta ; caută până la sfârşit

mov DX, offset mesF

jmp afis

gasit: mov DX, offset mesA

afis: mov AH,09h ; afişare mesaj

int 21h

ret

Figura 9-5. Afişarea mesajului la problema PR7-6 pentru caracterul căutat ‚s’

PR9-7. Să se scrie o secvenţă de program prin care să se înlocuiască elementele nule dintr-un șir cu caracterul '*'.

Exemplu: sir : 1, 2, 0, 5, 8, 0, 10, 12, 0 => sir: 1, 2, '*', 5, 8, '*', 10, 12,'*' Rezolvare:

Se pune 0 în registrul AL și se compară elementele șirului cu AL, prin scasb.

org 100h ; p9_07

.data

sir db 1, 2, 0, 5, 8, 0, 10, 12, 0

lung equ $-sir

Page 15: LAB 9. Instrucţiuni de manipulare a șirurilor

.code

cld

mov DI, offset sir

mov AL, 0

mov CX, lung

iar: scasb

jne et1

mov ES:[DI-1], '*' ; dacă am găsit un element egal cu 0, se înlocuieşte

et1: loop iar

PR9-8. Să se scrie o secvenţă de program prin care să se indice dacă un şir de 8 elemente conţine un subşir de 3 elemente.

Exemplu: SIR: 1,2,3,4,5,6,7,8

SUBSIR: 4,5,6 => SIR contine SUBSIR (var=1)

SUBSIR: 4,6,8 => SIR NU contine SUBSIR (var=0)

Rezolvare: Se caută mereu câte 3 elemente ale subşirului în şirul iniţial, începând de la poziţia dată de registrul BX (BX=0,1,2...5). Dacă se găsesc toate

cele 3 elemente, căutarea se opreşte; dacă nu, algoritmul continuă în următoarea fereastră de căutare (se compară cât timp acestea sunt egale).

org 100h ; p9_08

.data

sir db 1,2,3,4,5,6,7,8

lung equ $-sir

subsir db 4,5,8

var db 0

.code

cld

mov BX,0

iar: mov CX,3 ; se realizează 3 comparări cu elem. subşirului

mov SI, offset sir

add SI, BX ; compararea începe în şir de la poziţia SI+BX

mov DI,offset subsir

repe cmpsb ; se compară elementele din şir cu elem. din subşir

jne et1 ; dacă elem. sunt diferite, trece la următ. fereastră de căutare

mov var,1 ; aici s-au găsit în şirul iniţial toate elementele din subşir

jmp sfarsit ; iese din program

et1: inc BX ; trece la următoarea fereastră de căutare

cmp BX, lung-3 ; se verifică dacă s-a ajuns la capăt

jle iar ; dacă nu, se reia căutarea

sfarsit: ret

Page 16: LAB 9. Instrucţiuni de manipulare a șirurilor

Figura 9-6. Rezultatele obţinute la problema PR9-8

PR9-9. Se dau 2 şiruri de câte 8 elemente, reprezentate pe octet, în segmentul de date. Să se determine câte elemente din şirul 2 nu se regăsesc în şirul

1.

Rezolvare: Se ia pe rând câte un elem. din şirul S2. Acesta se compară cu toate elementele din şirul S1; dacă acesta nu se găseşte în şirul S1, se

contabilizează într-un contor. Dacă acesta a fost găsit, se trece la următorul element din şirul S2. Pentru implementare, elementul din şirul S2 se depune în

registrul AL, iar apoi se compară cu elementele din şirul S1 prin instucţiunea scasb cu prefixul de repetare repne (astfel compararea cu elementele din sirul

S1 decurge automat, cat timp elementele sunt diferite);

Instrucţiunea prefixată repne scasb se opreşte:

(a) fie atunci când elementul din AL s-a găsit în şirul S1,

(b) fie atunci când am ajuns la sfârsitul şirului S1, fără a găsi elementul din AL;

- în cazul (a), se trece la următorul element din şirul S2, care se depune în AL;

- în cazul (b), se contabilizează elementul găsit.

org 100h ; p9_09

.data

s1 db 1,2,3,4,5,6,7,8

lung equ $-s1

s2 db 1,9,12,4,7,0,10,8

nr db 0 ; aici se vor contabiliza elementele din s2 care nu apar în s1

.code

mov CX, lung

mov SI, offset s2 ; sursa

iar: mov DI,offset s1 ; destinaţia

lodsb ; se încarcă elementul din s1 în reg. AL

push CX ; se salvează CX din ciclul loop, pentru a putea

; face comparările dintre elem. din AL si elem. şirului s1

mov CX, lung ; se vor face maxim lung comparări

repne scasb ; se compară elem. din AL cu toate elem. din s1,

; (cât timp elem. sunt diferite)

je next ; elem. din AL a fost gasit in sirul s1; nu il contabilizăm

inc nr ; aici: dacă toate elem. din s1 au fost diferite de elem. din AL

; s-a contabilizat nr de elem. în variabila nr

next: pop cx ; se reface CX din cadrul buclei loop

loop iar ; se trece la următorul element din şirul s2

Page 17: LAB 9. Instrucţiuni de manipulare a șirurilor

PR9-10. Se dau două șiruri de câte 8 elemente pe octet (cu semn) în segmentul de date. Să se compare cele două șiruri element cu element, iar valoare

maximă de la fiecare comparare să se pună într-un al treilea șir.

Exemplu: SIR1: 1,5,7,20,...

SIR2: 2,3,9,10,.... => SIR3: 2,5,9,20,... Rezolvare:

Fără instrucţiuni pe şiruri Cu instrucţiuni pe şiruri

org 100h ; p9_10_a

.data

sir1 db 1, 5, 7, 20, 8, 32, 7, 21

lung equ $-sir1

sir2 db 2, 3, 9, 10, 20, 5, 13, 72

sir3 db lung dup(0)

.code

mov SI, 0

mov CX, lung

start:

mov AL, sir1[SI]

mov BL, sir2[SI]

cmp AL, BL

jl et1

; AL > BL; se pune val. din AL în șir3:

mov sir3[SI], AL

jmp et2

et1:

; AL < BL; se pune val. din BL în șir3:

mov sir3[SI], BL

et2: inc SI

loop start

org 100h ; p9_10_b

.data

sir1 db 1, 5, 7, 20, 8, 32, 7, 21

lung equ $-sir1

sir2 db 2, 3, 9, 10, 20, 5, 13, 72

sir3 db lung dup(0)

.code

lea SI, sir1

lea di, sir2

mov CX, lung

lea BX, sir3

cld

start:

cmpsb

jl et1

; AL > BL; se pune val. din AL în șir3:

mov AL, [SI-1]

mov [BX], AL

jmp et2

et1:

; AL < BL; se pune val. din BL în șir3:

mov AL, [DI-1]

mov [BX], AL

et2: inc BX

loop start

Page 18: LAB 9. Instrucţiuni de manipulare a șirurilor

PR9-11. Se dă un şir de 4 dublucuvinte în memorie. Să se scrie o secvenţă de program prin care să se adune octeţii de rang 2 ai acestor dubluvinte.

Exemplu: sir: 01234567h, 89ABCDEFh, 13579BDFh, 02468ACEh

se va aduna 23h + 0ABh + 57h + 46h = 016Bh Rezolvare:

org 100h ; p9_11

.data

sir dd 01234567h, 89ABCDEFh, 13579BDFh, 02468ACEh

nrElem equ ($-sir)/4

suma dw ?

.code

mov BX, 0 ; suma se va depune temporar în BX

lea SI, sir

mov CX, nrElem

iar: lodsw ; se preiau octeţii 1,0 din fiecare dublucuv

lodsb ; se preia octetul 2

mov AH, 0

add BX, AX ; se adună la BL cu tot cu eventuala depăşire

lodsb ; se preia şi octetul 3, dar nu se face nimic cu el

loop iar

mov suma, BX

ret

Figura 9-7. Rezultatele obţinute la problema PR9-11