Scrigroup - Documente si articole

     

HomeDocumenteUploadResurseAlte limbi doc
AccessAdobe photoshopAlgoritmiAutocadBaze de dateC
C sharpCalculatoareCorel drawDot netExcelFox pro
FrontpageHardwareHtmlInternetJavaLinux
MatlabMs dosPascalPhpPower pointRetele calculatoare
SqlTutorialsWebdesignWindowsWordXml

Instructiuni aritmetice si logice

calculatoare



+ Font mai mare | - Font mai mic



Instructiuni aritmetice si logice

A doua categorie importanta de instructiuni o constituie instructiunile aritmetice si logice. Rezultatul operatiei este totdeauna depus intr-unul din operanzi. La instructiunile cu doi operanzi, rezultatul este depus in primul operand. Instructiunile modifica flagurile CF, AF, ZF, SF, PF si OF, motiv pentru care acestea mai sunt numite si flaguri aritmetice.



1 Semnificatia flagurilor aritmetice

Flagul Carry = 1 semnifica un transport / imprumut din / in bitul cel mai semnificativ (b.c.m.s.) al rezultatului, unde b.c.m.s. poate fi bitul 7 sau bitul 15. Interpretarea acestui transport sau imprumut este cea de depasire la operatiile de adunare / scadere cu operanzi fara semn.

. Flagui Auxiliarry Carry = 1 semnifica un transport / imprumut din / in bitul 4 al rezultatului, fiind utilizat la operatiile cu numere BCD.

. Fiagul Zero este 1 daca rezultatul operatiei este nul.

. Flagul Sign este 1 daca bitul de semn al rezultatului (bitul 7 sau 15) este 1.

. Flagul Parity este 1 daca suma modulo 2 a celor 8 biti mai putin semnificativi ai rezultatului este 0.

. Flagul Overflow este 1 daca operatia a condus la un transport inspre b.c.m.s., dar nu din b.c.m.s. al rezultatului, sau invers. Altfel, OF se pozitioneaza la zero. Similar, in cazul imprumutului: OF = 1 daca a avut loc un imprumut dinspre b.c.m.s., dar nu din exterior, sau invers. Situatiile descrise sunt ilustrate in Figura

Interpretarea flagului OF este aceea de depasire la operatiile de adunare / scadere cu operanzi cu semn.

Sa consideram valoarea pe 1 octet 0FFH si sa adunam 1 la aceasta valoare. Rezultatul este 0 si transport atat din bitul 7, cat si din bitul 6 in bitul 7. Astfel, CF = 1 si OF = 0. Considerand operanzii fara semn (255 si 1), adunarea lor provoaca depasire, ceea ce corespunde cu CF = 1. Daca se considera operanzii cu semn, (-1 si 1), adunarea lor nu provoaca depasire si OF = 0.

Sa consideram, in mod similar, valorile 70H si 10H si suma acestora. Rezultatul este 80H si nu apare transport din bitul 7, dar este transport din bitul 6 in bitul 7. Ca atare, CF = 0 si OF = 1. In interpretarea fara semn, valorile operanzilor sunt 112 si 16, suma lor fiind 128, deci nu apare depasire (CF = 0). In interpretarea cu semn, valorile sunt tot 112 si 16, dar suma lor depaseste domeniul admisibil al octetilor cu semn si OF = 1.

Figura 2.2 Pozitionarea bistabilului Overflow

In fine, sa consideram operanzii 0FDH si 02H si suma lor. La adunare, se obtine valoarea 0FFH si nu apare transport nici din bitul 7, nici din bitul 6. Ca atare, CF = 0 si OF = 0. Valorile fara semn sunt 253 si 2, iar suma lor (255) este in domeniul admisibil, deci CF = 0. Valorile cu semn sunt -3 si 2, iar suma lor (-1) este in domeniul de reprezentare al numerelor cu semn, deci OF = 0.

La fiecare instructiune aritmetica sau logica, se vor preciza explicit flagurile afectate, adica flagurile care se pozitioneaza conform rezultatului. Un flag neafectat ramane la vechea valoare. Exista si situatii in care unele flaguri au valori nedefinite.

2 Instructiuni specifice adunarii (ADD, ADC, INC, DAA, AAA)

Instructiunea ADD (Add - Aduna)

Are forma generala:

ADD destinatie, sursa

in care destinatie poate fi un registru general sau o locatie de memorie, iar sursa poate fi un registru general, o locatie de memorie sau o valoare imediata. Cei doi operanzi nu pot fi simultan locatii de memorie. Semnificatia este:

(destinatie) <- (destinatie) + (sursa)

Flaguri afectate: AF, CF, PF, SF, ZF, OF (toate).

Operanzii pot fi pe 8 sau 16 biti si trebuie sa aiba aceeasi dimensiune. In caz de ambiguitate in ceea ce priveste lungimea operanzilor, se foloseste operatorul ptr. lata cateva exemple

ADD AX, BX

ADD AX, 1 ; Lungime 16 biti

ADD AL, 1 ; Lungime 8 biti

ADD  word ptr [DI], -1 ; Dest. in memorie, sursa

; imediata

ADD ALFA, 3 ; ALFA este definit cu DW

ADD byte ptr ALFA, 3 ; Fortare instructiune pe octet

Instructiunea ADC (Add with Carry - Aduna cu transport)

Forma generala este:

ADC destinatie, sursa

Formatul este similar cu instructiunea ADD, ceea ce difera fiind adunarea bistabilului CF:

(destinatie) <- (destinatie) + (sursa) + (CF)

Flaguri afectate: AF, CF, PF, SF, ZF, OF (toate).

