26
1 9. CELOBROJNA ARITMETIKA 9.1 Instrukcije pomeranja i rotacije Instrukcije pomeranja su jedna od glavnih karakteristika asemblerskog jezika. Pomeranje označava pomeranje bitova levo ili desno unutar operanda. U tabeli 1 su prikazane instrukcije pomeranja, koje sve utiču na Overflow i Carry flegove. Tabela 1. Instrukcije pomeranja i rotacije Mnemonik Opis SHL Shift left (pomeraj ulevo) SHR Shift right (pomeraj udesno) SAL Shift arithmetic left (aritmetičko pomeranje ulevo) SAR Shift arithmetic right (aritmetičko pomeranje udesno) ROL Rotate left (rotacija ulevo) ROR Rotate right (rotacija udesno) RCL Rotate carry left (rotacija sa prenosom ulevo) RCR Rotate carry right (rotacija sa prenosom udesno) SHLD Double-precision shift left SHRD Double-precision shift right 9.1.1 Logičko i aritmetičko pomeranje Postoje dva načina za pomeranje bitova unutar operanda. Logičko pomeranje upisuje nule na novokreirane pozicije. Na sledećoj slici, bajt se logički pomera za jednu poziciju udesno. Drugim rečima, svaki bit se pomera na sledeću nižu poziciju. Bitu 7 se dodeljuje vrednost 0. Sledeća ilustracija prikazuje jedno logičko pomeranje udesno binarne vrednosti 11001111, čime se dobija 01100111. Bit najmanje težine se premešta u Carry fleg:

Vezba 9 - Celobrojna Aritmetika

Embed Size (px)

DESCRIPTION

Vezba 9 - Celobrojna Aritmetika

Citation preview

Page 1: Vezba 9 - Celobrojna Aritmetika

1

9.

CELOBROJNA ARITMETIKA

9.1 Instrukcije pomeranja i rotacije

Instrukcije pomeranja su jedna od glavnih karakteristika asemblerskog jezika. Pomeranje

označava pomeranje bitova levo ili desno unutar operanda. U tabeli 1 su prikazane instrukcije

pomeranja, koje sve utiču na Overflow i Carry flegove.

Tabela 1. Instrukcije pomeranja i rotacije

Mnemonik Opis

SHL Shift left (pomeraj ulevo)

SHR Shift right (pomeraj udesno)

SAL Shift arithmetic left (aritmetičko pomeranje ulevo)

SAR Shift arithmetic right (aritmetičko pomeranje udesno)

ROL Rotate left (rotacija ulevo)

ROR Rotate right (rotacija udesno)

RCL Rotate carry left (rotacija sa prenosom ulevo)

RCR Rotate carry right (rotacija sa prenosom udesno)

SHLD Double-precision shift left

SHRD Double-precision shift right

9.1.1 Logičko i aritmetičko pomeranje

Postoje dva načina za pomeranje bitova unutar operanda. Logičko pomeranje upisuje nule

na novokreirane pozicije. Na sledećoj slici, bajt se logički pomera za jednu poziciju udesno.

Drugim rečima, svaki bit se pomera na sledeću nižu poziciju. Bitu 7 se dodeljuje vrednost 0.

Sledeća ilustracija prikazuje jedno logičko pomeranje udesno binarne vrednosti

11001111, čime se dobija 01100111. Bit najmanje težine se premešta u Carry fleg:

Page 2: Vezba 9 - Celobrojna Aritmetika

2

Drugi tip pomeranja je aritmetičko pomeranje. Novokreirane pozicije se popunjavaju sa

kopijom originalnog bita znaka:

Na primer, binarna vrednost 11001111, ima 1 kao bit znaka. Kada se aritmetički pomeri

za jedan bit udesno, postaće 11100111:

9.1.2 Instrukcija SHL

Instrukcija SHL vrši logičko pomeranje ulevo odredišnog operanda, popunjavajući

najniži bit sa nulom. Bit najveće težine se premešta u Carry fleg, a bit koji je bio u Carry flegu

se odbacuje:

Ako pomerite ulevo za jedno mesto broj 11001111, dobija se 10011110:

Sintaksa SHL instrukcije je:

SHL odredište, broj

gde broj označava za koliko mesta se vrednost pomera ulevo.

Instrukcija dozvoljava sledeće tipove operanada:

SHL reg,imm8

SHL mem,imm8

SHL reg,CL

SHL mem,CL

Procesori x86 dozvoljavaju da imm8 bude bilo koji ceo broj od 0 do 255. Alternativno,

registar CL može sadržati broj pomeranja. Ovi formati važe i za SHR, SAL, SAR, ROR, ROL.

Primer

U sledećim instrukcijama, BL se pomera jedanput ulevo. Najviši bit se kopira u Carry

fleg, a najniži postaje 0:

Page 3: Vezba 9 - Celobrojna Aritmetika

3

mov bl,8Fh ; BL = 10001111b

shl bl,1 ; CF = 1, BL = 00011110b

Višestruko pomeranje

Kada se vrednost pomera ulevo više puta, Carry fleg sadrži poslednji bit koji je pomeren

sa MSB pozicije. U sledećem primeru, bit 7 ne završava u Carry flegu, jer ga zamenjuje bit 6

(nula):

mov al,10000000b

shl al,2 ; CF = 0, AL = 00000000b

Na sličan način, kada se vrednost pomera udesno više puta, Carry fleg sadrži poslednji

bit koji je bio pomeren sa LSB pozicije.

Bitsko množenje

SHL može da vrši množenje sa stepenima dvojke. Pomeranje nekog operanda ulevo za n

bitova daje proizvod tog operanda sa 2n. Na primer, pomeranje broja 5 ulevo za 1 bit, daje 10:

mov dl,5

shl dl,1

Ako se binarni broj 00001010 (decimalno 10) pomeri ulevo za dva mesta, dobija se 40

(10 x 22):

mov dl,10 ; pre: 00001010

shl dl,2 ; posle: 00101000

9.1.3 Instrukcija SHR

Ova instrukcija vrši logičko pomeranje udesno odredišnog operanda, menjajući najviši

bit sa nulom. Najniži bit se kopira u Carry fleg, a bit koji je pre toga bio u Carry flegu je

izgubljen:

SHR koristi isti format instrukcija kao SHL. U sledećem primeru, 0 iz najnižeg bita u AL

se kopira u Carry fleg, a najviši bit u AL postaje 0:

mov al,0D0h ; AL = 11010000b

shr al,1 ; AL = 01101000b, CF = 0

Višestruko pomeranje

