CATEGORII DOCUMENTE |
Instructiuni de lucru cu siruri
In multe aplicatii este necesar sa se transfere siruri de date dintr-o zona de memorie in alta. Desi acest lucru este posibil folosind instructiuni MOV si adresari adecvate la memorie, s-au prevazut si instructiuni speciale in acest scop, care permit o viteza superioara, fiind recomandate in majoritatea situatiilor de acest gen.
Pentru aceste instructiuni s-au prevazut doua registre index: SI si DI - Source Index, respectiv Destination Index. Aceste registre contin adresele efective implicate in transfer, si se modifica automat, incrementandu-se sau decrementandu-se, cu 1 , cu 2, sau cu 4, la fiecare instructiune de acest tip. Transferul se poate face pe 8 biti, pe 16 biti , sau pe 32 biti (de la I-386 in sus - vezi Anexa 1). Sunt prezentate aici doar transferuri pe 8 si pe 16 biti.
Sirul sursa are adresa efectiva continuta in registrul index sursa SI si se afla in segmentul de date (cu adresa de segment in DS).
Sirul destinatie are adresa efectiva continuta in registrul index destinatie DI si se afla in extrasegment (cu adresa de segment in ES).
Sensul parcurgerii sirurilor este dat de flagul DF - Direction Flag, fiind crescator daca DF=0 si descrescator daca DF=1.
La utilizarea repetata a unor astfel de instructiuni este recomandabila folosirea prefixului REP in loc de utilizarea unei bucle clasice.
1. Instructiunile LODSB, LODSW, STOSB, STOSW
Mnemonic: LODSB - Incarca de la DS:SI in AL.
Actiune: AL←[SI].
SI←SI +1 daca DF=0, SI←SI-1 daca DF=1.
Mnemonic: LODSW - Incarca de la DS:SI in AX.
Actiune: AL←[SI].
AH←[SI+1].
SI←SI +2 daca DF=0, SI←SI-2 daca DF=1.
Mnemonic: STOSB - Incarca AL la ES:DI .
Actiune: [SI]←AL.
SI←SI +1 daca DF=0, SI←SI-1 daca DF=1.
Mnemonic: STOSW - Incarca AL la ES:DI.
Actiune: [SI]←AL.
[SI+1]←AH.
SI←SI +2 daca DF=0, SI←SI-2 daca DF=1.
Pentru instructiunile de transfer LODSB si LODSW, sursa este locatia de memorie cu adresa efectiva data de registrul index sursa SI si adresa de segment data de DS.
Pentru instructiunile de transfer STOSB si STOSW, destinatia este locatia de memorie cu adresa efectiva data de registrul index destinatie DI si adresa de segment data de ES.
In urma efectuarii unei astfel de instructiuni, registrul index SI respectiv DI se modifica in functie de starea flagului DF (de directie). Daca DF este 0, registrul index va fi incrementat cu 1 la LODSB si STOSB si cu 2 la LODSW si STOSW. Daca DF este 1, registrul index va fi decrementat cu 1, respectiv cu 2.
Registrul general implicit este AL la transferul de un octet si AX la transferul de doi octeti.
In exemplul urmator se arata utilizarea unor astfel de instructiuni la copierea unui bloc dintr-o zona memorie in alta.
Exemplul 1:
.radix 16
.model small
.stack 100h
LungimeBloc equ 30
.DATA
BlocSursa db 40 dup(56)
BlocDest db 40 dup(?)
.code
start:
mov ax,seg BlocSursa ;Se putea folosi si mov ;ax,@data
mov ds,ax ;Segmentul sursa in DS
mov ax,seg BlocDest ;Necesar numai daca ;blocurile sunt in ;segmente diferite
mov es,ax ;Segmentul destinatie ES
cld ;directia in sensul ;cresterii adreselor
mov si, offset BlocSursa ;AE a sursei in SI
mov di, offset BlocDest ;AE a destinatiei in DI
mov cx, LungimeBloc ;Numarul de transferuri in CX
bucla:
lodsb ;Incarca in AL un octet
stosb ;si il trimite la destinatie
loop bucla ;Decrementeaza CX si reia ;bucla pana cand CX devine 0
term:
jmp term
end start
Modul de lucru:
P 1 Sa se initializeze un bloc de 20h de cuvinte de forma 1122h in memorie incepand de la adresa 0 din segmentul de date si sa se copieze acest bloc intr-o zona incepand de la adresa 60h din segmentul de date.
Observatie: Reamintim ca dupa incarcarea lui DS, zona de memorie afisata in fereastra DUMP va fi cea a segmentului ES. Pentru a vedea segmentul de date, se da comanda Dump din submeniul View, avand activa fereastra CPU.
2 Instructiunile MOVSB si MOVSW
Aceste instructiuni combina instructiunile LODSB si STOSB, respectiv LODSW si STOSW, fara a afecta AL sau AX.
Mnemonic: MOVSB - Muta un octet de la adresa DS:SI la adresa ES:DI.
Actiune: [DS]←[SI].
SI←SI +1 daca DF=0, SI←SI-1 daca DF=1.
DI←DI +1 daca DF=0, DI←DI-1 daca DF=1.
Mnemonic: MOVSW - Muta un cuvant de la adresa DS:SI la adresa ES:DI
Actiune: [DI]←[SI].
[DI+1]←[SI+1].
SI←SI +2 daca DF=0, SI←SI-2 daca DF=1.
DI←DI +2 daca DF=0, DI←DI-2 daca DF=1.
Exemplul 2:
In exemplul 1 se pot inlocui instructiunile LODSB si LODSW cu MOVSB ca in secventa:
.
.
.
bucla:
movsb ;Un octet din blocul sursa
;este trimis la destinatie
loop bucla ;Decrementeaza CX si sare la ;eticheta 'Bucla' pana cand CX ajunge la 0
term:
jmp term
end start
Instructiunile MOVSB si MOVSW admit prefix de repetare, REP. In felul acesta instructiunea precedata de REP este executata de atatea ori cat se afla in registrul CX (maxim 65536 ori).
Acealsi exemplu poate avea partea finala scrisa in felul urmator:
Exemplul 3:
.
.
.
bucla:
REP movsb ;un numar de octeti egal cu ;continutul registrului CX sunt cititi ;din blocul sursa si trimisi la destinatie
term:
jmp term
end start
P 2 Sa se modifice programul de la punctul 6.1 pentru a folosi prefixul REP si instructiuni care sa nu afecteze continutul lui AX .
3 Instructiunile pentru analiza continutului sirurilor, SCASB si SCASW
Mnemonic: SCASB - Compara continutul registrului AL cu continutul locatiei ES:DI si pozitioneaza corespunzator flagurile.
Actiune: AL - [ES:DI].
Mnemonic: SCASW - Compara continutul registrului AX cu continutul locatiei ES:DI si ES:DI+1 si pozitioneaza corespunzator flagurile.
Actiune: AL - [ES:DI].
AH - [ES:DI+1].
Instructiunea SCASB compara octetul din locatia de memorie cu adresa ES:DI cu continutul lui AL si pozitioneaza indicatorii de conditii in functie de rezultatul compararii. Registrul DI va fi incrementat cu 1.
Instructiunea SCASW compara cuvantul punctat de locatia de memorie cu adresa ES:DI (octetul inferior fiind la aceasta adresa, iar cel superior la cea urmatoare), cu continutul lui AX si pozitioneaza indicatorii de conditii in functie de rezultatul compararii.Registrul DI va fi incrementat cu 2.
In conformitate cu regulile aritmeticii in complement fata de 2 (numerele negative au bitul cel mai semnificativ 1 iar scaderea cu rezultat negativ da un imprumut) , daca numarul din memorie este mai mic decat cel din registru, indicatorii C (transport la adunare si imprumut la scadere) si S (semn) se pozitioneaza in 1 . Daca numarul din memorie este mai mare decat cel din cu cel din registru, indicatorii C si S se pozitioneaza in 0. Daca numarul din memorie este egal cu cel din registru, se pozitioneaza in 1 indicatorul Z.
Exemplul 4
Programul prezentat in continuare efectueaza urmatoarele:
- Declara un sir de 15 octeti cu numere intregi crescatoare de la 1 la 5;
- Incarca in AL constanta 04;
- Numara de cate ori apare aceasta constanta in sir (compara pe rand continutul lui AL cu fiecare din locatiile sirului declarat si incrementeaza BH de cate ori este gasita constanta respectiva).
.radix 16
.model small
.stack 100h
.DATA
BlocSursa db 3 dup(1,2,3,4,5)
LB equ $-BlocSursa ;Asamblorul ;calculeaza lungimea blocului
.code
start:
mov ax,@data
mov ds,ax
mov es,ax ;Incarca in ES segmentul de ;date (pentru SCASB)
mov di, offset BlocSursa ;Incarca in DI adresa ;sirului(Pentru SCASB)
mov cx, LB ;In CX lungimea sirului
mov al,4 ;Constanta de comparat
mov bh,0 ;Valoare initiala contor
bucla:
scasb ;Compara AL cu un octetul de ;la [ES:DI] din sir
jnz conti ;Daca nu e egalitate sare
inc bh ;Daca e 4, incrementeaza BH
conti:
loop bucla ;Reluare daca nu s-a terminat
term:
jmp term
end start
Observatii:
- Instructiunea MOV DS,AX nu este necesara decat pentru a putea vizualiza in TD sirul declarat in memorie (cand fereastra CPU este activata, cu View-> Dump). Totusi, daca nu se introduce aceasta instructiune, prima instructiune din bucla va trebui scrisa in forma MOV BL,ES:[DI]pentru a se citi din segmentul de date.
-Nici instructiunea de incarcare in BL a octetului ce se compara nu este in mod normal necesara (daca o folosim, s-ar putea face comparatia fara SCASB). Aici ea a fost introdusa in scop didactic, pentru a putea vizualiza in fiecare moment termenii de comparat.
-Simbolul LB a fost introdus pentru a putea calcula automat lungimea blocului. Simbolul $ in limbaj de asamblare desemneaza adresa curenta.
-Daca era cunoscuta lungimea blocului, ea se putea declara explicit (de exemplu LB equ 0F
Modul de lucru
P 3 Se va rula pas cu pas programul din exemplul 6.3 si se va observa la fiecare comparatie eventuala schimbare a indicatorilor de conditii
P 4 Se va modifica programul de mai sus pentru a introduce un sir de cel putin 20 de caratere oarecare si a contoriza in BH numarul de aparitii ale caracterului 'a'.
Indicatie: Caracterele sau sirurile de caractere se scriu intre apstroafe, de exemplu: 'ghafs3yDGfa'.
P 5 Se va modifica programul de mai sus pentru a contoriza in BH numarul de aparitii ale unui subsirului 'fa' in sirul 'ghfafasfasfahsyfhhhsaad'.
Indicatii:
- In final, va trebui sa avem BH=4;
- Se va folosi instructiunea de comparatie SCASW, deci in AX va trebui incarcat subsirul 'af', (caracterele s-au inversat conform conventiei 'little-endian'- v. lucrarea de laborator 3);
- Instructiunea SCASW va incrementa DI cu 2, deci s-ar putea pierde subsirul care incepe de la o pozitie para (caracterele 8 si 9). Pentru a se cauta din unu in unu, imediat inainte de ultima instructiune a buclei se va decrementa DI cu 1, pentru a se compensa saltul de 2 al DI.
4. Instructiunile de comparare siruri CMPSB si CMPSW
Mnemonic: CMPSB - Compara continutul locatiei DS:SI cu continutul locatiei ES:DI si pozitioneaza corespunzator flagurile.
Actiune: [DS:SI] - [ES:DI]
SI←SI +1 daca DF=0, SI←SI-1 daca DF=1
DI←DI +1 daca DF=0, DI←DI-1 daca DF=1
Mnemonic: CMPSW - Compara continutul locatiilor DS:SI si DS:SI+1 cu continutul locatiilor ES:DI si ES:DI+1 si pozitioneaza corespunzator flagurile.
Actiune: [DS:SI] - [ES:DI]
[DS:SI+1] - [ES:DI+1]
SI←SI +2 daca DF=0, SI←SI-2 daca DF=1
DI←DI +2 daca DF=0, DI←DI-2 daca DF=1
Pentru instructiunea de comparatie CMPSB primul operand este locatia de memorie cu adresa efectiva data de registrul index sursa SI si adresa de segment data de DS iar al doilea operand este locatia de memorie cu adresa efectiva data de registrul index destinatie DI si adresa de segment data de ES.
Pentru instructiunea de comparatie CMPSW primul operand este dat de locatiile de memorie cu adresele DS:SI (octetul inferior) si DS:SI+1 (octetul superior) iar al doilea operand este dat de locatiile de memorie cu adresele ES:DI (octetul inferior) si ES:DI+1 (octetul superior).
In urma efectuarii unei astfel de instructiuni, registrele index SI respectiv DI se modifica in functie de starea flagului DF (de directie). Daca DF este 0, registrele index vor fi incrementate cu 1 la CMPSB si cu 2 la CMPSW. Daca DF este 1, registrele index vor fi decrementate cu 1, respectiv cu 2.
In exemplul urmator se arata utilizarea unor astfel de instructiuni la compararea a doua zone de memorie. Programul numara in BH cazurile de coincidenta a unui caracter dintr-un sir cu caracterul din aceeasi pozitie din al doilea sir.
Exemplul 5
.radix 16
.model small
.stack 100h
.DATA
Sir1 db 'ghfafasfasfahsyfhhhsaad'
LB equ $-Sir1 ;Lungimea este data de sirul 1
Sir2 db 'ahgfasgfasjkhajhasdjgdd'
.code
start:
mov ax,@data
mov ds,ax ;Incarca in DS segmentul de date
mov es,ax ;Incarca in ES segmentul de date
mov si, offset Sir1;Incarca in SI adresa sirului 1
mov di, offset Sir2;Incarca in DI adresa sirului 2
mov cx,LB ;Contorul de comparatii in CX
bucla:
mov dl,[si] ;Aduce in DL octetul din sirul 1
mov dh,[di] ;si in DH octetul din sirul 2 ;(instructiuni in scop didactic,
permit vizualizarea elementelor)
cmpsb ;Compara AL cu octetul respectiv
jnz b1 ;Daca nu este egalitate, se sare
inc bh ;Daca s-a gasit egalitate, se ;incrementeaza BH
b1: loop bucla ;Reluare daca nu s-a terminat ;sirul 1
term:
jmp term
end start
Modul de lucru
P 6 Se va rula pas cu pas programul din exemplul 6.4 si se va urmari cum se modifica registrele si indicatorii de conditii la fiecare comparatie.
P 7 Se va modifica programul anterior introducandu-se doua siruri de caractere numerice: '6512631827961792' si '7531790734264725'. In BH se va contoriza de cate ori cifrele omoloage coincid, in DL de cate ori cifra din primul sir este mai mica decat cea din al doilea sir, iar in DH de cate ori cifra din primul sir este mai mare decat cea din al doilea sir.
5 Prefixele REPE, REPZ, REPNE si REPNZ
Instructiunile de comparatie SCASB, SCASW, CMPSB si CMPSW pot fi precedate de prefixele REPE ( echivalent cu REPZ) si REPNE (echivalent cu REPNZ) care cer procesorului sa repete instructiunea pe care o preced pana cand CX devine 0 (prin decrementare automata), sau pana cand este gasita relatia de ordine specificata de prefixul respectiv.
Astfel, pentru:
REPE si REPZ - repeta atat timp cat termenii comparatiei sunt egali (pana cand apare o diferenta);
REPNE si REPNZ- repeta atata timp cat termenii comparatiei nu sunt egali (pana cand apare o situatie de egalitate).
Modul de lucru
Se vor folosi prefixe de repetare pentru urmatoarele programe:
P 8 Sa se scrie un program care sa indice in BH pozitia (numarul de ordine) in sirul 'ABCDEFGHIJKL' al caracterului 'E'.
P 9 Sa se scrie un program care sa indice in BH numarul de ordine al primelor elemente egale in sirurile: '123456789' si '987654321'.
P 10 Sa se scrie un program care sa indice in BH numarul de ordine al primelor elemente omoloage diferite din sirurile '112233445566' si 112244335566'.
Politica de confidentialitate | Termeni si conditii de utilizare |
Vizualizari: 2020
Importanta:
Termeni si conditii de utilizare | Contact
© SCRIGROUP 2024 . All rights reserved