Adunarea cu Carry se foloseste la adunari de operanzi pe mai multe cuvinte, in care poate aparea un transport intermediar. De exemplu, secventa de adunare a doua numere pe 4 octeti este:

.data

ALFA dd 145A789FH

BETA dd 92457ABCH

REZ dd ?

.code

MOV AX, word ptr ALFA ; Cuvintele m.p.s. la

; adr. mici

ADD AX, word ptr BETA ; Aici poate aparea

; transport

MOV word ptr REZ, AX

MOV AX, word ptr ALFA+2 ; Cuvintele m.s. la

; adr. mari

ADC AX, word ptr BETA+2 ; Se ia in considerare

; transportul precedent

MOV word ptr REZ+2, AX

Instructiunea INC (Increment - Incrementeaza)

Are forma generala:

INC  destinatie

in care destinatie este un registru sau un operand in memorie, de tip octet sau cuvant. Semnificatia este:

(destinatie) <- (destinatie) + 1

Flaguri afectate: AF, PF, SF, ZF, OF (fara CF).

Instructiunea DAA (Decimal Adjust for Addition - Corectie zecimala dupa adunare)

Instructiunea nu are operanzi si efectueaza corectia zecimala a acumulatorului AL, dupa o adunare cu operanzi in format BCD despachetat. Semnificatia este:

daca (AL0:3) > 9 sau (AF) = 1, atunci

daca acum (AL4:7) > 9 sau CF = 1, atunci

Flaguri afectate: CF, AF, CF, PF, SF, ZF. Flagul OF este nedefinit.

Daca cifra BCD mai putin semnificativa (AL0:3) este mai mare decat 9, deci este incorecta, sau daca a avut loc un transport din bitul 3 in bitul 4, se corecteaza aceasta cifra prin adunarea valorii 6. Daca cifra BCD mai semnificativa este acum mai mare decat 9, se corecteaza similar aceasta cifra. In ambele situatii, se pozitioneaza corespunzator AF si CF, pentru a indica depasirea care a avut loc.

Sa consideram, de exemplu, adunarea valorilor BCD 65 si 17. Aceste valori se reprezinta prin octetii 65H si 17H. In urma adunarii, se obtine rezultatul 7CH, care este incorect ca rezultat BCD. Operatia de corectie (DAA) conduce la rezultatul 82H, ceea ce reprezinta suma BCD a celor doua valori. Secventa de adunare trebuie sa fie:

.data

BCD1  db 65H

BCD2  db 17H

REZ db ?

.code

MOV AL, BCD1

ADD AL, BCD2

DAA

MOV REZ, AL

Instructiunea AAA (ASCll Adjust for Addition - Corectie ASCII a acumulatorului)

Instructiunea nu are operanzi si efectueaza corectia acumulatorului AX, dupa operatii de adunare cu operanzi BCD despachetati (o cifra BCD pe un octet). Semnificatia este urmatoarea:

daca (AL0:3) > 9 sau (AF) = 1, atunci

Flaguri afectate: AF, CF, restul nedefinite.

Corectia se face tot prin adaugarea valorii 6 la (AL), dar se face si o incrementare a registrului (AH), in ideea ca acolo s-ar putea tine cifra BCD despachetata mai semnificativa. Totodata se sterg bitii 4:7 ai registrului AL, pentru a avea o cifra BCD despachetata. Sa consideram ca registrele AX si BX contin valorile 0309H si 0104H, ceea ce ar corespunde valorilor BCD despachetate 39 si 14. In urma adunarii, se obtine rezultatul 040DH, care este incorect. Instructiunea AAA, corecteaza acest rezultat la 0503H, care este suma corecta a celor doua valori initiale:

MOV AX, 0309H

MOV BX, 0104H

ADD AX, BX ; AX = 040DH

AAA ; AX = 0503H

3 Instructiuni specifice scaderii (SUB, SBB, DEC, NEG, CMP, DAS, AAS)

Instructiunea, SUB (Subtract - Scade)

Are forma generala:

SUB  destinatie, sursa

unde destinatie si sursa sunt la fel ca la instructiunea ADD. Semnificatia este:

(destinatie) <- (destinatie) - (sursa)

Flaguri afectate: AF, CF, PF, SF, ZF, OF (toate).

Scaderea poate fi privita ca o adunare cu complementul fata de 2 al operandului sursa, dar cu inversarea rolului bistabilului CF, in sensul ca, daca la aceasta adunare echivalenta apare transport, atunci CF = 0 si reciproc. Sa consideram secventa de instructiuni:

MOV AL, 1

SUB AL, 05EH

Rezultatul este 0A3H si exista imprumut, deci CF = 1. Daca luam complementul fata de 2 al sursei, obtinem valoarea 0A2H, care, adunata la destinatie (adica la 1), conduce la valoarea 0A3H. La aceasta adunare echivalenta nu exista transport, deci, conform regulii de mai sus, operatia de scadere de la care am pornit va conduce la CF = 1.

Instructiunea SBB (Subtract with Borrow - Scade cu imprumut)

Are forma generala:

SBB  destinatie, sursa

in care destinatie si sursa sunt la fel ca la instructiunea ADD. Semnificatia este:

(destinatie) <- (destinatie) - (sursa) - (CF)

deci se ia in considerare un eventual imprumut anterior.

Flaguri afectate: AF, CF, PF, SF, ZF, OF (toate).

Instructiunea SBB se utilizeaza la scaderi de operanzi pe mai multe cuvinte, ca in exemplul urmator:

.data

ALFA  dd 145A789FH

BETA  dd 92457ABCH

REZ dd ?