U ovom slučaju, poslednji bit koji je bio na LSB poziciji se premešta u Carry fleg:

Page 4: Vezba 9 - Celobrojna Aritmetika

4

mov al,00000010b

shr al,2 ; AL = 00000000b, CF = 1

Bitsko deljenje

Logičkim pomeranjem neoznačenog operanda udesno za n bitova, dobija se količnik tog

operanda sa 2n. U sledećim iskazima, delimo 32 sa 2 i dobija se 16:

mov dl,32

shr dl,1

U sledećem primeru, 64 se deli sa 23:

mov al,01000000b ; AL = 64

shr al,3 ; deljenje sa 8, AL = 00001000b

Deljenje označenih brojeva pomoću pomeranja se dobija koristeći SAR instrukciju, zato

što ona čuva bit znaka.

9.1.4 Instrukcije SAL i SAR

SAL instrukcija radi isto kao i SHL instrukcija. SAL pomera svaki bit u odredišnom

operandu za određeni broj mesta ulevo. Najnižem bitu se dodeljuje 0. Najviši bit se premešta u

Carry fleg, a bit koji je već bio u Carry flegu se odbacuje:

Ako se broj 11001111 pomeri ulevo za jedan bit, postaje 10011110:

Instrukcija SAR vrši aritmetičko pomeranje udesno odredišnog operanda:

Operandi instrukcija SAL i SAR su isti kao i za SHL i SHR. Pomeranje se može ponavljati

veći broj puta, na osnovu drugog operanda u instrukciji:

SAR odredište, broj

Sledeći primer pokazuje kako SAR duplicira bit znaka. AL je negativan pre i posle

pomeranja udesno:

Page 5: Vezba 9 - Celobrojna Aritmetika

5

mov al,0F0h ; AL = 11110000b (-16)

sar al,1 ; AL = 11111000b (-8), CF = 0

Označeno deljenje

Možete podeliti označeni operand sa stepenom broja 2 koristeći SAR instrukciju. U

sledećem primeru, -128 se deli sa 23. Rezultat je -16:

mov dl,-128 ; DL = 10000000b

sar dl,3 ; DL = 11110000b

Proširivanje znakom registra AX u EAX

Pretpostavimo da AX sadrži označeni ceo broj i da želite da ga proširite znakom i smestite

u EAX. Najpre se EAX pomera 16 bitova ulevo, a potom se aritmetički pomera za 16 bitova

udesno:

mov ax,-128 ; EAX = ????FF80h

shl eax,16 ; EAX = FF800000h

sar eax,16 ; EAX = FFFFFF80h

9.1.5 Instrukcija ROL

Instrukcija ROL pomera svaki bit ulevo. Najviši bit se kopira u Carry fleg i na poziciju

najnižeg bita. Format instrukcije je isti kao i za SHL.

Rotacijom se ne gube bitovi. Bit sa jedne strane se rotiranjem pojavljuje na drugoj strani.

Primetite u sledećem primeru kako se najviši bit kopira i u Carry fleg i na poziciju 0:

mov al,40h ; AL = 01000000b

rol al,1 ; AL = 10000000b, CF = 0

rol al,1 ; AL = 00000001b, CF = 1

rol al,1 ; AL = 00000010b, CF = 0

Višestruke rotacije

Kada se koristi broj rotacija veći od 1, Carry fleg sadrži poslednji bit koji je izrotiran sa

MSB pozicije:

mov al,00100000b

rol al,3 ; CF = 1, AL = 00000001b

Zamena grupe bitova

Instrukcija ROL se može koristiti za zamenu gornje (bitovi 4-7) i donje (bitovi 0-3)

polovine bajta. Na primer, rotiranjem broja 26h za četiri mesta u bilo kom smeru, dobija se 62h:

mov al,26h

Page 6: Vezba 9 - Celobrojna Aritmetika

6

rol al,4 ; AL = 62h

Kada se rotira ceo broj od više bajtova za 4 bita, dobija se pomeranje svake

heksadecimalne cifre za jednu poziciju ulevo ili udesno. Na primer, ovde je neprekidno rotiran

broj 6A4Bh ulevo za 4 bita, a na kraju je dobijena originalna vrednost:

mov ax,6A4Bh

rol ax,4 ; AX = A4B6h

rol ax,4 ; AX = 4B6Ah

rol ax,4 ; AX = B6A4h

rol ax,4 ; AX = 6A4Bh

9.1.6 Instrukcija ROR

Ova instrukcija pomera svaki bit udesno i kopira najniži bit u Carry fleg i bit najviše

pozicije. Format instrukcije je isti kao i za SHL:

U sledećim primerima, primetite kako se najniži bit kopira i u Carry fleg i u najviši bit

rezultata:

mov al,01h ; AL = 00000001b

ror al,1 ; AL = 10000000b, CF = 1

ror al,1 ; AL = 01000000b, CF = 0

Višestruka rotacija

Kada se koristi višestruka rotacija, Carry fleg sadrži poslednji bit koji je pomeren sa LSB

pozicije:

mov al,00000100b

ror al,3 ; AL = 10000000b, CF = 1

9.1.7 Instrukcije RCL i RCR

Instrukcija RCL pomera svaki bit ulevo, kopira Carry fleg u LSB i kopira MSB u Carry

fleg:

Ako posmatramo Carry fleg kao dodatni bit koji je dodat na krajnji bit operanda, RCL se

ponaša kao ROL instrukcija. U sledećem primeru, CLC instrukcija briše Carry fleg. Prva RCL

instrukcija premešta najviši bit iz BL u Carry fleg i pomera ostale bitove ulevo. Druga RCL

instrukcija premešta Carry fleg u najniži bit i pomera ostale bitove ulevo:

clc ; CF = 0

Page 7: Vezba 9 - Celobrojna Aritmetika

7

mov bl,88h ; CF,BL = 0 10001000b

rcl bl,1 ; CF,BL = 1 00010000b

rcl bl,1 ; CF,BL = 0 00100001b

Restauracija bita iz Carry flega

RCL može da vrati bit koji je prethodno bio premešten pomeranjem u Carry fleg. U

sledećem primeru se proverava najniži bit promenljive testval tako što se pomera njen najniži

bit u Carry fleg. Ako je najniži bit jednak 1, dolazi do skoka. U suprotnom, RCL vraća broj na

originalnu vrednost:

.data

testval BYTE 01101010b

.code

shr testval,1 ; pomeri LSB u Carry fleg

jc exit ; izađi ako je Carry fleg setovan

rcl testval,1 ; u suprotnom vrati broj na staro

Instrukcija RCR

