Seminar 3 ASC MIR Operatii pe biti Operatii cu siruri 1. Operatii logice pe biti Sintaxa Efect AND dest, sursă dest = dest AND sursă - operanzii sursă şi destinaţie trebuie să aibă ambii aceeaşi dimensiune (octet sau cuvânt). OR dest, sursă dest = dest OR sursă - operanzii sursă şi destinaţie trebuie să aibă ambii aceeaşi dimensiune (octet sau cuvânt). XOR dest, sursă dest = dest OR sursă - operanzii sursă şi destinaţie trebuie să aibă ambii aceeaşi dimensiune (octet sau cuvânt). NOT sursă sursă = NOT sursă - operandul sursă poate fi de dimensiune octet sau cuvânt Regulile de calcul ale celor patru operaţii pe biţi sunt: AND 0 1 OR 0 1 XOR 0 1 NOT 0 0 0 0 0 1 0 0 1 0 1 1 0 1 1 1 1 1 1 0 1 0 Observatii: Instructiunea AND este indicata pentru izolarea unui anumit bit sau pentru fortarea anumitor biti la valoarea 0. Astfel daca dintr-o configuratie pe 8 biti de forma: a = x x x x x x x x b, se doreste izolarea bitului i (0<=i<=7), se utilizeaza expresia: AND a, 2 i iar daca se doreste fortarea anumitor biti din a la valoarea 0, de exemplu bitii 0, 2 si 3 (restul raman neschimbati), se utilizeaza expresia: AND a, 11110010b. Instructiunea OR poate fi utilizata pentru fortarea anumitor biti la valoarea 1. De exmplu daca se doreste fortarea bitilor 0, 2 si 3 la valoarea 1, se poate utiliza expresia: OR a, 00001101b. Instructiunea XOR este indicata pentru schimbarea valorii unor biti din 0 in 1 sau din 1 in 0. De exemplu, daca dorim ca bitii 4-7 din AL, sa-si schimbe valorile iar ceilalti sa ramana neschimbati, acesta cerinta se poate realiza utilizand expresia: XOR al, 11110000. 2. Instructiuni de deplasare de biti In cadrul octetilor sau cuvintelor, bitii pot fi deplasati sau rotiti, cu una sau mai multe pozitii. Pentru toate operațiile de deplasare pe biți: Destinația poate fi registru pe 1 sau 2 octeți sau o locație de memorie de 1 sau 2 octeți Numărul de poziții pentru deplasare poate fi 1 sau o valoare specificată în registrul CL Pentru fiecare dintre aceste instructiuni, se utilizeaza ca si exemplu, un octet X cu configuratia initiala: X = abcdefgh, unde a - h sunt cifre binare, h este cifra binara de rang 0, a este cifra binara de rang 7, iar k este valoarea existent in CF (CF=k)
2.a. Instructiuni de deplasare logica Instructiunea de deplasare logica la stanga: SHL sursă, n Efect: configuraţia de biţi din sursă este deplasată logic la stânga cu n poziţii. CF conţine ultimul bit deplasat. La dreapta se introduc zero-uri. Exemplu: SHL X,1 ; X=bcdefgh0, CF=a Instructiunea de deplasare logica la dreapta: SHR sursă, n Efect: configuraţia de biţi din sursă este deplasată logic la dreapta cu n poziţii. CF conţine ultimul bit deplasat. La stânga se introduc zero-uri. Exemplu: SHR X,1 ; X=0abcdefg, CF=h 2.b. Instructiuni de deplasare aritmetica Instructiunea de deplasare aritmetica la stanga: SAL sursă, n Efect: configuraţia de biţi din sursă este deplasată aritmetic la stânga cu n poziţii. CF conţine ultimul bit deplasat. La dreapta se introduc zero-uri. (acelasi efect ca si SHL) Exemplu: SAL X,1 ; X=bcdefgh0, CF=a Instructiunea de deplasare aritmetica la dreapta: SAR sursă, n Efect: configuraţia de biţi din sursă este deplasată aritmetic la dreapta cu n poziţii. CF conţine ultimul bit deplasat. La stânga se completează cu bitul de semn. Exemplu: SAR X,1 ; X=aabcdefg, CF=h 3. Instructiuni de rotire a bitilor in cadrul unui operand 3.a. Instructiuni de rotire fara carry Instructiuni de rotire fara carry la stanga: ROL sursă, n Efect: configuraţia de biţi din sursă este rotită spre stânga cu n poziţii. Odata un bit ieșit în stânga, el se adaugă automat în partea dreaptă a destinației. CF conţine ultimul bit rotit. Exemplu: ROL X,1 ; X=bcdefgha, CF=a Instructiuni de rotire fara carry la dreapta: ROR sursă, n Efect: configuraţia de biţi din sursă este rotită spre dreapta cu n poziţii. Odata un bit ieșit în dreapta, el se adaugă automat în partea stângă a destinației. CF conţine ultimul bit rotit. Exemplu: ROR X,1 ; X=habcdefg, CF=h 3.b. Instructiuni de rotire cu carry Instructiuni de rotire cu carry la stanga: RCL sursă, n Efect: configuraţia de biţi din sursă este rotită spre stânga cu n poziţii. Odata un bit ieșit în stânga, el se păstrează în CF. Valoarea anterioară din CF se adaugă automat în partea dreaptă a destinației. Exemplu: RCL X,1 ; X=bcdefghk, CF=a Instructiuni de rotire cu carry la dreapta: RCR sursă, n Efect: configuraţia de biţi din sursă este rotită spre dreapta cu n poziţii. Odata un bit ieșit în dreapta, el se păstrează în CF. Valoarea anterioară din CF se adaugă automat în partea stângă a destinației. Exemplu: RCR X,1 ; X=kabcdefg, CF=h
Problema: ; Se dau cuvintele A si B. Se cere cuvantul C format astfel: ;- bitii 0-2 ai lui C coincid cu bitii 10-12 ai lui B ;- bitii 3-6 ai lui C au valoarea 1 ;- bitii 7-10 ai lui C coincid cu bitii 1-4 ai lui A ;- bitii 11-12 ai valoarea 0 ;- bitii 13-15 ai lui C concid cu inversul bitilor 9-11 ai lui B ; Vom obtine cuvantul C prin operatii succesive de "izolare". Numim operatia de izolare a bitilor 10-12 ai ; lui B, pastrarea intacta a valorii acestor biti, si initializarea cu 0 a celorlalti biti. ; Operatiunea de izolare se realizeaza cu ajutorul operatorului AND intre cuvantul B si masca ; 0001110000000000. Odata bitii izolati, printr-o operatie de rotire se deplaseaza grupul de biti doriti in ; pozitia dorita. Cuvantul final se obtine prin aplicarea operatorului OR intre rezultatele intermediare ; obtinute in urma izolarii si rotirii. ; Observatie: rangul bitilor se numara de la dreapta la stanga assume cs:code, ds:data data segment a dw 0111011101010111b b dw 1001101110111110b c dw? data ends code segment start: mov ax, data ; incarcam adresa segmentului de date in resgistrul ds mov ds, ax mov bx, 0 ; in registrul bx vom calcula rezultatul, deci trebuie initializat!! mov ax, b ; izolam bitii 10-12 ai lui b and ax, 0001110000000000b mov cl, 10 ror ax, cl ; rotim 10 bozitii spre dreapta or bx, ax ; punem bitii in rezultat or bx, 0000000001111000b ; facem biti 3-6 din rezultat sa aiba valoarea 1 mov ax, a ; izolam biti 1-4 ai lui a and ax, 0000000000011110b mov cl, 6 rol ax, cl ; rotim 6 pozitii spre stanga or bx, ax ; punem bitii in rezultat and bx, 1110011111111111b ; facem biti 11-12 din rezultat sa aiba valoarea 0 mov ax, b not ax ; inversam valaorea lui b and ax, 0000111000000000b ; izolam biti 9-11 ai lui b
mov cl, 4 rol ax, cl ; deplasam biti 4 pozitii spre stanga or bx, ax ; punem biti in rezultat mov c, bx ; punem valoarea din registru in variabila rezultat mov ax, 4c00h ; terminam programul int 21h code ends end start Seminar 3 - partea II Operatii cu siruri Caracterizarea unui sir in limbajul de asamblare 8086 consta intr-o insiruire de octeti (byte), cuvinte (word) sau dublucuvinte (doubleword). Pentru fiecare sir, trebuie sa avem in vedere urmatoarele aspecte: Tipul elementelor Adresa primului element din sir Lungimea sirului (numarul de elemente din sirul respectiv) Directia de parcurgere a sirului: stanga la dreapta adresa mica spre adresa mare dreapta la stanga adresa mare spre adresa mica a. Instrucţiuni de comparare CMP dest, sursă comparaţie între valorile operanzilor, fără a modifica valorile acestora. efectuează practic o operaţie fictivă de scădere dest-sursă şi setează corespunzător flag-urile. TEST dest, sursă efectuează fictiv operația dest AND sursă şi setează corespunzător flag-urile. b. Instrucţiuni de salt Instrucţiune de salt necondiţionat JMP operand salt necondiţionat la adresa determinată de operand. Operand poate sa fie o eticheta, un registru sau o variabila de memorie ce contine o adresa. Efectul ei este transferul neconditionat al controlului la instructiunea ce urmeaza etichetei, la adresa continuta in registru, respectiv la adresa continuta in variabila de memorie. Instrucţiuni de salt condiţionat Instructiunile de salt conditionat ofera posibilitatea de a lua decizii in cadrul unui program. Elementele care conditioneaza acest tip de salt sunt valorile flagurilor si continutul registrului CX. Cand se compara doua numere: cu semn se folosesc termenii less than (mai mic decat) si greather than (mai mare decat), fara semn, se folosesc termenii below (inferior, sub), si respectiv above (superior, deasupra, peste).
Instrucţiunile de salt prezentate în continuare sunt condiţionate de valorile anumitor flag-uri şi au ca efect salt la adresa determinată de operand. Sintaxa generala este: [instructiune_de_salt] eticheta Semnificatia instructiunilor de salt conditionat este data sub forma: salt daca operand1 (op1) <<relatie>> fata de operand2 (op2). În general, setarea flag-urilor care sunt verificate are loc în urma unei operaţii CMP sau TEST. Instruction Jump if... Condition JB JNAE JC JAE JNB JNC JBE JNA JA JNBE JE JZ JNE JNZ JL JNGE JGE JNL JLE JNG JG JNLE JP JPE JNP JPO below not above or equal carry above or equal not below no carry below or equal not above above not below or equal is equal Is zero not equal not zero less than not greater or equal greater or equal not less than less than not greater than greater than not less than parity even parity not parity odd parity CF=1 CF=0 CF=1 or ZF=1 CF=0 and ZF=0 ZF=1 ZF=0 SF OF SF=OF ZF=1 or SF OF ZF=0 and SF=OF PF=1 PF=0 JS negative sign SF=1 JNS no negative sign SF=0 JO overflow OF=1 JNO no overflow OF=0
Obs: În cazul instrucţiunilor JB, JBE, JNB, JNBE, JA, JAE, JNA, JNAE interpretarea comparaţiei este fără semn, iar pentru instrucţiunile JL, JLE, JNL, JNLE, JG, JGE, JNG, JNGE interpretarea comparaţiei are loc cu semn. Instructiuni de ciclare Cu ajutorul instructiunilor de salt conditionat se pot construi cicluri (bucle). Un ciclu nu este altceva decat un bloc de instructiuni care se termina cu o instructiune de salt conditionat. Sintaxa: [instructiune] eticheta Limbajul de asamblare 80x86 prevede instructiuni speciale pentru realizarea ciclarii. Ele sunt: LOOP, LOOPE, LOOPNE si JCXZ Instructiunea LOOP comanda reluarea executiei blocului de instructiuni ce incepe la eticheta, atata timp cat valoarea din registrul CX este diferita de 0. Se efectueaza intai decrementarea registrului CX si apoi se face testul si eventual saltul. Saltul este "scurt" (max. 127 octeti - atentie deci la "distanta" dintre LOOP si eticheta!). Alte observatii: 1. offset-ul variabilei s ne referim la deplasamentul şirului s în cadrul segmentului de memorie în care se află 2. $ reprezintă valoarea contorului de locaţii şi are semnificaţia de valoare curentă a offset-ului (adică câţi octeţi au fost alocaţi de către asamblor până în acest punct al codului generat corespunzător segmentului de date pentru programul nostru. 3. operatorul DUP se foloseşte pentru rezervarea unui bloc de memorie de lungime l prezenţa caracterului? în această declaraţie are ca efect doar rezervarea zonei respective de memorie, fără a o iniţializa cu nici o valoare. Probleme: 1. Se dă un şir de caractere format din litere mici. Să se transforme în literele mari corespunzătoare. Exemplu: Dacă se dă şirul: s db a, v, x, a, c trebuie să se obţină şirul rezultat: d db A, V, X, A, C assume cs:code, ds:data data segment s db a, v, x, a, c ;această declaraţie este echivalentă cu următoarea: ;s db avxac ;efectul celor două instrucţiuni fiind alocarea a câte unui octet pentru ;fiecare caracter din şir, în ordinea în care acestea apar ;când spunem offset-ul variabilei s ne referim la deplasamentul şirului s ;în cadrul segmentului ;de memorie în care se află l EQU $-s
;$ reprezintă valoarea contorului de locaţii şi are semnificaţia de valoare curentă a offset-ului ;(adică câţi octeţi au fost alocaţi de către asamblor până în acest punct al codului generat ;corespunzător segmentului de date pentru programul nostru, în acest moment $=5 pentru că s- ;au alocat 5 octeţi pentru caracterele a v, x, a, c ) scăzând offset-ul lui s din offset-ul curent ;obţinem numărul de octeţi ai şirului s, adică numărul de caractere din şir numărul astfel obţinut ;este reţinut în constanta l se putea folosi şi declaraţia: l db $-s ;în ipoteza că lungimea şirului poate fi memorată într-un octet ;avantajul folosirii directivei EQU ;va putea fi observat în cele ce urmează d db l dup (?) ;alocăm spaţiu pentru şirul rezultat d, care va avea aceeaşi lungime ca şi operatorul DUP se ;foloseşte pentru rezervarea unui bloc de memorie de lungime l ;prezenţa caracterului? în această declaraţie are ca efect doar rezervarea zonei respective de ;memorie, fără a o iniţializa cu nici o ;valoare. Dacă am fi dorit iniţializarea octeţilor din această ;zonă de memorie cu valoarea 0, am fi ;folosit următoarea declaraţie: ; d db l dup (0) ;motivul pentru care putem folosi valoarea lui l în această declaraţie este faptul că atribuirea ;valorii ;constantei l se face în faza de asamblare; în schimb, dacă pentru obţinerea lungimii ;şirului s ar fi ;fost folosită declaraţia: ; l db $-s ;atunci, necunoscându-i-se valoarea la asamblare, l nu ar fi putut să apară în declaraţia: ; d db l dup (?) ;obţinân d la asamblare mesajul de eroare Expecting scalar type ;o altă diferenţă între cele două variante prezentate este faptul că directiva EQU nu provoacă ;generare de octeţi, deci practic constantei l nu i se alocă spaţiu în segmentul de date. În schimb, ;dacă folosim directiva db pentru l, se va genera un octet. data ends code segment start: mov ax, data mov ds, ax mov cx, l mov si, 0 ;pregătim în registrul cx lungimea şirului s, deoarece vom folosi ;instrucţiunea loop pentru execuţia repetată a unui set de instrucţiuni ;registrul si va fi folosit ca şi index în cele două şiruri jcxz Sfarsit ;vom folosi instrucţiunea loop, care execută o buclă de cx ori, motiv pentru care ne ;asigurăm că valoarea din cx nu este 0 înaintea intrării în buclă, caz în care bucla s-ar ;executa de 65535 ori (deoarece are loc întâi ;decrementarea 0-1 = -1 = 65535 şi apoi ;testul) Repeta: mov al, byte ptr s[si] ;în al se copiază octetul care se află în segmentul de ;date la offset-ul lui s plus si octeţi; ;obţinem astfel ;octetul de rang si din şir, unde primul octet are rangul 0 ;în acest moment, în al avem codul ASCII al unei litere mici din şirul sursă s ;datorită tipului byte al variabilei s, este corectă şi folosirea instrucţiunii: mov al, s[si] ;dacă am fi avut un şir de cuvinte, declarat astfel: ; sw dw a, v, x, a, c ;atunci instrucţiunea: ; mov al, s[si] ;ar fi constituit o eroare sintactică, generând apariţia mesajului de eroare Operand types ;do not match, datorită faptului că al este octet iar s este cuvânt ;corectă în acest caz ar fi fost folosirea instrucţiunii: ; mov al, byte ptr s[si] ;care ar fi avut ca şi efect încărcarea în al a celui mai puţin semnificativ octet din cuvântul ;de la offset-ul s+si
sub al, a - A ;pentru a obţine litera mare corespunzătoare literei mici al ;cărei cod ASCII se află în al, vom scădea din codul ASCII ;al literei mici diferenţa a - A (diferenţa dintre codul ;ASCII al caracterului a şi codul ASCII al caracterului ; A ), care este chiar diferenţa între ;codul ASCII al oricărei ;litere mici şi codul ASCII al literei mari corespunzătoare ei mov byte ptr d[si], al ;litera mare astfel obţinută o reţinem în şirul destinaţie d, pe aceeaşi poziţie si pe care se ;află litera mică ;în şirul sursă s ;este corectă şi folosirea instrucţiunii: ; mov d[si], al ;din aceleaşi motive explicate mai sus inc si ;trecem la următorul octet din şir loop Repeta Sfarsit: ;terminarea programului mov ax, 4C00h int 21h code ends end start --------------------------------------------------------------------------------------------------------- 2. Se da un sir de octeti S. Sa se determine maximul elementelor de pe ;pozitiile pare si minimul elementelor de pe pozitiile impare din S. ;Exemplu: ;S: 1, 4, 2, 3, 8, 4, 9, 5 ;max_poz_pare: 9 ;min_poz_impare: 3(in document era scris 5) assume ds: data, cs: code data segment s db 1, 4, 2, 3, 8, 4, 9, 5 ;declaram sirul s l equ $-s ;lungimea sirului s min db? ;min si max vor contine rezultatele max db? data ends code segment start: mov ax, data mov ds, ax mov al, 255 mov bl, 0 mov cx, l mov si, 0 jcxz Sfarsit ;valoarea minimului se va calcula in al ;valoarea maximului se va calcula in bl ;cx = lungimea sirului(l) ;si = indexul primului element
Repeta: test si, 1 ;daca indexul este par, ZF = 1 jz Par ;daca si impar cmp al, s[si] ;comparam minimul cu nr.din sir jnae Increm ;daca minimul e mai mic, trecem la urmatorul nr din sir mov al, s[si] ;altfel schimbam valoarea minimului(al) jmp Increm Par: ;daca si par cmp bl, s[si] ;comparam maximul cu nr din sir jnbe Increm ;daca maximul e mai mare ca nr, mergem la urmatorul nr din sir mov bl, s[si] ;altfel schimbam val maximului(bl) Increm: inc si loop Repeta Sfarsit: mov min, al mov max, bl ;punem rezultatele in min si max mov ax, 4c00h int 21h code ends end start -------------------------------------------------------------------------------------------------- Tema. Se dau doua siruri de octeti S1 si S2 de aceeasi lungime. Sa se obtina sirul D prin intercalarea elementelor celor doua siruri. ;Exemplu: ;S1: 1, 3, 5, 7 ;S2: 2, 6, 9, 4 ;D: 1, 2, 3, 6, 5, 9, 7, 4