.code

MOV AX, word ptr ALFA ; Cuvintele m.p.s. la

; adr. mici

SUB AX, word ptr BETA ; Aici poate aparea

; imprumut

MOV word ptr REZ, AX

MOV AX, word ptr ALFA+2 ; Cuvintele m.s. la

; adr. mari

SBB AX, word ptr BETA+2 ; Se ia in considerare

; imprumutul precedent

MOV word ptr REZ+2, AX

Instructiunea DEC (Decrement - Decrementeaza)

Are forma generala:

DEC  destinatie

in care destinatie este la fel ca la instructiunea INC. Semnificatia este:

(destinatie) <- (destinatie) - 1

Flaguri afectate: AF, PF, SF, ZF, OF (fara CF).

Instructiunea NEG (Negate - Schimba semnul)

Are forma generala:

NEG  destinatie

in care destinatie este un registru sau o locatie de memorie, pe 8 sau pe 16 biti. Semnificatia este:

(destinatie) <- 0 - (destinatie)

deci se face o schimbare a semnului operandului.

Flaguri afectate: AF, CF, PF, SF, ZF, OF (toate).

De observat ca schimbarea semnului poate conduce uneori la aceeasi valoare, in cazul depasirii domeniului admisibil. De exemplu, secventa:

MOV AL, -128

NEG AL

va lasa registrul AL neschimbat (80H), deoarece 128 si -128 au aceeasi reprezentare interna.

Instructiunea CMP (Compare - Compara)

Are forma generala:

CMP  destinatie, sursa

iar semnificatia este executia unei scaderi temporare (destinatie) - (sursa), fara a se modifica vreun operand, dar cu pozitionarea bistabililor de conditie.

Flaguri afectate: AF, CF, PF, SF, ZF, OF (toate).

Testand bistabilii de conditie, putem deduce relatia dintre cei doi operanzi. De exemplu, instructiunea CMP AX, BX va provoca o scadere temporara (AX) - (BX). Daca ZF = 1 inseamna ca (AX) = (BX). Daca CF = 1 inseamna ca la scadere a aparut un imprumut, deci (AX) < (BX), daca sunt considerate ca numere fara semn.

Instructiunea CMP se foloseste, de obicei, impreuna cu instructiuni de salt conditionat (vezi 2.4.3).

Instructiunea DAS (Decimal Adjust for Subtraction - Corectie zecimala dupa scadere)

Instructiunea nu are operanzi si executa corectia zecimala a acumulatorului AL, dupa operatii de scadere cu numere in format BCD impachetat. Semnificatia este:

daca (AL0:3) > 9 sau (AF) = 1, atunci

daca acum (AL4:7) > 9 sau CF = 1, atunci

Flaguri afectate: AF, CF, PF, SF, ZF. Flagul OF este nedefinit.

Explicatia operatiilor de mai sus este similara cu cea de la instructiunea DAA. De exemplu, in urma secventei:

.code

MOV AL, 52H

SUB  AL, 24H ; AL = 2EH

DAS  ; AL = 28H

se obtine in AL rezultatul corect 28H (28= 52 - 24).

Instructiunea AAS (ASCII Adjust for Subtraction - Corectie ASCII dupa scadere)

Instructiunea nu are operanzi si efectueaza corectia acumulatorului AX, dupa operatii de scadere cu operanzi BCD despachetati (o cifra BCD pe un octet). Semnificatia este urmatoarea:

daca (AL0:3) > 9 sau (AF) = 1, atunci

Flaguri afectate: AF, CF, restul nedefinite.

Se observa analogia cu instructiunea AAA, specifica adunarii in format BCD despachetat.

4 Instructiuni specifice inmultirii (CBW, CWD, MUL, IMUL, AAM)

Operatiile de inmultire se fac intre acumulator si un al doilea operand. Rezultatul operatiei este pe 16 sau, respectiv, 32 de biti. Se folosesc urmatoarele notiuni, definite diferit la operatii de 8 sau 16 biti:

. acumulator - registrul AL, respectiv, AX

. acumulator extins - registrul AX, respectiv perechea de registre DX:AX

. extensia acumulatorului - registrul AH, respectiv DX

. extensia de semn a acumulatorului - continutul registrului AL, respectiv AX, reprezentat, ca numar cu

semn, pe o lungime dubla (16, respectiv 32 de biti).

Instructiunea CBW (Convert Byte to Word - Converteste octet la cuvant)

Este fara operanzi si are urmatoarea semnificatie:

daca (AL7) = 0, atunci

(AH) <- 0

altfel

(AH) <- 1

Flaguri afectate: nici unul.

Practic, se extinde bitul de semn din AL la intreg registrul AH. Acest lucru este echivalent cu reprezentarea lui AL in complement fata de 2, pe un numar dublu de biti. De exemplu, daca AL = -3 (OFDH), atunci instructiunea CBW va forta in AX valoarea 0FFFDH, care este chiar reprezentarea in complement fata de 2 a valorii - 3.

Instructiunea CWD (Convert Word to DoubleWord - Converteste cuvant la dublu-cuvant)

Este fara operanzi si are urmatoarea semnificatie:

daca (AX15) = 0, atunci

(DX) <- 0

altfel

(DX) <- 1

Flaguri afectate: nici unul.

Se extinde bitul de semn din AX la intreg registrul DX, obtinandu-se astfel o reprezentare a lui AX pe 32 de biti.

Prin instructiunile CBW si CWD, se obtin extensiile de semn ale acumulatorului in acumulatorul extins.

Instructiunea MUL (Multiply - Inmulteste fara semn)

Are forma generala:

MUL  sursa