Ova instrukcija pomera svaki bit udesno, kopira Carry fleg u MSB i kopira LSB u Carry

fleg:

Kao i u slučaju sa RCL, pomaže da se zamisli ceo broj na ovoj slici kao 9-bitna vrednost,

sa Carry flegom sa desne strane LSB-a.

U sledećem primeru se koristi STC kako bi se setovao Carry fleg. Potom se vrši RCR

operacija nad AH registrom:

stc ; CF = 1

mov ah,10h ; AH, CF = 00010000 1

rcr ah,1 ; AH, CF = 10001000 0

Prekoračenje označenih vrednosti

Overflow fleg se setuje kada se pomera ili rotira označeni ceo broj za jednu poziciju i

dobije se vrednost van opsega označenih brojeva odredišnog operanda. Drugim rečima, znak

broja biva promenjen. U sledećem primeru, pozitivan ceo broj (+127), smešten u 8-bitnom

registru, postaje negativan broj (-2) kada se rotira ulevo:

mov al,+127 ; AL = 01111111b

rol al,1 ; OF = 1, AL = 11111110b

Slično, kada se -128 rotira za jednu poziciju udesno, setuje se Overflow fleg. Rezultat u

AL (+64) ima suprotan znak:

Page 8: Vezba 9 - Celobrojna Aritmetika

8

mov al,-128 ; AL = 10000000b

shr al,1 ; OF = 1, AL = 01000000b

Vrednost Overflow flega je nedefinisana kada se pomera ili rotira za više od jednog mesta.

9.1.8 Instrukcije SHLD i SHRD

SHLD instrukcija pomera odredišni operand za određen broj mesta ulevo. Upražnjene

pozicije se popunjavaju sa najvišim bitovima izvorišnog operanda. Izvorišni operand se ne

menja, ali utiče se na Sign, Zero, Parity, Carry i Auxiliary Carry flegove:

SHLD odredište, izvorište, broj

Na sledećoj slici je prikazano izvršavanje SHLD instrukcije sa pomerajem od jednog

mesta. Najviši bit izvorišnog operanda se kopira u najniži bit odredišnog operanda. Svi bitovi

odredišnog operanda se pomeraju ulevo:

Instrukcija SHRD pomera odredišni operand za određeni broj pozicija udesno.

Upražnjene pozicije se popunjavaju najnižim bitovima izvorišnog operanda:

SHRD odredište, izvorište, broj

Na sledećoj slici je prikazao izvršavanje SHRD instrukcije sa pomerajem od jednog

mesta:

Sledeći formati instrukcija se mogu primeniti i na SHLD i SHRD. Odredišni operand

može biti registarski ili memorijski, a izvorišni operand mora biti registarski. Operand broj

može biti CL registar ili 8-bitni neposredni operand:

SHLD reg16,reg16,CL/imm8

SHLD mem16,reg16,CL/imm8

SHLD reg32,reg32,CL/imm8

Page 9: Vezba 9 - Celobrojna Aritmetika

9

SHLD mem32,reg32,CL/imm8

Primer 1

Sledeći iskazi pomeraju wval ulevo za 4 bita i ubacuju najviša 4 bita AX registra u najniže

4 pozicije wval promenljive:

.data

wval WORD 9BA6h

.code

mov ax,0AC36h

shld wval,ax,4 ; wval = BA6Ah

Kretanje podataka je prikazano na sledećoj slici:

Primer 2

U sledećem primeru, AX se pomera udesno za 4 bita, a najniža 4 bita registra DX se

pomeraju u najviše 4 pozicije registra AX:

mov ax,234Bh

mov dx,7654h

shrd ax,dx,4 ; AX = 4234h

SHLD i SHRD se mogu koristiti za manipulaciju bitmapiranim slikama, kada se grupa

bitova mora pomeriti ulevo ili udesno za pozicioniranje slike na ekranu. Druga moguća

upotreba je enkripcija podataka, u kojoj algoritam enkripcije uključuje pomeranje bitova. Na

kraju, dve instrukcije se mogu koristiti kada se vrši brzo deljenje i množenje sa veoma velikim

celim brojevima.

Sledeći primer demonstrira upotrebu SHRD tako što se niz dvostrukih reči pomera udesno

za 4 bita:

.data

array DWORD 648B2165h,8C943A29h,6DFA4B86h,91F76C04h,8BAF9857h

.code

mov bl,4 ; broj pomeranja

mov esi,OFFSET array ; ofset niza

mov ecx,(LENGTHOF array) – 1 ; broj elemenata niza

L1: push ecx ; čuvanje brojača petlje

mov eax,[esi + TYPE DWORD]

mov cl,bl ; broj pomeranja

Page 10: Vezba 9 - Celobrojna Aritmetika

10

shrd [esi],eax,cl ; pomeri EAX u gornje bitove [ESI]-a

add esi,TYPE DWORD ; ukaži na sledeći par elemenata

pop ecx ; vrati brojač petlje

loop L1

shr DWORD PTR [esi],COUNT ; pomeri poslednju dvostruku reč

9.2 Primena instrukcija pomeranja i rotiranja

9.2.1 Binarno množenje

U ranijim Intel-ovim procesorima, instrukcije binarnog množenja (MUL i IMUL) su se

smatrale sporim u odnosu na druge mašinske instrukcije. Kao rezultat toga, programeri su

pronašli da se množenje može efikasnije odraditi koristeći tehnike pomeranja bitova. Instrukcija

SHL vrši efikasno neoznačeno množenje kada je činilac stepen broja 2. Pomeranjem

neoznačenog broja za n bitova ulevo dobija se proizvod tog broja sa 2n. Bilo koji drugi činilac

se može izraziti kao suma stepena broja dva. Na primer, množenje neoznačenog EAX sa 36

možemo napisati kao množenje sa 25 + 22 i koristiti osobinu distributivnosti množenja:

EAX * 36 = EAX * (25 + 22)

= EAX * (32 + 4)

= (EAX * 32) + (EAX * 4)

Na sledećoj slici je prikazano množenje 123 sa 36, čime se dobija 4428:

Zanimljivo je primetiti da se u proizvodu 36 setuju bitovi 2 i 5, a da 2 i 5 istovremeno

označavaju koliko puta se pomeraju brojevi. Koristeći ovu informaciju, sledeći kod množi 123

sa 36 koristeći SHL i ADD instrukcije:

.code

mov eax,123

mov ebx,eax

shl eax,5 ; množenje sa 25

shl ebx,2 ; množenje sa 22

add eax,ebx ; sabiranje proizvoda

9.2.2 Prikaz binarnih bitova

