ÚÄÄÄ
ÚÄÄÄ ÚÄ
ÚÄ
ÚÄ ÚÄ
ÚÄ ÚÄ
ÚÄÚÄ ÚÄÚÄ
ÚÄ ÚÄ
ÚÄÄ ÚÄ
ÚÄÄ ÚÄ
ÚÄÄÄÄÄÄÄÄÄ
ÚÄÄ ÚÄ
Ú ÚÄ Ja
ljublju ASSEMBLY
ÚÄÄ ÚÄÄ
ÚÄ ÚÄ ÚÄ
ÚÄ VIII.rész
ÚÄÄ ÚÄÄ
ÚÄÄÄÄ ÚÄ
ÚÄ
Lássunk
neki az osztásnak és társainak. A következő
utasításoknál NEM lehet közvetlen értékeket
használni. Csak regisztert, vagy memóriatartalmat.
MUL utasítás
(unsigned MULtiplication):
|
Használat:
MUL forrás
Ha
a forrás byte, akkor az AX=AL*forrás műveletet végzi
el. Ha a forrás szó, akkor az AX*forrás műveletet
végzi el. Ekkor az eredmény DX:AX-ben adja vissza, vagyis
az eredmény nagyobb helyiértékű szavát DX-ben,
az alacsonyabbat AX-ben adja meg. CF és OF akkor lesz 1, ha byte
forrás estén AH-ban, szó forrás estén
pedig DX-ben van legalább egy 1 értékű bit.
Példa:
MOV
AL,56h ; AL-ben
az egyik tényező, a másik 45h, ez most
MOV CL,45h ;
CL-ben van ,de lehet máshol is, 45h byte
MUL CL ;
ezért az eredmény AX-ben képződik és 172eh
lesz
MOV
AX,3476h ; AX-ben az egyik
tényező, a másik szó (1256h)
MOV CX,1256h ;
ezért eredmény DX:AX-ben lesz. A szorzás
MUL CX ;
eredménye 03c1eba4h. Ebből DX-be a felső szó
; vagyis 03c1h kerül, míg AX-be az alsó,
0eba4h
IMUL utasítás
(Integer MULtiplication):
|
Használat:
IMUL forrás
Ez
előjelesen szoroz.
Ha a forrás byte, akkor AL-lel szorozza
és az előjeles eredmény AX-ben lesz. Ha a forrás
szó, akkor AX-szel szorozza és a szintén előjeles
eredmény DX:AX-ben lesz a MUL-nál leírt felbontásban.
CF
és OF akkor lesz 1, ha byte forrás esetén AH az AL-nek,
vagy szó forrás esetén DX az AX-nek előjeles bővítése.
DIV utasítás
(unsigned DIVision):
|
Használat:
DIV forrás
Előjel
nélküli osztás.
Ha a forrás byte, akkor AX regisztert
elosztja forrással. A hányados AL-be kerül, a maradék
pedig AH-ba. Ha a forrás szó, akkor DX:AX regisztert (így
együtt 32 bitesek) osztja el forrással. Ekkor a hányados
AX-be, a maradék DX-be megy.
A
jelzőbiteket nem bántja.
Példa:
MOV
AX,3465h ; az osztandó AX=3465h, az osztó
CL=56h
MOV CL,56h ;
az eredmény AL=9bh, ez a hányados
DIV CL
; és AH=53h, ez a maradék
MOV
DX,2345h ; Az osztandó felső szava
DX-ben, alsó szava AX-ben
MOV AX,8765h ;
mivel duplaszót osztunk, az osztó CX-ben
MOV CX,6543h ;
az eredmény: a hányados AX=592bh és
DIV CX
; a maradék DX=3a24h
Az
osztásnál vigyázni kell, mert ha 0-val osztunk, vagy
a hányados nem fér el a neki kiszabott helyre, akkor osztáshiba,
INT 00h hajtódik végre, ami gyakorlatilag a program végét
jelenti, ugyanis a DOS ilyenkor visszaveszi a vezérlést
és kilépteti a programot. Ez ellen vagy saját INT
00h megírásával (ehhez még nem tudtok eleget)
vagy odafigyeléssel lehet védekezni. Ha elképzelhető,
hogy az osztó helyén 0 van (pl.: memóriatartalommal
osztasz), akkor osztás előtt ellenőrizd, hogy nem nulla-e. Ha pedig
egy szót kis számmal osztasz, akkor inkább a dupla
szavas osztást használd DX-ben 0-val, mert így biztos
nem lesz a hányados túl nagy.
zzzzIDIV utasítás
(Integer DIVision):
|
Használat:
IDIV forrás
Előjeles
osztást végez. Egyébként ugyanaz, mint DIV.
A maradék előjele megegyezik az osztandó előjelével. Következnek
a bitforgató/léptető utasítások. A számláló
minden utasításban egy közvetlen byte vagy a CL lehet.
A cél mindenhol regiszter vagy memóriatartalom lehet.
SAL utasítás
(Shift Arithmetic Left):
|
Használat:
SAL cél, számláló
A
célt számlálószor balra lépteti, mégpedig
úgy, hogy a jobb oldalon 0-t hoz be, a bal oldalon kilépő
bitet pedig CF-be írja.
Példa:
SAL
AL,3 ; legyen AL=11010011b,
ezt 3-szor léptetve
;
AL=10011000b-t kapunk és CF=0 lesz, mert
;
ez lépett ki utoljára a bal oldalon
SAL AX,CL ;
AX=1111011000111011b és CL=6, ekkor a léptetés után
;
AX=1000111011000000b lesz és CF=1, mert az utolsó
;
kilépő bit 1 volt
SAR utasítás
(Shift Arithmetic Right):
|
Használat:
SAR cél, számláló
A
célt számlálószor jobbra lépteti úgy,
hogy a jobb oldalon kilépő bit CF-be kerül, a legfelső bit
pedig ismétlődik. Ez az ismétlődő bit kerül SF-be is.
Példa:
SAR
AL,3 ; AL=10011010b legyen,
ekkor AL=11110011b és CF=0 lesz
SHL utasítás
(SHift logical Left):
|
Ugyanaz
mint SAL.
SHR utasítás
(SHift logical Right):
|
Használat:
SHR cél, számláló
A
célt számlálószor jobbra lépteti, mint
a SAR, de ez a bal oldalon 0-kat hoz be mindig.
Példa:
SHR
AL,2 ; legyen AL=11000011b, ekkor AL=00110000b
és CF=1 lesz
ROL utasítás
(ROtate Left):
|
Használat:
ROL cél, számláló
A
célt számlálószor balra forgatja. A forgatás
során a cél legmagasabb helyiértékű bitje
a legalacsonyabba kerül, a többi bitet pedig eggyel balra lépteti
a proci. A legmagasabb helyiértékű bit a CF-be is belekerül.
Példa:
ROL
AL,4 ; legyen AL=11001011b, az utasítás
után AL=10111100h
;
vagyis helyet cserélt az alsó és a felső 4 bit
;
CF pedig 0, mert utoljára egy 0 lépett ki bal oldalon
ROL
BX,CL ; Legyen CL=6 és BX=110011111000011b,
az utasítás után
;
BX=111000011110011b és CF=1, mert ez lépett ki
;
utoljára a bal oldalon
ROR utasítás
(ROtate Right):
|
Használat:
ROR cél, számláló
A
célt számlálószor jobbra forgatja úgy,
hogy a cél legkisebb helyiértékű bitje a legmagasabba
kerül, valamint belemásolódik CF-be is. A többi
bit jobbra lép.
Példa:
ROR
AL,3 ; AL=11010001b, ekkor AL=00111010b
és CF=0 lesz
RCL utasítás (Rotate through
Carry Left):
|
Használat:
RCL cél, számláló
A
célt számlálószor balra forgatja a CF felhasználásával.
Úgy kell tekinteni, mintha CF lenne a cél legmagasabb helyiértékű
bitje és ezután balra forgatnánk.
Példa:
RCL
AL,2 ; legyen AL=11100101b és
CF=0, ekkor AL=10010101b és
;
CF=1 lesz
RCR utasítás
(Rotate through Carry Right):
|
Használat:
RCR cél, számláló
A
célt számlálószor jobbra forgatja CF segítségével.
Itt Łgy kell
venni, hogy CF a cél legkisebb helyiértékű
bitje és így forgatunk.
Példa:
RCR
AL,2 ; legyen AL=11100101b és
CF=1, így AL=11111001b és
;
CF=0 lesz
Ezek
az utasítások nagyon hasznosak lehetnek, mikor egy számot
szorozni vagy osztani kell 2 hatványával. Hogy miért?
Mert ha egy számot eggyel balra tolunk, akkor az olyan, mint ha
2-vel szoroztuk volna. Gondolj arra, hogy mi van akkor, ha egy decimális
szám végére egy nullát írunk. A szám
10-szeresére nő. Egy bináris szám balra léptetése,
ha a jobb oldalon egy 0-t hozunk be, pontosan ugyanazt jelenti mintha
egy 0-t a végére írtunk volna, ezért a számrendszer
alapjával szorzott értéke lesz. A számrendszer alapja
most éppen 2. Jobbra forgatásnál éppen a fordítottja,
vagyis 2-vel osztódik. DE!! Negatív számok osztásánál
más a hányados képzése, mint IDIV esetén.
A hányadost lefele kerekíti a léptetéses osztás,
azaz a kapott hányados kisebb lesz, mint a valódi. Pozitív
és negatív számokra is igaz, hogy ha többet
léptetünk jobbra, akkor a maradékot nem jól
kapjuk meg, mert a léptetés után CF mindig csak a
legutolsó lépés maradékát (volt-e vagy
sem) tárolja. Ezért az ilyen módŁ osztásokat
ajánlott lépésenként elvégezni.
Nézzünk
egy példát erre a lefele kerekítésre!
Léptessük -13-at jobbra háromszor,
azaz osszuk el 8-cal. -13 kettes komplemensben ábrázolva
11110011b. Hajtsuk végre a SAR
11110011b,3
utasítást. Azért a SARt, mert ez megőrzi a szám
eredeti előjelét
I. léptetés:
11111001b CF=1
Az eredmény átírva
decimálissá -7 és van egy maradék, mert CF=1.
Már most látszik a lefele kerekítés (angolul
ezt úgy mondják, hogy a "negative infinity", azaz
a negatív végtelen felé kerekítenek, így
talán érthetőbb, mi az a lefele kerekítés
ebben az esetben), mert -13/2 az testvérek között is
-6 és maradt -1, míg itt -7 és marad +1.
II.
léptetés: 11111100b CF=1
A hányados -4 és
CF=1 maradékot jelez. Tehát -13/4 az -4 és marad
+1. Ez így nem igazán jó, mert -4*4+1=-15. A baj
az, hogy lazán elfelejtettük az előző maradékot. így
az igazi maradék 11b azaz +3. Így már helyes az eredmény,
de itt is eltér az IDIV-től, ami -3 hányadost és
-1 maradékot adna vissza.
III.
léptetés: 11111110b CF=0
A hányados -2 és
CF=0 nem jelez maradékot. Tehát -13/8=-2 és marad
0? Á, dehogy...! Megint nem figyeltük az előző maradékokat,
ezért a tényleges maradék 011b=+3. Kész is
vagyunk mert -2*8+3=-13!! Az IDIV bezzeg -1 hányadost és
-5 maradékot adna vissza és ez is jó (sőt ez egyezik
a suliban tanultakkal mert -13-ban a 8 egyszer van
meg), mert -1*8-5=-13.
Összegezve:
-13/8 pontos értéke -1 és -2 között van.
Lefele (negatív végtelen felé) kerekítve -2-t
választom hányadosnak és ehhez kapom meg a maradékot,
ami itt +3 lesz. Felfele (azaz 0 felé) kerekítve pedig a
-1-et választom eredménynek és ehhez számolok
maradékot. Remélem világos!?
A
következő cikkben elmondom a logikai műveleteket és végre
visszatérünk a programhoz, ahonnan indultunk, de most már
felfegyverkezve mindenféle hasznos tudással
Lucifer
of ZeroBit
|