in care sursa poate fi un registru sau o locatie de memorie de 8 sau 16 biti. Variantele noi de procesoare accepta si date imediate ca operand sursa. Rezultatul se obtine pe un numar dublu de biti (16 sau 32). Semnificatia este:

(acumulator extins) <- (acumulator) * (sursa)

in care ambii operanzi se considera numere fara semn. Mai precis, daca sursa este pe octet:

(AH:AL) <- (AL) * (sursa)

iar daca sursa este pe cuvant:

(DX:AX) <- (AX) * (sursa)

Flaguri afectate: daca extensia acumulatorului (adica AH sau DX) este diferita de 0, atunci CF si OF sunt 1, altfel CF si OF sunt 0. Restul flagurilor sunt nedefinite. Exemple:

.data

ALFA  db 10H

BETA  dw 200H

.code

MOV AL, 10H

MUL ALFA ; (AX) <- (AL) * ALFA

MOV AX, 20H

MUL BETA ; (DX:AX) <- (AX) * BETA

MOV AX, 100H

MOV BX, 20H

MUL BX ; (DX:AX) <- (AX) * (BX)

In situatia in care un operand este de tip byte, iar celalalt de tip word, se converteste operandul de tip byte la word, ca numar fara semn, deci cu partea mai semnificativa 0. De exemplu, pentru a inmulti valorile ALFA si BETA, se poate scrie:

MOV AL, ALFA

MOV AH, 0 ; (AX) = 0010H

MUL BETA ; (DX:AX) = 2000H

Se observa ca instructiunea MUL nu poate conduce la depasiri. Inmultind fara semn cele mai mari valori posibile pe 8 / 16 biti, se obtin valori corecte pe 16 / 32 de biti. De exemplu,

(216 - 1)*(216 - 1) = 232 - 217 + 1, care este o valoare reprezentabila pe 32 de biti.

Instructiunea IMUL (Integer Multiply - Inmulteste cu semn)

Are forma generala:

IMUL sursa

fiind similara cu instructiunea MUL. Deosebirea este ca operatia de inmultire se face considerand operanzii numere cu semn.

Flaguri afectate: daca extensia acumulatorului reprezinta extensia de semn a acumulatorului, atunci CF si OF se pozitioneaza la 0. Altfel, CF si OF devin 1. Restul flagurilor sunt nedefinite.

Nu pot aparea situatii de depasire. Inmultind cele mai mari valori in modul, se obtin valori corect reprezentabile. De exemplu, 127*127 = 16129, care se reprezinta corect ca numar cu semn pe 16 biti. Similar,

Daca sunt necesare conversii de la byte la word, se va folosi instructiunea CBW, ca in secventa urmatoare:

.data

ALFA db -113

BETA dw -147

REZ dd ?

.code

MOV AL, ALFA

CBW ; Conversie la word

MUL BETA ; Inmultire pe 16 biti

MOV word ptr REZ, AX ; Partea m.p.s. la

; adrese mici

MOV word ptr REZ+2, BX ; partea m.s. la

; adrese mari

Instructiunea AAM (ASCII Adjust for Multiply - Corectie ASCIl dupa inmultire)

Instructiunea nu are operanzi si efectueaza o corectie a acumulatorului AX, dupa o inmultire pe 8 biti cu numere in format BCD despachetat. Semnificatia este:

(AH) <- (AL) / 10

(AL)  <- (AL) MOD 10

Flaguri afectate: PF, SF, ZF, restul nedefinite.

De exemplu, sa consideram secventa:

MOV AL, 5

MOV CL, 9

MUL CL

AAM

In urma inmultirii, registrul AX va contine valoarea 2DH (45). Corectia prin AAM conduce la AH = 4 si AL = 5, deci AX = 0405H, adica reprezentarea BCD despachetat pentru valoarea zecimala 45.

5 Instructiuni specifice impartirii (DIV, IDIV, AAD)

Impartirea presupune ca deimpartitul este pe o lungime dubla decat impartitorul. Prin impartire se obtin catul si restul, de lungime egala cu a impartitorului.

Instructiunea DIV(Divide - Imparte fara semn)

Are forma generala:

DIV  sursa

in care sursa e un operand (registru sau locatie de memorie) pe octet sau pe cuvant. Procesoarele moderne accepta si date imediate ca operand sursa. Semnificatia este urmatoarea:

(acumulator) <- (acumulator extins) / (sursa)

(extensia acumulatorului) <- (acumulator extins) MOD (sursa)

Detaliind operatiile, se obtine, in cazul in care sursa este pe octet:

(AL) <- (AX) / (sursa)

(AH) <- (AX) MOD (sursa)

iar daca sursa este pe cuvant:

(AX) <- (DX:AX) / (sursa)

(DX) <- (DX:AX) MOD (sursa)

Flaguri afectate: toate flagurile sunt nedefinite.

Impartirea poate conduce la depasiri. In situatia in care catul rezulta mai mare decat valoarea maxima reprezentabila pe 8, respectiv 16 biti, sau daca impartitorul este 0, rezultatele sunt nedefinite si se genereaza o intrerupere soft pe nivelul 0 (Divide Overflow - Depasire la impartire). De exemplu, in secventa:

MOV AX 1000

MOV  BL, 2

DIV  BL

catul ar trebui sa fie 500, valoare care nu se poate reprezenta pe un octet. Ca atare, apare depasire si se va genera o intrerupere pe nivelul 0. Rutina afectata acestui nivel de intrerupere opreste de obicei programul executabil si afiseaza un mesaj de eroare la consola.