Uobičajen programerski zadatak je konverzija binarnih celih brojeva u ASCII binarni

string koji se može prikazati. Instrukcija SHL je korisna zato što kopira najviši bit operanda u

Carry fleg svaki put kada se operand pomera ulevo. Sledeća procedura predstavlja jednostavnu

implementaciju ovog principa.

Page 11: Vezba 9 - Celobrojna Aritmetika

11

;---------------------------------------------------------

BinToAsc PROC

;

; Konvertuje 32-bitne binarne cele brojeve u ASCII binarne

brojeve.

; Prima: EAX = binarni ceo broj, ESI ukazuje na bafer

; Vraća: bafer popunjen sa ASCII binarnim ciframa

;---------------------------------------------------------

push ecx

push esi

mov ecx,32 ; broj bitova u EAX

L1: shl eax,1 ; pomeranje gornjeg bita u Carry fleg

mov BYTE PTR [esi],'0' ; odabir 0 kao podrazumevane

; cifre

jnc L2 ; ako nema prenosa, skoči na L2

mov BYTE PTR [esi],'1' ; u suprotnom, premesti 1 u

; bafer

L2: inc esi ; sledeća pozicija u baferu

loop L1 ; pomeri drugi bit ulevo

pop esi

pop ecx

ret

BinToAsc ENDP

9.2.3 Ekstrakcija MS-DOS polja sa datumom

Kada je memorija od velike važnosti, sistemski softveri često pakuju više polja podataka

u jedan broj. Da bi se dobili ovi podaci, aplikacije često treba da ekstrahuju sekvencu bitova

koje se nazivaju stringovi bitova. Na primer, u režimu sa realnim adresama, MS-DOS funkcija

57h vraća datum poslednje modifikacije fajla u DX. Bitovi 0-4 predstavljaju dan između 1 i 31,

bitovi 5-8 su za mesec, a bitovi 9-15 za godinu. Ako je fajl poslednji put modifikovan 10.3.1999,

datum u fajlu će imati sledeći oblik u DX registru (broj za godinu se računa kao razlika do 1980.

godine):

Da bi se dobio jedan string bitova, treba pomeriti bitove u niži deo registra i obrisati

nebitne pozicije. Sledeći kod ekstrahuje dan iz datuma u fajlu tako što kopira DL i maskira

bitove koji ne pripadaju tom polju:

mov al,dl ; kopiranje DL

and al,00011111b ; brisanje bitova 5-7

mov day,al ; sačuvaj u day

Da bi se dobio mesec, pomeramo bitove 5-8 u donji deo registra AL pre maskiranja ostalih

bitova. AL se potom kopira u promenljivu:

Page 12: Vezba 9 - Celobrojna Aritmetika

12

mov ax,dx ; kopiranje DX

shr ax,5 ; pomeri udesno za 5 bitova

and al,00001111b ; obriši bitove 4-7

mov month,al ; sačuvaj u month

Godina (bitovi 9-15) je kompletno u DH registru. Kopiramo ga u AL i pomeramo udesno

za jedan bit:

mov al,dh ; kopiranje DH

shr al,1 ; pomeri udesno za 1

mov ah,0 ; obriši AH

add ax,1980 ; godina je razlika od 1980. godine

mov year,ax ; sačuvaj u year

9.3 Instrukcije za množenje i deljenje

Množenje celih brojeva u x86 asembleru se može vršiti kao 32-bitne, 16-bitne ili 8-bitne

operacije. U većini slučajeva, radi se sa EAX ili jednim od njegovih delova (AX, AL).

Instrukcije MUL i IMUL vrše neoznačeno i označeno množenje celih brojeva, respektivno.

Instrukcija DIV vrši neoznačeno deljenje, a IDIV označeno deljenje celih brojeva.

9.3.1 Instrukcija MUL

Instrukcija MUL ima tri verzije:

— Množenje 8-bitnog operanda sa AL registrom,

— Množenje 16-bitnog operanda sa AX registrom,

— Množenje 32-bitnog operanda sa EAX registrom.

Dva činioca uvek moraju biti iste veličine, a proizvod je duplo veće veličine. Ova tri

formata prihvataju registarske i memorijske operande, ali ne i neposredne:

MUL reg/mem8

MUL reg/mem16

MUL reg/mem32

Jedini operand u MUL instrukciji je množilac. U tabeli 2 su prikazani podrazumevani

množioci i proizvodi, u zavisnosti od veličine množioca. Pošto je odredišni operand duplo veći

u veličini od množilaca, do prekoračenja ne može doći. MUL setuje Carry i Overflow flegove

ako gornja polovina proizvoda nije jednaka nuli. Carry fleg se obično koristi kod neoznačene

aritmetike, tako da ćemo o njemu ovde govoriti. Kada se AX pomnoži sa 16-bitnim operandom,

na primer, proizvod se smešta u kombinaciju DX i AX registara. Odnosno, gornjih 16 bitova

proizvoda se smešta u DX, a donjih 16 u AX. Carry fleg se setuje ako DX nije jednak nuli, što

označava da proizvod ne može stati u donju polovinu implicitnog odredišnog operanda.

Page 13: Vezba 9 - Celobrojna Aritmetika

13

Tabela 2. Operandi MUL instrukcije

Množilac 1 Množilac 2 Proizvod

AL reg/mem8 AX

AX reg/mem16 DX:AX

EAX reg/mem32 EDX:EAX

Primeri

Sledećim iskazima se množi AL sa BL, a rezultat se smešta u AX. Carry fleg se briše (CF

= 0) jer je AH (gornja polovina proizvoda) jednak nuli.

mov al,5h

mov bl,10h

mul bl ; AX = 0050h, CF = 0

Sledećim iskazima se množi 16-bitna vrednost 2000h sa 0100h. Carry fleg je setovan zato

što gornja polovina proizvoda (u DX) nije jednaka nuli:

.data

val1 WORD 2000h

val2 WORD 0100h

.code

mov ax,val1 ; AX = 2000h

mul val2 ; DX:AX = 00200000h, CF = 1

Sledećim iskazima se množi 12345h sa 1000h, čime se dobija 64-bitni proizvod u

kombinaciji EDX i EAX registara. Carry fleg je obrisan jer je gornja polovina proizvoda u EDX

jednaka nuli:

mov eax,12345h

mov ebx,1000h

mul ebx ; EDX:EAX = 0000000012345000h, CF = 0

9.3.2 Instrukcija IMUL

Instrukcija IMUL vrši množenje sa označenim brojevima. Za razliku od instrukcije MUL,

IMUL čuva znak proizvoda. To se radi tako što se najviši bit donje polovine proizvoda proširuje

u gornje bitove proizvoda. Postoje tri formata ove instrukcije: sa jednim, dva ili tri operanda. U

formatu sa jednim operandom, množioci su iste veličine, a proizvod je duplo veći u veličini.

Page 14: Vezba 9 - Celobrojna Aritmetika

14

Format sa jednim operandom

Proizvod se smešta u AX, DX:AX ili EDX:EAX:

IMUL reg/mem8 ; AX = AL * reg/mem8

IMUL reg/mem16 ; DX:AX = AX * reg/mem16

IMUL reg/mem32 ; EDX:EAX = EAX * reg/mem32

Kao i kod MUL, pošto je veličina proizvoda duplo veća od množilaca, ne može doći do

prekoračenja. Takođe, Carry i Overflow flegovi se setuju ako gornja polovina proizvoda ne

predstavlja proširenje znaka donje polovine. Ova informacija se može koristiti kako bi se

odlučilo treba li odbaciti gornju polovinu proizvoda.

Format sa dva operanda

Proizvod se smešta u prvom operandu, koji mora biti registar. Drugi operand može biti

registar, memorijski operand ili neposredna vrednost. Slede 16-bitni formati:

IMUL reg16,reg/mem16

IMUL reg16,imm8

IMUL reg16,imm16

Slede formati sa 32-bitnim operandima koji pokazuju da množilac može biti 32-bitni

registar, 32-bitni memorijski operand ili neposredna vrednost (8 ili 32 bita):

IMUL reg32,reg/mem32

IMUL reg32,imm8

IMUL reg32,imm32

Ovaj format odseca proizvod na dužinu odredišnog operanda. Ako se izgube značajne

cifre, setuju se Carry i Overflow flegovi. Treba proveriti jedan od ovih flegova nakon izvršenja

IMUL instrukcije sa dva operanda.

Format sa tri operanda

Proizvod se smešta u prvom operandu. Drugi operand može biti 16-bitni registar ili

memorijski operand, koji se množi sa trećim operandom, 8-bitnim ili 16-bitnim neposrednim

operandom:

IMUL reg16,reg/mem16,imm8

IMUL reg16,reg/mem16,imm16

Registar ili memorijski operand dužine 32 bita se može pomnožiti sa 8-bitnom ili 32-

bitnom neposrednom vrednošću:

IMUL reg32,reg/mem32,imm8

IMUL reg32,reg/mem32,imm32

Ako se izgube značajne cifre pri izvršavanju IMUL, setuju se Carry i Overflow flegovi.

Treba proveriti status ovih flegova nakon izvršavanja IMUL instrukcije sa tri operanda.

Page 15: Vezba 9 - Celobrojna Aritmetika

15

Neoznačeno množenje

IMUL formati sa dva ili tri operanda se mogu koristiti i za neoznačeno množenje, budući

da je donja polovina proizvoda ista i za označene i za neoznačene brojeve. Postoji jedan

nedostatak kada se ovo radi: Carry i Overflow flegovi neće označavati da li je gornja polovina

proizvoda jednaka nuli.

Primeri sa IMUL

Sledeće instrukcije množe 48 sa 4, dobijajući +192 u AX. Iako je proizvod korektan, AH

nije proširenje znaka od AL, tako da je setovan Overflow fleg:

mov al,48

mov bl,4

imul bl ; AX = 00C0h, OF = 1

Sledeće instrukcije množe -4 sa 4, čime se dobija -16 u AX. AH predstavlja proširenje

znaka od AL, tako da je Overflow fleg obrisan:

mov al,-4

mov bl,4

imul bl ; AX = FFF0h, OF = 0

Sledeće instrukcije množe 48 sa 4, čime se dobija +192 u DX:AX. Registar DX

predstavlja proširenje znaka od AX, tako da je Overflow fleg obrisan:

mov ax,48

mov bx,4

imul bx ; DX:AX = 000000C0h, OF = 0

Sledeće instrukcije množe 32-bitne vrednosti 4.823.424 sa -423, čime se dobija

-2.040.308.352 u EDX:EAX. Overflow fleg je obrisan jer je EDX proširenje znaka od EAX:

mov eax,+4823424

mov ebx,-423

imul ebx ; EDX:EAX = FFFFFFFF86635D80h, OF = 0

Sledeće instrukcije demonstriraju format sa dva operanda:

.data

word1 SWORD 4

dword1 SDWORD 4

.code

mov ax,-16 ; AX = -16

mov bx,2 ; BX = 2

imul bx,ax ; BX = -32

imul bx,2 ; BX = -64

imul bx,word1 ; BX = -256

mov eax,-16 ; EAX = -16

mov ebx,2 ; EBX = 2

imul ebx,eax ; EBX = -32

imul ebx,2 ; EBX = -64

imul ebx,dword1 ; EBX = -256

Page 16: Vezba 9 - Celobrojna Aritmetika

16

IMUL instrukcije sa dva i tri operanda koriste odredišni operand koji je iste veličine kao

i množilac. Samim tim, moguće je da dođe do označenog prekoračenja. Treba uvek proveriti

Overflow fleg nakon izvršavanja ovakvih IMUL instrukcija. Sledeće instrukcije sa dva

operanda pokazuju označeno prekoračenje jer -64.000 ne može da stane unutar 16-bitnog

odredišnog operanda:

mov ax,-32000

imul ax,2 ; OF = 1

Sledeće instrukcije pokazuju format sa tri operanda, uključujući primer sa označenim

prekoračenjem:

.data

word1 SWORD 4

dword1 SDWORD 4

.code

imul bx,word1,-16 ; BX = -64

imul ebx,dword1,-16 ; EBX = -64

imul ebx,dword1,-2000000000 ; OF = 1

Merenje vremena izvršavanja programa

Programeri često porede performanse jedne implementacije koda u odnosu na drugu tako

što mere njihova vremena izvršavanja. MS-Windows API biblioteka omogućava neophodne

alate za ovaj posao, što je još više olakšano sa GetMseconds procedurom u Irvine32 biblioteci.

Procedura daje broj sistemskih milisekundi koje su prošle od ponoći. U sledećem primeru,

najpre se poziva GetMseconds, tako da zapamtimo početno vreme. Potom se poziva procedura

čije vreme izvršavanja želimo da izmerimo (FirstProcedureToTest). Na kraju, ponovo se

poziva GetMseconds i računa se razlika dve vrednosti koje je procedura vratila:

.data

startTime DWORD ?

procTime1 DWORD ?

procTime2 DWORD ?

.code

call GetMseconds ; početno vreme