Sa consideram cateva exemple de operatii de impartire fara semn, care ilustreaza pregatirea operanzilor in situatiile care nu corespund celor doua tipuri de baza (impartire cuvant la octet si impartire dublu-cuvant la cuvant):

.data

B1 db ?

B2 db ?

W1 dw ?

W2 dw ?

Dl dd ?

.code

; impartire octet la octet

MOV  AL, B1

MOV  AH, 0

DIV  B2 ; AL = cat, AH = rest

; impartire cuvant la octet

MOV  AX, W1

DIV  B1 ; AL = cat, AH = rest

; impartire dublu-cuvant la cuvant:

MOV  AX, word ptr D1

MOV  DX, word ptr D1 + 2

DIV  W1 ; AX = cat, DX = rest

; impartire cuvant la cuvant

MOV  AX, W1

MOV  DX, 0

DIV W2 ; AX = cat, DX = rest

; impartire dublu-cuvant la byte

MOV AX, word ptr D1

MOV DX, word ptr D1 + 2

MOV BL, B1

MOV BH, 0

DIV BX ; AX = cat, DX = rest

Instructiunea IDIV (Integer Divide - Imparte cu semn)

Are forma generala:

IDIV sursa

in care sursa este la fel ca la instructiunea DIV. Semnificatia este aceeasi ca la instructiunea DIV, cu diferenta ca operanzii sunt considerati cu semn, iar impartirea se face cu semn.

Flaguri afectate: toate flagurile sunt nedefinite.

In situatia in care catul rezulta in afara domeniului reprezentabil pe 8, respectiv 16 biti, sau daca impartitorul este 0, rezultatele sunt nedefinite si se genereaza o intrerupere soft pe nivelul 0. Concret, catul trebuie sa fie in domeniul [-128, +127] la impartire pe octet, respectiv in domeniul [-32768, +32767] la impartire pe cuvant. De exemplu, in secventa:

MOV AX, 400

MOV BL, 2

IDIV  BL

catul ar trebuie sa rezulte 200, valoare care nu se poate reprezenta ca numar cu semn pe un octet. Ca atare, va aparea o intrerupere pe nivelul 0.

In ceea ce priveste calculul restului la impartirea cu semn, acesta este totdeauna calculat astfel incat sa fie indeplinita identitatea urmatoare:

a = b*(a / b) + a MOD b

in care a / b si a MOD b sunt catul si restul calculate de instructiunea IDIV. De exemplu, in secventa:

MOV  AX, -10

MOV  BL, -3

IDIV BL ; AL = 3, AH = 0FFH

catul rezulta +3, iar identitatea de mai sus conduce la restul - 1. Asadar (-10) MOD (-3) = -1 si in registrul AH se va gasi 0FFH (-1 reprezentat pe un octet).

Tipurile posibile de impartiri sunt aceleasi ca la instructiunea DIV, cu observatia ca operanzii trebuie pregatiti folosind instructiunile CBW si CWD. Consideram aceleasi definitii de date ca la instructiunea DIV:

. code

; impartire octet la octet

MOV AL, B1

CBW

IDIV  B2 ; AL = cat, AH = rest

; impartire cuvant la octet

MOV AX, W1

IDIV  B1 ; AL = cat, AH = rest

; impartire dublu-cuvant la cuvant

MOV AX, word ptr D1

MOV DX, word ptr D1 + 2

IDIV  W1 ; AX = cat, DX = rest

; impartire cuvant la cuvant

MOV AX, W1

CWD

IDIV  W2 ; AX = cat, DX = rest

; impartire dublu-cuvant la byte

MOV AL, B1

CBW

MOV BX, AX ; BX = deimpartit

MOV AX, word ptr D1

MOV DX, word ptr D1 + 2 ; DX:AX = impartitor

IDIV BX ; AX = cat, DX = rest

O aplicatie tipica a instructiunilor de impartire este conversia unui cuvant de 16 biti, cu sau fara semn, la un sir de caractere (cifre) in baza 10. Daca presupunem ca n este variabila care contine numarul, iar sir este variabila unde se depun cifrele generate, algoritmul poate fi descris (intr-o notatie specifica limbajului C), in felul urmator:

adrsir = sir;

do while (n != 0);

*sir = 0;

inverseaza (sir);

Interpretam numarul n fara semn. In bucla de program cu test la partea inferioara, se calculeaza restul si catul impartirii lui n la 10. Catul furnizeaza cifra curenta, careia i se aduna codul ASCII al cifrei 0. Se avanseaza adresa sir la urmatorul caracter, bucla terminandu-se cand n devine 0.

Se observa ca acest algoritm furnizeaza cifrele numarului in ordine inversa; ca atare, rutina inverseaza(sir), trebuie sa inverseze ordinea caracterelor din sirul generat. De exemplu, daca n = 1234, atunci prima iteratie produce rest = 4 si n = 123, a doua iteratie produce rest = 3 si n = 12 etc.

Sa implementam acest algoritm printr-o secventa in limbaj de asamblare.

.data

n  dw ?

sir db 20 dup (?)

.code

lea si, sir

mov ax, n

mov dx, 0

mov bl, 10

mov bh, 0

_do:

div bx ; AX = cat; DX (DL) = rest

add dl, '0'

mov [si] , dl

inc si

mov dx, 0

cmp ax, 0

jne _do ; Salt daca AX diferit de 0

mov byte ptr [si], 0

; Inverseaza

mov di, si

dec di ; DI indica ultimul caracter util

lea si, sir ; SI indica primul caracter

_test:

cmp si, di

jae _gata ; Salt daca SI >= DI

mov al, [si] ; Interschimba octetii de la

xchg  al, [di] ; adresele din SI si DI

mov [si], al

inc si

dec di

jmp _test

_gata:

Declaratia sir db 20 dup (?) rezerva o zona de 20 de octeti in segmentul de date. Simbolurile _do:, _test:, _gata: sunt etichete folosite la instructiuni de salt.

Desi avem de facut o impartire la 10 (deci la o cantitate care se poate reprezenta pe un octet), iar deimpartitul este un cuvant, vom folosi totusi impartirea dublu-cuvant la cuvant, pentru a evita depasirile. Se pregateste deci deimpartitul in DX:AX si catul in BX. Pentru accesul la sirul de caractere, folosim registrul SI. Asadar, variabilele n si sir din algoritm vor fi tinute in registrele AX si SI.

Prin impartire, se obtine catul in AX si restul in DX. De fapt, fiind o impartire la 10, restul nu poate depasi valoarea 9, deci il vom gasi, de fapt, in DL. Adaugam '0' si depunem caracterul la adresa data de SI, incrementam SI si pregatim deimpartitul pentru pasul urmator (adica fortam DX = 0). Se testeaza acum AX (adica variabila n), prin comparatie cu 0. Instructiunea JNZ inseamna "Jump on Not Equal', deci salt daca operanzii din ultima comparatie sunt diferiti. Acest salt conditionat reia bucla de program.

Pentru a inversa caracterele generate, se pozitioneaza registrele SI si Dl pe primul si, respectiv, pe ultimul caracter util din sir, dupa care se executa o bucla de inversare, care continua cat timp SI < Dl. Instructiunea JAE inseamna "Jump if Above or Equal', deci salt daca la ultima comparatie primul operand a fost mai mare sau egal cu al doilea. In bucla respectiva, se interschimba caracterele de la adresele Dl si SI, prin doua MOV-uri si un XCHG.

Instructiunea AAD (ASCII Adjust for Division - Corectie ASCII inainte de impartire)

Instructiunea nu are operanzi si efectueaza o corectie a acumulatorului AX, interpretat ca doua cifre BCD despachetate. Semnificatia este urmatoarea:

(AL) <- (AH) * 10 + (AL)

(AH) <- 0

Flaguri afectate: PF, SF si ZF, restul nedefinite.

Operatia de corectie trebuie facuta inainte de impartirea unui numar pe doua cifre BCD, reprezentat pe un cuvant, la o cifra BCD reprezentata pe un octet.

De exemplu, daca AX = 0305H, adica valoarea BCD 35 si BL = 2, secventa de impartire va fi:

AAD ; AX = 23H

DIV BL ; AL = 11H, AH = 1

Instructiunea AAD incarca AX cu valoarea 22H (35) si impartirea se face corect, obtinandu-se catul 11H (17) si restul 1.

6 Instructiuni logice (NOT, AND, TEST, OR, XOR)

Instructiunile logice realizeaza functiile logice de baza, pe octet sau pe cuvant. Operatiile se fac la nivel de bit, deci se aplica functia logica respectiva tuturor bitilor sau perechilor de biti corespunzatori din operanzi. Instructiunea NOT are un singur operand, celelalte avand fiecare doi operanzi.

Instructiunea NOT (Not - Negare logica bit cu bit)

Forma generala este:

NOT  destinatie

in care destinatie poate fi un registru sau o locatie de memorie de 8 sau 16 biti. Instructiunea provoaca negarea tuturor bitilor operandului, deci calculul complementului fata de 1.

Flaguri afectate: nici unul.

Instructiunea AND (And - Si logic bit cu bit)

Are forma generala:

AND  destinatie, sursa

in care destinatie poate fi un registru sau o locatie de memorie de 8 sau 16 biti, iar sursa poate fi un registru, o locatie de memorie sau o constanta, pe 8 sau 16 biti. Semnificatia este:

(destinatie) <- (destinatie) AND (sursa)

Flaguri afectate: SF, ZF, PF, CF = 0, OF = 0, AF nedefinit.

Instructiunea TEST(Test - Testeaza)

Are forma generala:

TEST destinatie sursa

in care destinatie si sursa sunt la fel ca la instructiunea AND. Efectul este executia unei operatii AND intre cei doi operanzi, fara a se modifica destinatia, dar cu pozitionarea flagurilor la fel ca la instructiunea AND.

Flaguri afectate: SF, ZF, PF, CF = 0, OF = 0, AF nedefinit.

Aceasta instructiune si raportul ei cu instructiunea AND sunt similare cu instructiunea CMP si raportul cu instructiunea SUB.

Instructiunea OR (Or - Sau logic bit cu bit)

Are forma generala:

OR destinatie, sursa

in care destinatie si sursa sunt la fel ca la instructiunea AND. Semnificatia este:

(destinatie) <- (destinatie) OR (sursa)

Flaguri afectate: SF, ZF, PF, CF = 0, OF = 0, AF nedefinit.

Instructiunea XOR (Exclusive Or - Sau-exclusiv bit cu bit)

Are forma generala:

XOR  destinatie, sursa

in care destinatie si sursa sunt la fel ca la instructiunea AND. Semnificatia este:

(destinatie) <- (destinatie) XOR (sursa)

Flaguri afectate: SF, ZF, PF, CF = 0, OF = 0, AF nedefinit.

Functia sau-exclusiv este 1 cand operanzii sai sunt unul 0, iar celalalt 1 si este 0 cand operanzii sunt ambii 0 sau ambii 1. Din acest motiv, functia sau-exclusiv se mai numeste si anticoincidenta.

Instructiunile logice sunt folosite frecvent pentru anumite operatii tipice, cum ar fi:

. stergerea rapida a unui registru, cu pozitionarea flagurilor

XOR  AX, AX

XOR  CL, CL

. fortarea unor biti la valoarea 1, restul ramanand neschimbati

MASCA EQU 01101101B

OR AL, MASCA

Pseudo - instructiunea EQU defineste constante simbolice, iar prefixul B inseamna numar scris in baza 2. In secventa de mai sus, bitii cu valoarea 1 din MASCA vor fi fortati la 1 in registrul AL, iar bitii cu valoarea 0 din MASCA vor ramane neschimbati.

. fortarea unor biti la valoarea 0 cu ceilalti neschimbati

AND AL, MASCA

Bitii cu valoarea 0 din MASCA vor deveni 0 in AL, iar cei cu valoarea 1 in MASCA vor ramane neschimbati.

testarea unui singur bit dintr-un operand

TEST  AL, 01000000B

JZ eticheta ; sau JNZ

. pozitionarea flagurilor fara a modifica operandul

OR AX, AX ; Pozitioneaza FLAGS

; conform AX

AND AX, AX ; Similar

TEST  AX, AX ; Similar

. complementarea unui grup de biti, cu ceilalti neschimbati

Presupunem constanta MASCA, definita ca mai sus, si operandul aflat in AL. Dorim ca bitii cu valoarea 1 din MASCA sa fie complementati in AL, iar ceilalti sa ramana neschimbati.

MASCA EQU 01110110B

MOV BL, AL ; Salvare

AND AL, MASCA ; Selectie biti care

; se modifica

NOT AL ; Complementare

XCHG AL, BL ; Refacere

AND AL, NOT MASCA ; Selectie biti care

; nu se modifica

OR AL, BL ; Rezultat final

Expresia NOT MASCA este evaluata la asamblare, producandu-se o constanta cu toti bitii negati.

7 Instructiuni de deplasare (SHL, SAL, SHR, SAR) si de rotatie (ROL, RCL, ROR, RCR)

Acest grup de instructiuni realizeaza operatii de deplasare si de rotatie la nivel de bit. Instructiunile au doi operanzi: primul este operandul propriu-zis, iar al doilea este numarul de biti cu care se deplaseaza sau se roteste primul operand. Ambele operatii se pot face la dreapta sau la stanga. Deplasare inseamna translatarea tuturor bitilor din operand la stanga / dreapta, cu completarea unei valori fixe in dreapta / stanga si cu pierderea bitilor din stanga / dreapta. Depistarea cu un bit la stanga este echivalenta cu inmultirea operandului cu 2, iar deplasarea la dreapta, cu impartirea operandului la 2.

Rotatie inseamna translatarea tuturor bitilor din operand la stanga / dreapta, cu completarea in dreapta / stanga cu bitii care se pierd in partea opusa.

Ambele operatii se fac cu modificarea bistabilului CF, care poate chiar participa la operatiile de rotatie.

Forma generala a instructiunilor este:

OPERATIE OPERAND, CONTOR

in care OPERAND este un registru sau o locatie de memorie de 8 sau 16 biti, iar CONTOR (numarul de biti) este fie constanta 1, fie registrul CL, care contine numarul de biti cu care se deplaseaza / roteste operandul. Procesoarele de generatie noua (80286 si peste) accepta un numar oarecare de biti, specificat si printr-o constanta intreaga.

Flagurile sunt afectate in felul urmator. La operatiile de deplasare, se modifica toate flagurile conform rezultatului, in afara de AF, care este nedefinit. La operatiile de rotatie, se modifica numai CF si OF.

Modificarea flagului OF se face printr-un algoritm destul de complicat. Pentru a nu repeta acest algoritm, consideram urmatoarele secvente definite in pseudo - cod:

pozit_OF_left

pozit_OF_right

Se vede deci ca flagul OF este pozitionat numai daca se face o operatie de deplasare / rotatie de 1 bit.

Descrierea instructiunilor se va face intr-un format de tip pseudo - cod, cu evidentierea operatiilor aritmetice echivalente.

La instructiunile de deplasare, se considera deplasari logice si aritmetice, care se pot utiliza dupa natura operanzilor.

Instructiunea SHL/SAL (Shift Logic / Arithmetic Left - Deplaseaza logic / aritmetic la stanga)

Are forma generala:

SHL / SAL  OPERAND, CONTOR

Desi exista doua mnemonice (SHL si SAL), in fapt este vorba de o unica instructiune. Semnificatia este urmatoarea:

temp <- CONTOR

cat timp temp ! = 0

pozit_OF_left

Aceasta descriere nu spune altceva decat ca bitul cel mai semnificativ al operandului trece in CF, dupa care toti bitii se deplaseaza la stanga cu o pozitie (vezi Figura 2.3). Operatia se repeta de atatea ori cat este valoarea lui CONTOR (1 sau continutul registrului CL).

Instructiunea SHR (Shift Logic Right - Deplaseaza logic la dreapta)

Are forma generala:

SHR  OPERAND, CONTOR

Semnificatia este urmatoarea:

temp <- CONTOR

cat timp temp != 0

pozit_OF_right

Descrierea de mai sus spune ca bitul cel mai putin semnificativ din OPEFAND trece in CF, dupa care se deplaseaza toti bitii cu o pozitie la dreapta (impartire la 2). Faptul ca operatia de impartire se executa fara semn inseamna ca se completeaza cu un bit 0 dinspre stanga (vezi Figura 2.3). Operatia se repeta de atatea ori cat este valoarea lui CONTOR (1 sau continutul registrului CL).