mov startTime,eax

.

call FirstProcedureToTest

.

call GetMseconds ; krajnje vreme

sub eax,startTime ; računanje proteklog vremena

mov procTime1,eax ; čuvanje proteklog vremena

Naravno, postoji malo vreme koje se troši na dva poziva procedure GetMseconds.

Međutim, ovo vreme je nevažno kada se mere performanse između dve implementacije koda.

Page 17: Vezba 9 - Celobrojna Aritmetika

17

Ovde, pozivamo drugu proceduru koju želimo da testiramo, i čuvamo njeno vreme izvršavanja

(procTest2):

call GetMseconds ; početno vreme

mov startTime,eax

.

call SecondProcedureToTest

.

call GetMseconds ; krajnje vreme

sub eax,startTime ; računanje proteklog vremena

mov procTime2,eax ; čuvanje proteklog vremena

Na kraju ovoga, odnos između procTime1 i procTime2 ukazuje na relativne performanse

dve procedure.

Poređenje MUL i IMUL sa pomeranjem bitova

U starijim x86 procesorima, postojala je značajna razlika u performansama između

množenja pomoću pomeranja bitova i množenja sa MUL i IMUL instrukcijama. Možemo

koristiti proceduru GetMseconds kako bismo uporedili vremena izvršavanja ova dva tipa

množenja. Sledeće dve procedure vrše neprekidno množenje koristeći konstantu

LOOP_COUNT kako bi se odredio broj ponavljanja:

mult_by_shifting PROC

;

; Množi EAX sa 36 koristeći SHL, LOOP_COUNT puta.

;

mov ecx,LOOP_COUNT

L1: push eax ; sačuvaj originalni EAX

mov ebx,eax

shl eax,5

shl ebx,2

add eax,ebx

pop eax ; vrati EAX

loop L1

ret

mult_by_shifting ENDP

mult_by_MUL PROC

;

; Množi EAX sa 36 koristeći MUL, LOOP_COUNT puta.

;

mov ecx,LOOP_COUNT

L1: push eax ; sačuvaj originalni EAX

mov ebx,36

mul ebx

pop eax ; vrati EAX

loop L1

ret

mult_by_MUL ENDP

Page 18: Vezba 9 - Celobrojna Aritmetika

18

Sledećim kodom se poziva mult_by_shifting i prikazuje vreme izvršavanja.

LOOP_COUNT = 0FFFFFFFFh

.data

intval DWORD 5

startTime DWORD ?

.code

call GetMseconds ; početno vreme

mov startTime,eax

mov eax,intval ; množenje počinje

call mult_by_shifting

call GetMseconds ; krajnje vreme

sub eax,startTime

call WriteDec ; prikaz proteklog vremena

Nakon poziva mult_by_MUL na isti način, rezultujuća vremena na 4 GHz Pentium 4

procesoru su pokazala da se procedura sa SHL izvršila za 6,078 sekundi, a sa MUL za 20,718

sekundi. Drugim rečima, korišćenje MUL instrukcije je bilo 241 puta sporije. Međutim, kada

se isti programi pokrenu na Intel Core2Duo procesoru, vremena obe funkcije su potpuno ista.

Ovaj primer pokazuje da je Intel uspeo da značajno optimizuje MUL i IMUL instrukcije u

skorijim procesorima.

9.3.3 Instrukcija DIV

Instrukcija DIV vrši 8-bitno, 16-bitno i 32-bitno neoznačeno celobrojno deljenje. Jedini

registarski ili memorijski operand je delilac. Formati su:

DIV reg/mem8

DIV reg/mem16

DIV reg/mem32

U sledećoj tabeli je prikazan odnos između deljenika, delioca, količnika i ostatka.

Deljenik Delilac Količnik Ostatak

AX reg/mem8 AL AH

DX:AX reg/mem16 AX DX

EDX:EAX reg/mem32 EAX EDX

Primeri

Sledeće instrukcije vrše 8-bitno neoznačeno deljenje 83h sa 2, čime se dobija 41h i ostatak

1:

mov ax,0083h ; deljenik

movbl,2 ; delilac

div bl ; AL = 41h, AH = 01h

Page 19: Vezba 9 - Celobrojna Aritmetika

19

Sledeće instrukcije vrše 16-bitno neoznačeno deljenje 8003h sa 100h, čime se dobija 80h

i ostatak 3. DX sadrži viši deo deljenika, tako da se mora obrisati pre izvršenja DIV instrukcije:

mov dx,0 ; obriši deljenik, gornji deo

mov ax,8003h ; deljenik, donji deo

mov cx,100h ; delilac

div cx ; AX = 0080h, DX = 0003h

Sledeće instrukcije vrše 32-bitno neoznačeno deljenje koristeći memorijski operand kao

delilac:

.data

dividend QWORD 0000000800300020h

divisor DWORD 00000100h

.code

mov edx,DWORD PTR dividend + 4 ; viša dvostruka reč

mov eax,DWORD PTR dividend ; niža dvostruka reč

div divisor ; EAX = 08003000h, EDX = 00000020h

9.3.4 Deljenje označenih brojeva

Deljenje označenih brojeva je skoro identično sa deljenjem neoznačenih brojeva, sa

jednom važnom razlikom: deljenik mora biti u potpunosti proširen znakom pre deljenja. Najpre

pogledajmo instrukcije za proširenje znaka. Potom ćemo ih primeniti na instrukciju za označeno

deljenje, IDIV.

Instrukcije za proširenje znaka (CBW, CWD, CDQ)

Instrukcija CBW (convert byte to word) proširuje bit znaka registra AL u AH, čuvajući

znak broja. U sledećem primeru, 9Bh (u AL) i FF9Bh (u AX) su oba jednaki -101 decimalno:

.data

byteVal SBYTE -101 ; 9Bh

.code

mov al,byteVal ; AL = 9Bh

cbw ; AX = FF9Bh

Instrukcija CWD (convert word to doubleword) proširuje znak od AX u DX:

.data

wordVal SWORD -101 ; FF9Bh

.code

Page 20: Vezba 9 - Celobrojna Aritmetika

20

mov ax,wordVal ; AX = FF9Bh

cwd ; DX:AX = FFFFFF9Bh

Instrukcija CDQ (convert doubleword to quadword) proširuje znak od EAX u EDX:

.data

dwordVal SDWORD -101 ; FFFFFF9Bh

.code

mov eax,dwordVal

cdq ; EDX:EAX = FFFFFFFFFFFFFF9Bh

9.3.5 Instrukcija IDIV

Ova instrukcija vrši označeno deljenje, koristeći iste operande kao i DIV. Pre izvršavanja

8-bitnog deljenja, deljenik (AX) mora biti proširen sa znakom. Ostatak uvek ima isti znak kao

i deljenik.

Primer 1

Sledeće instrukcije dele -48 sa 5. Nakon izvršenja IDIV, količnik u AL je -9, a ostatak u

AH je -3:

.data

byteVal SBYTE -48 ; D0 heksadecimalno

.code

mov al,byteVal ; donja polovina deljenika

cbw ; proširi AL u AH

mov bl,+5 ; delilac

idiv bl ; AL = -9, AH = -3

Sledeća slika prikazuje kako se AL proširuje znakom u AX sa instrukcijom CBW.

Da bismo razumeli zašto je proširenje znakom deljenika neophodno, ponovićemo prethodni

primer bez proširivanja znaka. Sledeći kod inicijalizuje AH sa nulom tako da ima poznatu

vrednost, a potom deli bez korišćenja CBW:

.data

byteVal SBYTE -48 ; D0 heksadecimalno

.code

mov ah,0 ; gornji deo deljenika

mov al,byteVal ; donji deo deljenika

mov bl,+5 ; delilac

idiv bl ; AL = 41, AH = 3

Pre deljenja, AX = 00D0h (208 decimalno). IDIV deli taj broj sa 5, čime se dobija 41 i

ostatak 3. Ovo sigurno nije korektno rešenje.

Page 21: Vezba 9 - Celobrojna Aritmetika

21

Primer 2

Za 16-bitno deljenje neophodno je da AX bude prošireno znakom u DX. U sledećem

primeru se deli -5000 sa 256:

.data

wordVal SWORD -5000

.code

mov ax,wordVal ; deljenjik, donji deo

cwd ; proširenje AX u DX

mov bx,+256 ; delilac

idiv bx ; količnik AX = -19, ostatak DX = -136

Primer 3

Za 32-bitno deljenje je neophodno da EAX bude prošireno znakom u EDX. U sledećem

primeru se deli 50.000 sa -256:

.data

dwordVal SDWORD +50000

.code

mov eax,dwordVal ; deljenik, donji deo

cdq ; proširenje EAX u EDX

mov ebx,-256 ; delilac

idiv ebx ; količnik EAX = -195, ostatak EDX = +80

Svi statusni flegovi su nedefinisani nakon izvršavanja DIV i IDIV.

Prekoračenje prilikom deljenja

Ako se prilikom deljenja dobije količnik koji ne može da stane u odredišni operand, dolazi

do prekoračenja. To čini da procesor dobije prekid, a trenutni program se zaustavlja. Na primer,

sledeće instrukcije generišu prekoračenje zato što je količnik (100h) suviše veliki za AL:

mov ax,1000h

mov bl,10h

div bl ; AL ne može da smesti 100h

Kada se ovaj kod izvršava na MS-Windows, dobija se poruka o grešci prikazana na slici

1. Slična poruka se dobija kada pokušate da delite sa nulom.

Slika 1. Poruka o prekoračenju prilikom deljenja

Page 22: Vezba 9 - Celobrojna Aritmetika

22

Kako bi se smanjila verovatnoća pojavljivanja prekoračenja, treba koristiti 32-bitne

delioce i 64-bitne deljenike. U sledećem kodu, delilac je u EBX, a deljenik je smešten u 64-

bitnu kombinaciju EDX i EAX:

mov eax,1000h

cdq

mov ebx,10h

div ebx ; EAX = 00000100h

Da bi se sprečilo deljenje sa nulom, testirajte delilac pre deljenja:

mov ax,dividend

mov bl,divisor

cmp bl,0 ; provera delioca

je NoDivideZero ; nula? Prikaži grešku

div bl ; nije nula: nastavi

.

.

NoDivideZero: ;(prikaži "Pokušaj deljenja sa nulom")

9.3.6 Implementacija aritmetičkih izraza

Implementacija aritmetičkih izraza na prvi pogled deluje kao radnja koju je najbolje

ostaviti za pisce kompajlera. Međutim, možete naučiti kako kompajleri optimizuju kod.

Takođe, možete implementirati bolju proveru na greške od kompajlera tako što ćete proveriti

veličinu proizvoda nakon operacija množenja. Većina kompajlera jezika visokog nivoa ignoriše

gornja 32 bita proizvoda kada se množe dva 32-bitna operanda. U asembleru, međutim, možete

koristiti Carry i Overflow flegove kako biste videli da li proizvod može da stane u 32 bita.

Primer 1

Implementirati sledeći C++ iskaz u asembleru, koristeći neoznačene 32-bitne cele

brojeve:

var4 = (var1 + var2) * var3;

U ovom slučaju možemo raditi s leva na desno (prvo sabiranje, pa množenje). Nakon

druge instrukcije, EAX sadrži sumu var1 i var2. U trećoj instrukciji, EAX se množi sa var3 i

proizvod se smešta u EAX:

mov eax,var1

add eax,var2

mul var3 ; EAX = EAX * var3

jc tooBig ; neoznačeno prekoračenje?

mov var4,eax

jmp next

tooBig: ; prikaz poruke o grešci

Ako instrukcija MUL generiše proizvod veći od 32 bita, instrukcija JC skače na labelu

koja prikazuje grešku.

Page 23: Vezba 9 - Celobrojna Aritmetika

23

Primer 2

Implementirati sledeći C++ iskaz, koristeći neoznačene 32-bitne cele brojeve:

var4 = (var1 * 5) / (var2 - 3);

U ovom primeru, postoje dva podizraza unutar zagrada. Leva strana se može dodeliti u

EDX:EAX, tako da nije neophodno proveravati na prekoračenje. Desna strana se dodeljuje u

EBX:

mov eax,var1 ; leva strana

mov ebx,5

mul ebx ; EDX:EAX = proizvod

mov ebx,var2 ; desna strana

sub ebx,3

div ebx ; konačno deljenje

mov var4,eax

Primer 3

Implementirati sledeći C++ iskaz, koristeći označene 32-bitne cele brojeve:

var4 = (var1 * -5) / (-var2 % var3);

Možemo početi sa izrazom na desnoj strani i smestiti njegovu vrednost u EBX. Pošto su

operandi označeni, važno je proširiti sa znakom deljenik u EDX i koristiti IDIV instrukciju:

mov eax,var2 ; početak desne strane

neg eax

cdq ; proširivanje znakom deljenika

idiv var3 ; EDX = ostatak

mov ebx,edx ; EBX = desna strana

Potom, računamo izraz na levoj strani, a proizvod smeštamo u EDX:EAX:

mov eax,-5 ; početak leve strane

imul var1 ; EDX:EAX = leva strana

Na kraju, leva strana (EDX:EAX) se deli sa desnom stranom (EBX):

idiv ebx ; krajnje deljenje

mov var4,eax ; količnik

9.4 Sabiranje i oduzimanje sa proširenom preciznošću

Sabiranje i oduzimanje sa proširenom preciznošću predstavlja sabiranje i oduzimanje

brojeva koji su skoro beskonačne veličine. U C++-u, pisanje programa kojim se sabiraju dva

1024-bitna cela broja ne bi bilo lako. Ali u asembleru, instrukcije ADC (add with carry) i SBB

(subtract with borrow) služe za ove operacije.

Page 24: Vezba 9 - Celobrojna Aritmetika

24

9.4.1 Instrukcija ADC

Instrukcija ADC sabira izvorišni operand sa sadržajem Carry flega i odredišnim

operandom. Formati instrukcije su isti kao i za ADD, a operandi moraju biti iste veličine:

ADC reg,reg

ADC mem,reg

ADC reg,mem

ADC mem,imm

ADC reg,imm

Na primer, sledeće instrukcije sabiraju dva 8-bitna cela broja (FFh + FFh), čime se dobija

16-bitna suma u DL:AL, koja je 01FEh:

mov dl,0

mov al,0FFh

add al,0FFh ; AL = FEh

adc dl,0 ; DL/AL = 01FEh

Na sledećoj slici je prikazano kretanje podataka tokom dva koraka sabiranja. Najpre, FFh

se sabira sa AL, čime se dobija FEh u AL registru i setuje se Carry fleg. Potom, i 0 i sadržaj

Carry flega se sabiraju sa DL registrom:

Na sličan način, sledeće instrukcije sabiraju dva 32-bitna cela broja (FFFFFFFFh +

FFFFFFFFh), čime se dobija 64-bitna suma u EDX:EAX: 00000001FFFFFFFFh:

mov edx,0

mov eax,0FFFFFFFFh

add eax,0FFFFFFFFh

adc edx,0

Primer sa proširenim sabiranjem

Sledeća Extended_Add procedura sabira dva proširena cela broja iste veličine. Koristeći

petlju, radi sa proširenim celim brojevima kao da su paralelni nizovi. Kako sabira svaki par

vrednosti u nizovima, uzima u obzir i vrednost prenosa iz sabiranja koje je izvršeno u

prethodnoj iteraciji petlje. Ova implementacija podrazumeva da su brojevi smešteni kao nizovi

bajtova, ali ovaj primer se lako može modifikovati za sabiranje nizova dvostrukih reči:

;--------------------------------------------------------

Extended_Add PROC

;

; Računa sumu dva proširena cela broja smeštena

; kao nizovi bajtova.

; Prima: ESI i EDI ukazuju na dva cela broja,

Page 25: Vezba 9 - Celobrojna Aritmetika

25

; EBX ukazuje na promenljivu koja će čuvati sumu

; ECX ukazuje koliko bajtova treba sabirati.

; Memorija za smeštaj sume mora biti za jedan bajt

; veća od ulaznih operanada.

; Vraća: ništa

;--------------------------------------------------------

pushad

clc ; brisanje Carry flega

L1: mov al,[esi] ; uzmi prvi broj

adc al,[edi] ; saberi sa drugim brojem

pushfd ; sačuvaj Carry fleg

mov [ebx],al ; smesti delimičnu sumu

add esi,1 ; ažuriraj sva tri pokazivača

add edi,1

add ebx,1

popfd ; vrati Carry fleg

loop L1 ; ponovi petlju

mov byte ptr [ebx],0 ; obriši viši bajt sume

adc byte ptr [ebx],0 ; saberi sa preostalim prenosom

popad

ret

Extended_Add ENDP

Sledeći kod poziva ovu proceduru, prosleđujući joj dva 8-bitna cela broja. Treba paziti da

se alocira dodatan bajt za sumu, u slučaju da se generiše prenos prilikom sabiranja dva gornja

bajta brojeva.

.data

op1 BYTE 34h,12h,98h,74h,06h,0A4h,0B2h,0A2h

op2 BYTE 02h,45h,23h,00h,00h,87h,10h,80h

sum BYTE 9 DUP(0)

.code

main PROC

mov esi,OFFSET op1 ; prvi operand

mov edi,OFFSET op2 ; drugi operand

mov ebx,OFFSET sum ; suma

mov ecx,LENGTHOF op1 ; broj bajtova

call Extended_Add

; Prikaz sume.

mov esi,OFFSET sum

mov ecx,LENGTHOF sum

call Display_Sum

call Crlf

Program daje sledeće na svom izlazu. U ovom slučaju se dobija prenos:

0122C32B0674BB5736

Procedura Display_Sum iz istog programa prikazuje sumu u pravilnom redosledu,

počevši sa najvišim bajtom, pa potom ide ka nižim bajtovima:

Page 26: Vezba 9 - Celobrojna Aritmetika

26

Display_Sum PROC

pushad

; ukaži na sledeći element niza

add esi,ecx

sub esi,TYPE BYTE

mov ebx,TYPE BYTE

L1: mov al,[esi] ; uzmi bajt iz niza

call WriteHexB ; prikaži ga

sub esi,TYPE BYTE ; ukaži na prethodni bajt

loop L1

popad

ret

Display_Sum ENDP

9.4.2 Instrukcija SBB

Instrukcija SBB oduzima i izvorišni operand i vrednost u Carry flegu od odredišnog

operanda. Mogući operandi su isti kao i za ADC instrukciju. Sledeći kod vrši 64-bitno

oduzimanje. Setuje EDX:EAX na 0000000700000001h i oduzima 2 od ove vrednosti. Donja

32 bita se prva oduzimaju, setujući Carry fleg. Potom se gornja 32 bita oduzimaju, uključujući

Carry fleg:

mov edx,7 ; gornja polovina

mov eax,1 ; donja polovina

sub eax,2 ; oduzmi 2

sbb edx,0 ; oduzmi gornju polovinu

Na slici 2 je prikazano kretanje podataka tokom dva koraka oduzimanja. Najpre, vrednost

2 se oduzima od EAX, čime se dobija FFFFFFFFh u EAX. Carry fleg se setuje jer je neophodna

pozajmica kada se oduzima veći broj od manjeg. Potom SBB instrukcija oduzima i 0 i sadržaj

Carry flega od EDX.

Slika 2. Oduzimanje od 64-bitnog celog broja koristeći SBB