Instructiunea SAR (Shift Arithmetic Right - Deplaseaza aritmetic la dreapta)

Are forma generala:

Semnificatia este urmatoarea:

temp <- CONTOR

cat timp temp != 0

pozit_OF_right

Singura diferenta fata de deplasarea logica la dreapta este realizarea impartirii la 2, luand in considerare semnul operandului. Aceasta inseamna ca se conserva bitul de semn, mai precis, completarea dinspre stanga se face cu bitul de semn (vezi Figura 2.3).

Aceste doua tipuri de deplasare la dreapta se reflecta si in implementarile limbajelor de nivel inalt. De exemplu, standardul ANSI al limbajului C lasa neprecizat faptul ca deplasarea la dreapta a unui intreg de tip signed se face cu completare dinspre stanga cu 0 sau cu bitul de semn (deci operatie de tip SHR sau SAR); aceasta alegere revine implementarii. Totusi, la deplasarea cantitatilor de tip unsigned, se completeaza intotdeauna dinspre stanga cu 0 (deci se face deplasare logica). Acest fapt este important mai ales in cazul tipului char, care nu este specificat in standardul ANSI ca fiind cu semn sau fara semn.

Instructiunea ROL (Rotate Left - Roteste la stanga)

Are forma generala:

ROL  OPERAND, CONTOR

Semnificatia este urmatoarea:

temp <- CONTOR

cat timp temp != 0

pozit_OF_left

Descrierea de mai sus spune ca bitul cel mai semnificativ din OPERAND trece atat in CF, cat si in bitul cel mai putin semnificativ din OPERAND, dupa ce toti bitii acestuia s-au deplasat la stanga cu o pozitie (vezi Figura 2.3). Operatia se repeta de atatea ori cat este valoarea lui CONTOR (1 sau continutul registrului CL).

Instructiunea RCL (Rotate Left through Carry - Roteste la stanga prin carry)

Are forma generala:

RCL  OPERAND, CONTOR

Semnificatia este urmatoarea:

temp <- CONTOR

cat timp temp 1 = 0

pozit_OF_left

Descrierea de mai sus spune ca bitul cel mai semnificativ din OPERAND trece in CF, se deplaseaza toti bitii din OPERAND cu ( pozitie la stanga, iar CF original trece in bitul cel mai putin semnificativ din OPERAND. Cu alte cuvinte, CF participa efectiv la rotatie (vezi Figura 2.3). Operatia se repeta de atatea ori cat este valoarea lui CONTOR (1 sau continutul registrului CL).

Instructiunea ROR (Rotate Right - Roteste la dreapta)

Are forma generala:

ROR OPERAND, CONTOR

Semnificatia este:

temp <- CONTOR

cat timp temp != 0

pozit_OF_right

Descrierea de mai sus spune ca bitul cel mai semnificativ din OPERAND trece atat in CF, cat si in bitul cel mai putin semnificativ, dupa ce toti bitii s-au deplasat la dreapta cu o pozitie (vezi Figura 2.3). Operatia se repeta de atatea ori cat este valoarea lui CONTOR (1 sau continutul registrului CL).

Instructiunea RCR (Rotate Right through Carry - Roteste la dreapta prin carry)

Are forma generala:

RCR   OPERAND, CONTOR

Semnificatia este urmatoarea:

temp <- CONTOR

cat timp temp != 0

pozit_OF_right

Descrierea de mai sus spune ca bitul cel mai putin semnificativ din OPERAND trece in CF, se deplaseaza toti bitii din OPERAND cu o pozitie la dreapta, iar CF original trece in bitul cel mai semnificativ din OPERAND. Cu alte cuvinte, CF participa efectiv la rotatie (vezi Figura 2.3). Operatia se repeta de atatea ori cat este valoarea lui CONTOR (1 sau continutul registrului CL).

Semnificatiile celor 7 instructiuni de deplasare si rotatie sunt ilustrate in Figura 2.3.

Sa consideram cateva exemple de rotatii si deplasari.

Inmultirea / impartirea cu puteri ale lui 2. Operatiile de asemenea tip se executa mult mai eficient prin deplasari la stanga / dreapta. Secventa:

MOV CL, 4

MOV AH, 0

SHL AX, CL

realizeaza inmultirea lui AL cu valoarea 16. Rezultatul se regaseste in AX. Secventa:

MOV CL, 3

SAL BX, CL

realizeaza impartirea lui BX (considerat numar cu semn) la valoarea 8.

Similar, se realizeaza si inmultiri cu valori care se pot exprima prin sume cu un numar redus de termeni de puteri ale lui 2. Secventa urmatoare realizeaza inmultirea unei valori N presupuse initial in AL cu valoarea 13, prin deplasari si adunari repetate. Rezultatul se regaseste in BX.

MOV AH, 0

MOV BX, AX ; Salvare N

MOV DX, AX ; Salvare N

MOV CL, 3

SHL AX, 3 ; AX <--- N * 8

ADD BX, AX ; BX <--- N * 8 + N

Figura 2.3 Semnificatia operatiilor de deplasare si de rotatie

MOV AX, DC ; Refacere N

MOV CL, 2

SHL AX, CL ; AX <--- N * 4

ADD BX, AX ; BX <--- N * 8 + N * 4 + N



Politica de confidentialitate | Termeni si conditii de utilizare



DISTRIBUIE DOCUMENTUL

Comentarii


Vizualizari: 2622
Importanta: rank

Comenteaza documentul:

Te rugam sa te autentifici sau sa iti faci cont pentru a putea comenta

Creaza cont nou

Termeni si conditii de utilizare | Contact
© SCRIGROUP 2024 . All rights reserved