Asembler Dili (Assembly Language) 3
ATLAMALAR ve ATLAMA
komutlari
Atlama komutlari döngü
komutlarindan farkli olarak istedigimiz sartlara göre dallanmayi saglar. Atlama
komutlari karsilastirma komutlari ile veya karsilastirma komutlari olmadan da
kullanilabilir. Ancak özel durum ve hassas degerler için karsilastima komutlari
mutlaka gereklidir. Bunun için öncelikle karsilastirma komutlarini ögrenmemiz
gerekir.
Karsilastirma komutlari
bayrak registerin bitlerine göre hareket eden, bayrak registerin ilgili
bitlerinin set veya reset yaparak sartlari olusturan komutlardir. Daha önce
CMPS komutundan bahsetmistim. Bu komut ESI ve EDI ile karsilatirma yaptigi gibi
ECX ile uzun ölçekli karsilatirmalarda yapar. Karsilastirma komutlari genel
olarak CMP komutu altinda toplanmistir. CMP komutu aynen registerin
adreslemelerinde anlattigim gibi çok genis bir adresleme sahasina sahiptir.
cmp reg1,reg
cmp reg1,deger
cmp [addr],reg1
cmp [addr]deger
gibi karsilatirma olanaklari mevcuttur. Kombine kullanimlarda bu etki daha da
arttirilir. Örnegin bir hafiza bölgesinde analiz yapmamamiz gerekiyorsa ve
sadece sayilari bulmak istiyorsak <0 ve >9 olarak mantik formülü
kurabiliriz. Bunuda "eger veri 0 sayisi ASCII (0 ASCII sembolu
30h) sembolünden küçükse ve 9 sayisi ASCII (9 ASCII sebolu 39h)
sembolünden büyükse bu bir sayi degildir diyebiliriz. Bunu Assembler olarak
ifade etmek istersek :
cmp byte ptr [bölge],30h
ve
cmp byte ptr [bölge],39h
ise dogru degilse yanlis
seklinde sembolik olarak ifade ederiz. Burada geriye kalan sadece karsilastirma
kosuluna göre dallanma yapan atlama komutlaridir. Tam halini yazacak olursak:
cmp byte ptr [bölge],30h
jl düsük
cmp byte ptr [bölge],39h
ja büyük
Yani ASCII kodlarini bildigimiz 0 ve 9 sayilarinin sinirlari içindemi seklinde
bir sinama yapmis oluyoruz. CMP komutu gibi bit karsilastirmasi yapan TEST
komutuda vardir. TEST komutunun özünde bit karsilatirmasi vardir ve özellikle
lojik islemlerde çok kullanilir.
TEST Komutu
TEST komutunun CMP
komutundan en büyük farki karsilastirilan degerlere mantiksal AND isleminin
uygulanmasidir. AND komutunun islevini daha sonra ayrintili olarak
görecegiz ancak kisaca bahsetmem gerekirse AND islevi karsilastirma sonucunda iki
bitte eger 1 ise sonuç biti 1 (set olur) diger durumlarda 0 (reset) olur.
Tabi sonuç tam tersi oldugu için bu karsilastirma sonuçlari yukarida
bahsettigim sartli karsilastirma komutlarinin sonuçlarindan farkli (tersi)
olur. Ayni sekilde atlama komutlarinda oldugu gibi standart bayrak (flag
register) bitlerini kullanir.
AND islevi ( her sütunu
yukaridan asagiya olarak inceleyeyin )
|
Kaynak bit |
1 |
0 |
1 |
0 |
|
Karsilastirilan bit |
1 |
1 |
0 |
0 |
|
Islem sonucu |
1 |
0 |
0 |
0 |
Sartli atlamalar
Karsilastima komutlarini
kisaca anlattiktan sonra karsilastirma sonuçlarini nasil yönlendirecegimizide
ögrenmemizin zamani geldi. Yaptigimiz her karsilastirma sonucu ne olursa olsun
bayrak registeri etkiler. Daha önce iç-içe döngülerde anlattigim gibi
karsilastirma durumlarida yigin bölgesine atilarak o andaki durum korunabilir.
Bunun için PUSHF, PUSHFD ve POPF,POPFD olarak özel komutlar olusturulmustur. Bu
komutlar o andaki bayrak registerin degerini yigin (ESP ile gösterilen bölgeye)
bölgesine atabilir. Sonra tekrardan alip o andaki durum tekrar ortaya
çikarilabilir. Bu durum ortaya baska bir özelligi çikarmistir. Normalde bayrak
registeri sadece karsilastirmalar ile degistirmiyoruz, yigin üzerinden alinan
bayrak register degerini lojik komutlar ile degistirerek tekrar bayrak
registere aktarir ve istedigimiz ortami olusturabiliriz. Bunlari yapmaya gerek
kalmadanda bazi özel komutlar ile istedigimiz ortami olusturabiliriz. Örnegin
CLC ve STC komutlari bizim bayrak registerin CARRY bitini degistirmemizi
saglar. Programlar içinde Carry biti anahtar gibi kullanilabilir.
Iste bütün bu islemlerin yapilma amaci programin içinde istedigimiz sartlari
olusturmak ve bu olusturdugumuz bu sartlara göre programa yön vermektir. Cümle
olarak ifade edersek " a sayisi b sayisindan büyükse baska sayi seç degilse
a sayisini aktar" seklindeki programa uygulayacagimiz algoritmalari bunlar
sayesinde yapariz.
Birde karsilatirma komutu
kullanmadan yapabilecegimiz dallanmalar var. Her ne sekilde olursa olsun bir
programin akisinda eger registerlerden birisi sifir yada sifir oluyorsa mutlaka
Z (Zero flag) set (yani 1) olur. Öyleyse CMP yada TEST komutu kullanmadan da
atlama yapabiliriz.
Atlama komutlariyla ilgili küçük bir tüyo vermek gerekirse, sartli atlama
komutlarinin yanina gelen "e" harfi ile kendi sarti ile birlikte esit
olmasi durumunuda kontrol eder. Ayrica sartli atlama komutlari +127 -128
aralikla atlama yaptigi gibi opkodu degiserek (bizim birsey yapmamiza gerek
olmadan derleyici otomatik olarak yapar) 16 ve 32 bit atlamada mevcuttur.
Asagidaki listede belirttigim gibi JMP komut haricindeki diger tüm atlama
komutlari eger sartli yerine gelmiyorsa kendinden sonraki opkod ile yoluna
devam eder.
Simdi sartli atlama
komutlarini inceleyelim.:
|
JMP |
Bu komut sartsiz
atlayan tek komuttur. Hiçbir sarta bagli olmadan atlar ve kendisinden sonraya
devam etmez. |
|
JA-JAE |
Büyükse atlama
komutudur. JAE ise büyük ve esit ise dallanmadir. |
|
JB-JBE |
Küçük ise atlama
komutudur. JBE ise küçük ve esit ise dallanmadir. |
|
JC |
C (Carry) biti 0 ise
atlama yapar. |
|
JCXZ - JECXZ |
Eger ECX (yada CX)
register 0 ise dallanma yapar. |
|
JE |
Eger esit ise. Bu
istedigimiz bir degeri sartlandirmamiza yarar. |
|
JG
-JGE |
Eger büyükse, JA dan
farki Z ve SO bayrak bitlerini kullanmasi. |
|
JL-JLE |
Eger küçükse, JLE ise
hem küçük hemde esitse dallanma yapar. |
|
JNA-JNAE |
Eger yukarisindaysa,
tasma varsa, JA gibi ancak kullandigi bitler farklidir. |
|
JNB-JNBE |
Eger asagidaysa, JB
gibi ancak kullandigi flag farkli. |
|
JZ |
Eger 0 ise atlama
yapar. |
|
JNZ |
Eger 0 degilse atlama
yapar. |
|
JS |
Eger S (Sign = isaret)
biti set (yani 1) ise. |
|
JNS
|
Eger S (Sign =
isaret) biti reset (yani 0) ise. |
|
JO |
Eger tasma (Overflow)
biti set ise. |
|
JNO |
Eger tasma (Overflow)
biti reset ise. |
|
JP |
Eger esitlik (Parity)
biti set ise. |
|
JNP
|
Eger esitlik (Parity)
biti reset ise. |
Ayni sekilde 16 ve 32 bitlik atlama komutlarida vardir. Isimleri aynidir yalniz
opkodlari farklidir. Derleyiciler son asamadan bunu uzakliklari hesaplayarak
kendileri tayin ederler. Ancak kendimiz hex olarak opkod yazmak istersek ve 8
bitlik bir dallanma yada tam tersini kullanirsak o komutun alanina ve
sinirlarina göre hareket eder. Atlama komutlari bu kadarla sinirli
degildir. Ben burada en çok kullanilan ve kullanim alani en genis olanlari
verdim. Diger atlama komutlari özel amaçlar için kullanilabilir.
Atlama komutlarinin temelinde karsilastirma ve bu karsilastirma sonucunda
sartlari olusturuyorsa atlayacagin yer vardir. Atlayacagin yere kisaca LABEL
yada ETIKET diyoruz. Editör ile bir assembler programi yazarken eger bir atlama
komutu kullaniyorsak mutlaka atlayacagi yeride belirtmemiz gerekiyor. Aksi
halde hata mesaji alir ve programi çalistiramayiz. Bütün Assembler dillerinde
etiket daima harf ile baslar ve sonunda mutlaka" iki nokta üst-üste"
olur. Örnegin:
buyukse:
altama12:
L20001:
gibi. Burada küçük bir kural daha vardir, etiket isimlerinde büyük- küçük harf
hassasiyeti vardir. Hepsi büyük harf veya hepsi küçük harf olarak kullanilacak
diye bir kural yok ancak atlama komutunun sembolu ile etiket ayni harf sekline
sahip olmadir. Etiketler derleyiciler için semboliktir ve derleme sirasinda
neyin nereye gidecegini - atlayacagini sembolize eder.
Örnekler:
1) Burada yazi içinden 'h' harfi araniyor ve bulunca "buldum"
isimli etikete gidiyor. Burada sayi verilmedigi için arama islemi 'h' harfini
buluncaya kadar devam ediyor.
veri db
'Assembler hizlidir',0
....
lea esi, veri
ara1:
lodsb
cmp al,'h'
je buldum
jne ara1
buldum:
.....
2)
yazi db 'CW dostlarina selamlar!',0
key db 0
....
lea esi, yazi
mov ecx,5
xor eax,eax
xor ebx,ebx
topla:
lodsd
add ebx,eax
loopnz topla
cmp
ebx,12345678
jz crc_ok
mov byte ptr
[key],0
ret
crc_ok:
mov byte ptr
[key],1
ret
Burada da verilen yazi
toplaniyor ve istedigimiz sonucun çikip - çikmadigina bakiliyor. Eger sonuç
dogru ise "key" olarak belirtigimiz hafiza bölgesini 1 yapiyor
degilse yoluna devam edip 0 yapiyor. Basit bir algoritma. Burada
"key" bölgesi illaki 1 veya 0 yapilmak zorunda degil. Kullanici
programin aksina göre istedigi gibi degerler kullanabilir.
CMPXCHG Komutu
CMPXCHG komut iki komutun
birlesik tek bir komut olarak tasarlanmasi sonucu ortaya çikmistir. Daha önce
gördügümüz CMP ve XCHG komutlarinin islevini kombine bir sekilde yapar. Bu
komut A registerler (AL, AX, EAX) için tasarlanmistir. CMPXCHG komut ile EAX
register ile baska bir deger yada register karsilastirilir ve sonuç ayni ise
karsilastirilan deger ile A register degeri yerdegistirir. Optimize kullanimlar
için gerçekten ideal bir komuttur.
CMPXCHG8B komutu
Ayni CMPXCHG komutu
gibidir ancak 64 bitlik bir islem kapasitesi vardir. Bu komut CMPXCHG komutu
gibi EAX registerle beraber EDX registeride asil olarak kullanir. ECX :EBX
register degerler EDX:EAX ayni ise ikisi yer degistirir. Daha büyük islemler
için idealdir.
JMP KOMUTU
JMP komutu bagimsiz bir
atlama komutudur. Bu komut ile gösterdigimiz yere atlanir ve program buradan
itibaren devam eder. JMP komutu sartli döngüler içinde geri dönüsüm atlamasi
içinde kullanilir. Ancak mutlaka döngüyü kesecek bir kontrolde eklemek gerekli
yoksa döngü sonsuz olacak dolayisiyla islem yerine getirilemeyecektir.
Örnek döngü:
lea esi,yazilar
dis1:
lodsb
cmp al,'A'
jz buldum
jmp short dis1
buldum:
......
Burada görüldügü gibi yazilar bölgesinden 'A' harfini ariyoruz. Bu aramanin
bir limiti yok. Buluncaya kadar ESI registerin degeri LODSB ile yükseltilip AL
degeri alinacak. Eger bulursa "buldum" olarak belirttigimiz yere
atlayacak ve döngüden çikilmis olacak. Eger alinan deger 'A' degilse JMP
SHORT DIS1 ile direkt atlama yapilarak döngü devam edecek. Burada SHORT kisa
mesafelerdeki atlamalar için kullanilan bir ek. JMP komutu uzun ve kisa atlama
olarak ikiye ayriliyor. Eger hiçbir sey belirtmezsek derleyici uzun olarak
algilar ve bu opkod 6 byte uzunlugundadir. Kisa olan ise sadece 3 byte
uzunlugundadir ve bu sayede programda 3 bytelik bir alan optimizesi yapmis
oluyoruz. SHORT ekini kullanmak zorunlu degildir.
CALL ve RET
komutu
CALL komutu sartli atlama
komutu degildir. Programin akisi içerisinde istenildigi zaman baska bir yere
sartsiz atlanarak oradaki kodun çalismasi saglananilir. CALL sartli degildir
ancak RET komutu ile kombine çalisir. Bunun en büyük nedeni ise CALL komutunun
diger atlama komutlarinda olmayan bir özelligindir. CALL komut çagrildigi yerde
islemlerini tamamladiktan sonra RET komutu ile çagrildigi yerin sonrasina devam
eder. Böylece program bir akiskan düzen üstüne oturtulmasi ve çagrilan
prosedurun (kod blogu) sonuçlarinin alinip kullanilmasi saglanmis olur. CALL ve
RET komutlari yigin bölgesiyle çalisir. Zaten geriye dönüs yigin bölgesine
atilan CS ve IP register degerleri ile mümkün olur. Bu yigina atma islevi
tamamen CPU tarafindan olusturulur ve programci isinin bitip geriye dönmesini
istedigi yere RET komutunu koyar. Bu komut o andaki yigin bölgesinden CS ve IP
register degerlerini alir ve geriye dönüsümü saglar. Ancak burada dikkat
edilecek bir nokta var. Eger çagrilan prosedur içinden yigina atma islemi
yapilip tekrar geriye alinmadiysa yigin bölgesi yanlis degerleri verecektir
dolayisiyla program yanlis yere dönüs yapacaktir. Eger özel bir algoritma
olusturulmuyorsa prosedurun basindaki yigin degeri ile RET komutuna ulasan
yigin bölgesi degeri ayni olmak zorundadir. Eger ayni olmuyorsa bunu RET
komutunun degerini alacagi yeri isaret ederekte yapabiliriz. Normalde RET
komutu kendi basina kullanilir. Ancak asagida oldugu gibi RET komutunun
geri dönüs degerlerini "ayarlama" yaparak gösterebiliriz.
RET 0008
Bu komut ile RET komutu
geri dönüs degerlerini (adresini) yigin bölgesinin 8 byte öncesinden
almaktadir. Yani ESP-8 (yada SP-8) seklinde olmaktadir.
CALL komutu ile çagrilan kod
blogundan istenildigi kadar yine CALL komutu kullanilabilir. Ayni kendisinde
oldugu gibi çagrilan içsel CALL komutlari yine RET komutu ile çagrildigi yere
geri dönecektir.
CALL komutunun en iyi
özelliginden birisi prosedur olarak kullanildiginda yaninda yigin bölgesi
vasitasiyla parametlerler kullanilabilmesidir. Standart Windows API
fonksiyonlarida bu düzene göre çalisirlar.
CALL
Fnt,param1,param2,param3,......
gibi. Bu durumda
parametreler sirasiyla yigin bölgesine atilirlar ve çagrim yapilan yerde istenildigi
gibi kullanilirlar. Derleyiciler prosedur sonunda RET komutunun yanina otomatik
olarak parametre sayisi kadar düsüs degeri koyar ve dönüsümün dogru yere
olmasini saglar.
xor eax,eax
xor ebx,ebx
call denemeproc,1,2,3
......
denemeproc proc p1:dword, p2:dword, p3:dword
mov eax,p1
mov ebx,p2
add eax,ebx
imul eax,eax,p3
ret
denemeproc endp
Bu örnekte denemeproc
isimli prosedur (kod blogu) 1,2,3 sayilari ile çagriliyor. Prosedürün basina
gelince yigin bölgesinde CS, EIP, 1,2,3 degerleri olacaktir. Prosedurde bu
degerleri kullanmak için hepsine bir simge veriyoruz.Burada p1,p2,p3 gibi.
Sonra bunlarin degerlerini veriyoruz ki prosedur içinde dogru kullanilim
olussun. Islem yapiliyor ve sonuçta bir EAX degeri olusuyor. Tekrar belirtmem
gerekirse burasi tamamen programcinin hakimiyetinde, sonuçta mutlaka EAX
register olmak zorunda degil. Ayni sekilde parametre sayisi ve degisken
isimleride tamamen kullanicinin kontrolündedir. Ben burada örneklemek için bu
degerleri ve registerleri kullandim. Prosedure (kod blogu) RET komutu ile
bitiyor ve geri dönüs basliyor. Biz burada sadece RET komutunu vererek yigin
bölgesi - atlama bölgesi dogrulamasini derleyiciye birakiyoruz. Ancak herhangi
bir debugger ile bakinca burada RET komutunun yaninda 000Ch degerinide
görecegiz. Yani RET 000Ch olacaktir. Geri dönüsüm islemi benim örnekte .....
seklinde belirttigim yere olacaktir. Yani çagrilan komutun sonrasina.
Yigin üzerinde atlama
yapmak
Bu standart bir islem
degildir. Sadece programcilarin kullandigi ve güzel bir yöntemdir. Bu yöntem
RET komutunun geri dönüs için yigin bölgesini kullanmasi esasina dayanir.
Herhangi bir register yada herhangi bir deger yigin bölgesine atilir (PUSH ile
yada direkt olarak MOV [ESP+4],deger gibi) Daha sonra RET komutu uygulanarak
istenilen adrese dönmesi saglanilir.
mov eax,401000h
push eax
ret
Bu örnekte görüldügü gibi EAX registere 401000 degeri veriliyor ve PUSH EAX ile
yigina atiliyor. Sonra RET komutu uygulaniyor. RET komutu dogrudan yigin
bölgesindeki 401000 degerini alacak ve o adrese dönüsüm yapacaktir. Bu islem
register kullanmadan da asagidaki gibi kisaca yapilabilir:
push 401000h
ret
Bu dönüsüm sonunda elbette yigin bölgesinden çagrim adresinin degeri düsülerek
ESP (ve SP) register degeri degisecektir.
Ben bu yöntemi daha çok grup eslemeleri ile kullaniyorum. Yani beser byte
aralikli atlama tablosu olusturup yapilan matematiksel isleme göre (offset
degerini toplayarak) atlamayi sagliyorum. Sizlerde kendiniz böyle kisa ve
yararli yöntemler gelistirebilirsiniz.
CALL FAR ve IRET komutu
Her ne kadarki Windows
ortaminda CALL FAR SEG:OFT seklinde bir komuta rastlamamis olsanizda bu çagrim
sekli gerçek modda yani DOS ortaminda bir hayli önemlidir. En çok kullanildigi
alan daha önce bahsettigim TSR' ler konusundadir. Buna göre CALL komutu baska
bir segmentte bir offseti çagirmakta ve yigin degerlerini buna göre
saklamaktadir. Korumali modun yapisindan dolayi bu komutun korumali modda pek
kullanma ihtiyaci duymayiz fakat sistemde yüksek düzeyli interrupt
programlamarinda kullanilmaktadir.Gerçek modda ise (DOS) interrupt
vektörlerinin alinan ve baska bir yere yönlendirilen (hook edilen)
interrupt'un (kesme) vektör degerleri mutlaka sisteme geri dönüs yapmak
(callback) zorundadir. Yoksa sistem kararsiz duruma düserek kilitlemeye,
resetlenmeye neden olacaktir. Bunun için vektör degerleri mutlaka tutulup
interrupt rutini sonunda çagrilmalidir. CALL FAR komutu bunu tek ve komut
olarak saglar. Ayrica yeri gelmisken belirtmekte yarar var, normal CALL çagrim
islemlerinin geri dönüsümü saglayan RET komutu yerine IRET komutu tahsis
edilmistir. IRET komutunun RET komutundan en büyük farki yigin bölgesine CS, IP
registerden baska FLAG (bayrak) registeride atmasidir. IRET komutu korumali
modda IRETD olarak kullanilir ve bu 32 bitlik IRET komutu demektir.
JMP FAR Komutu
JMP FAR komutuda CALL FAR
komutu gibidir kullanilisi aynidir. Ancak CALL FAR gibi geriye dönüsü yoktur.
JMP komutu daha önce anlattigim gibi sartsiz ve direkt atlama yapar ve islem
oradan itibaren devam eder.
Mantiksal komutlar ve
islemleri
Lisede mantik isimli bir ders gördük. Isin içinde not olunca ögrenme istegimiz
yapaylassada mantik dersi matematik gibi önemli bir dersdi. Bu dersde bir
önerme sonunda sonuc vardir yada yoktur seklince bir genel bir tanim vardir. Bu
mantigin temelini olusturur ve yine "üçüncü hali imkansizligi" gibi
genel bir teoriyide kapsar. Iste bilgisayarlarda bilgi alis-verisini ve çalisma
prensiplerini hep bu temel üzerine oturmustur. Bilgisayarda mantik denilince
aklimiza ikili sayi sistemi gelmeli çünkü makina kodunda mantik komutlari ve
islevleri hep bitler üzerinde olur. Daha önceki konularda bahsettigimiz gibi 8
bit 1 byte etmekte. Kisaca bir sayi, sembol yada harf 8 tane 1 veya 0 'dan
(yada sadece birisinden) olusur. Bitler üzerinde yapilan islemler dogal olarak
sayinin degerinde de degisklige yol açacaktir. Biti setlemek (1 yapmak) yada
resetlemek (sifirlamak) aslinda toplama ve çikarma islemleri gibidir. Toplama
ve çikarma islemleride asil olarak bitler üzerinde degisiklik yaparak
islevlerini gerçeklestiririz. Tabi olarak mantiksal islemlerin sonuçlari
toplama çikarma islemlerini sonuçlari ile ayni degildir, her mantiksal komutun
farkli sartlari vardir ve sonuçlar bu kurallara göre tayin olur.
Mantiksal islemlerde VE, VEYA, DEGIL, VEYA DEGIL gibi mantik karsilastirmalari
vardir. Bunlar assemblerda AND, OR, XOR, NOT komutlariyla islevlerini
gerçeklestirirler. Buradaki amaç en iyi seçenekleri bulmak ve istenildigi
sekilde gruplama yapabilmektir.
AND mantiksal komutu
AND komutu asagida verdigim tabloya göre karsilastirma yaparak bitleri setler
yada resetler. Bu islem birisi asil sayi digeri hedef sayi olmak üzere iki
sayinin AND islemine tabi tutulmasi ile olur. Bütün mantiksal islemlerde oldugu
gibi AND isleminde de sonuc hedef sayiya yüklenir. AND komutu
register-register, register -adres, adres- register seklinde aynen matematiksel
toplama ve çikarma komutu gibi adreslenebilir. Ancak bu islemin adreslerle
ilgili olmayip matematiksel - mantiksal oldugunu unutmayalim. Asagidaki liste
diger mantiksal komutlar içinde geçerlidir.
and al,bl ; register-register
and eax,1234 ; register - sayi
and dword ptr [label1],9876 ; adres-sayi
and dword ptr [label1],edx ; adres - register
gibi birden çok kullanilim seçenegi mevcuttur. Simdi AND komutunun tablosunu
inceleyelim. Yukaridan asagiya dogru siralama yaptim.
AND Mantiksal Tablosu
|
ASIL |
1 |
1 |
0 |
0 |
|
HEDEF |
1 |
0 |
1 |
0 |
|
SONUC |
1 |
0 |
0 |
0 |
Bu tabloda gördügünüz gibi
asil ile hedef 1 veya 0 olarak ikili sistemde deger aliyorlar. Bu degerlere
göre AND islemi karsilastirma yapiyor.
asil deger 1 ise ve hedef degerde 1 ise sonuc 1 olacaktir.
asil deger 0 ise ve hedef degerde 1 ise sonuc 0 olacaktir.
asil deger 1 ise ve hedef degerde 0 ise sonuc 0 olacaktir.
asil deger 0 ise ve hedef degerde 0 ise sonuc 0 olacaktir.
Örnek :
mov eax,0ffh ; eax = 0ffh = 11111111b
mov ebx,0aah ; ebx = 089h = 10001001b
and eax,ebx ; eax = 089h = 10001001b
yukaridaki tabloyu dikkate alarak incelerseniz 1-1 olanlarin sonuçlari 1;
digerlerinin sonuçlarinin 0 oldugunu görürürüz.
OR Mantiksal Komutu
OR mantiksal komutu AND mantiksal komutuna göre biraz daha genis açilidir.
Yukaridaki tabloda görüldügü gibi AND islevi ancak iki bitinde 1 (set) olmasi
durumuda 1 oluyor. Ancak OR mantiksal isleminde sadece ikisi 0 (reset) ise
sonuç 0 olacaktir. Diger durumlarda sonuc hep 1 olacaktir. Tabloyu yukaridan
asagiya dogru inceleyin.
OR Mantiksal Tablosu
|
ASIL |
1 |
1 |
0 |
0 |
|
HEDEF |
1 |
0 |
1 |
0 |
|
SONUC |
1 |
1 |
1 |
0 |
Örnegin:
mov eax,12345678h ; eax = 12345678h = 00010010001101000101011001111000b
mov ebx,87654321h ; ebx = 87654321h = 10000111011001010100001100100001b
or eax,ebx ; eax = 97755779h = 10010111011101010101011101111001b
örnegin yukaridaki tablodan bakarak incelerseniz sadece iki bitin reset (0)
olmasi durumunda 0 oldugu görülür. Diger durumlarda sonuç daima 1 (set)
olacaktir.
XOR Mantiksal Komutu
XOR mantiksal komutu mantiksal komutlar içinde nerdeyse en çok bilinendir.
Genelde sifreleyiciler, paketleyiciler gibi koruma uygulamalarinda XOR ile
degerleri degistirmek yada paket için tablo olusturmak alisilagelmistir. Bu
veya diger komutlar kesinlikle CPU tasariminda yalnizca sifreleme yada
paketleme gibi islemler için tasarlanmamistir. Bu tamamen programcilarin
tercihidir. XOR mantiksal komutu OR komutunun özel bir seklidir. Bu mantiksal
komutta sart eger asil bit ile hedef bit ayni ise sonuç 0 (reset); farkli ise
sonuç 1 (set) olur. Buna göre XOR islemine tabi tutulan bitlerin ikiside 1 veya
0 ise sonuç daima 0 olacaktir. Eger farkli ise sonuç 1 olacaktir.
XOR Mantiksal Tablosu
|
ASIL |
1 |
1 |
0 |
0 |
|
HEDEF |
1 |
0 |
1 |
0 |
|
SONUC |
0 |
1 |
1 |
0 |
Örnegin:
mov eax,12345678h ; eax = 12345678h = 00010010001101000101011001111000b
mov ebx,87654321h ; ebx = 87654321h = 10000111011001010100001100100001b
xor eax,ebx ; eax = 95511559h = 10010101010100010001010101011001b
NOT Mantiksal komutu
NOT komutu "degil" anlamina gelir. Bunu bitlerin degili olarak
düsünürsek 1 ise 0 ; 0 ise 1 demek oluyor. Yani tersine bitleri tam tersine
çevirmis oluyoruz. Bu komut iki deger ile birlikte degilde dogrudan hedef
üzerinde islem yapar. Bunun için basta belirttigim adresleme seklide sadece NOT
Register seklini alir. Bu komutun asil sayisi ile sonuç sayisi toplanirsa
ortaya en yüksek sayi çikar. Asagidaki örnekte 32 bitlik bir islem oldugu için
sonuç 0ffffffffh olacaktir.
NOT Mantiksal Tablosu
|
ASIL |
1 |
0 |
|
SONUC |
0 |
1 |
Örnegin :
mov eax, 12345678h ; eax = 12345678h = 00010010001101000101011001111000b
not eax ; eax = EDCBA987h = 11101101110010111010100110000111b
12345678+edcba987 = 0ffffffffh
NOT EAX isleminden sonra sayinin bitlerini tam tersine döndügüne dikkat edin.
NEG Mantiksal komutu
NEG komutu negatife çevirme yapmak için kullanilir. NEG komutuda NOT gibi
register ile dogrudan kullanilir. Bu islem sonucunda CPU sonuç sayisini C
bayragi ile toplanarak tamamlama yapilir. Bunun için asil sayi ile hedef sayiyi
birbirleriyle toplarsak sonuç daima 0 olur.
NEG Mantiksal Tablosu
|
ASIL |
1 |
0 |
|
SONUC |
0 |
1 |
Örnegin :
mov eax, 12345678h ; eax = 12345678h = 00010010001101000101011001111000b
not eax ; eax = EDCBA988h = 11101101110010111010100110001000b
12345678h+edcba988h = 0
Mantiksal Bit çevirme
ve kaydirma komutlari
Bit çevirme ve kaydirma komutlari pek çok alanda kullanilir. Grafiksel
islemlerde, çevrim islemlerinde, sayaçlarda,... Bit kaydirma kendi arasinda
kaydirma komutlari ve çevirme komutlari olarak ikiye ayrilir. Kaydirma
komutlarida aritmetik ve logical olarak ikiye ayrilirlar. Bunlarin arasinda
islevsel bir farklilik vardir. Kaydirma komutlari biti sonuç 0 oluncaya kadar
saga yada sola dogru kaydirir. Kaydirilan bit yokolur ve tersine islem yapilsa
bile geriye dönemez. Çevirme komutlari ise bitleri çevirerek dönüsüm yapar ve
bit sayisina bagli olarak tekrar eski degerine ulasir. Çevirme komutlarinda
hiçbir bitin degeri kaybolmaz. Daima çevrimiçi olarak kalir. Iki komut grubunda
da saga ve sola kaydirma mevcuttur ve ingilizcedeki left, right kelimelerinin
basharfleri ile belirtilirler. Bu komutlar yardimci register ile kullanilarak
blok kaydirma veya çevirme islemlerine tabi tutulabilirler. Yardimci register
degismez olarak CL registerdir ve burada bir sayaç görevini üstlenir.
Registerdeki sayinin bitini su kadar kaydir diye komut verebiliriz. Özellikle
aritmatiksel kaydirma komutlari register-register kullanilimi ile kaydirmak
islevine sahiptirler. Burada kaydirma sayisi registeri 0-31 sayilari olmak
zorunda çünkü su anda
bu komutlar en fazla 32 bitlik registerleri kullanabiliyor.
Mantiksal kaydirma ve çevirme komutlari bildigimiz matematiksel bölme ve çarpma
islemlerinin aynisi yaparlar. Saga dogru yapilirsa çarpma, sola dogru yapilirsa
bölme isleminin aynisini yapmis olurlar.
Asagidaki örnekler ile sanirim bunlar daha iyi anlasilacak.
Mantiksal kaydirma komutlari
Örnek olarak elimizde eax registerde 00111000 seklinde bir sayimiz var. Bu
sayiyi 1 bitlik kaydirma islemine tabi tutuyoruz:
mov eax,00111000 ; eax = 00111000
shl eax,1 ; eax = 01110000
shl eax,1 komutu ile eax registerdeki bitleri sola dogru (shl= sola , shr =
saga) kaydirdik. Örnektede görüldügü gibi ilk bit 0 oldu ve ilk set olan bit
sola dogru kaydi. Sonuçta sayinin degeri iki katina çikmis oldu. Çünkü basamak atladi.
Eger biz bu islemi 5 kere daha yaparsak bütün bitler sola dogru kayacagi ve
yerlerin resetleyecegi için sonuç 0 olacaktir. Yani sayi döngü içinde mutlaka 0
degerine ulasacaktir. Buradaki 0 degeri olarak bahsettigim bitlerin tamaminin
sifirlanmasi ve sayinin degerini tamamen kaybetmesi oluyor.
shl eax,1 ; 01110000 <-
shl eax,1 ; 11100000 <-
shl eax,1 ; 11000000 <-
shl eax,1 ; 10000000 <-
shl eax,1 ; 00000000 <-
Eger sayiya shr islemine
(saga kaydirma) tabi tutarsak:
shr eax,1 ; 01110000
->
shr eax,1 ; 00111000 ->
shr eax,1 ; 00011100 ->
shr eax,1 ; 00001110 ->
shr eax,1 ; 00000111 ->
shr eax,1 ; 00000011 ->
shr eax,1 ; 00000001 ->
shr eax,1 ; 00000000 ->
Görüldügü gibi sonuç eger sayinin toplam biti kadar yapilirsa saga yada sola
olmasi farketmezsizin
daima 0 olacaktir.
Aritmatik kaydirmalara örnek vermek gerekirse:
mov ax,1234 ; ax = 1234
mov cl,4 ; Kaç bitlik kaydirma islemi yapacak?
sar ax,cl ; saga dogru kombine 4 bit kayacak
Diger bir örnek :
mov ax,9978
mov cl,7
sal ax,cl ; sola
dogru 7 bit kaydirilir.
Ayni sekilde SHR ve SHL komutlarida yardimci register olmadan yanina verilen
parametre kadar kaydirilabilir.
mov ax,4523
shr ax,5
yada
mov eax,9742
shl eax,2
Ayrica 64 bitlik islemler için SHLD ve SHRD komutlarida vardir. Bunlar ayni SHL ve SHR seklinde
çalisir ancak bit alanlari 64 bite kadar çikar.
Mantiksal Döndürme komutlari
Mantiksal döndürme komutlari ayni kaydirma komutlari gibi bitleri saga yada
sola kaydirir yalniz bitlerin degeri kaybolmaz her kayan bitin yerine bir
önceki bit gelir. Son bit ilk bir ile yer degistirir veya ilk bir son bit ile
yer degistirir. Eger döndürülecek registerin degeri 0 degilse ve degerini
yokedecek baska bir islem yapilmiyorsa degeri asla 0 olmaz. Çevrimi bir daire
gibi düsünebiliriz. Ayni
dünyanin günes etrafinda dönüsü gibi belli bir süre sonra bitler tekrar ayni
yerlerine gelecektir. Yine kaydirma komutari gibi tek tek yada yardimci
register vasitasiyla birden fazla kombine çevrim mümkündür.
Örnegin:
mov ax,0111000 ; eax = 1110000
rol ax,1 ; eax = 1100001
görüldügü gibi bastaki bit sola dogru çevrilir ve tasan bir ilk bitin yerine
koyulur.
mov ax,0111000 ; 0111000 <-
rol ax,1 ; 1100001 <-
rol ax,1 ; 1000011 <-
rol ax,1 ; 0000111 <-
tam terside yapilabilir.
mov ax,0111000 ; 0111000
->
ror ax,1 ; 0011100 ->
ror ax,1 ; 0001110 ->
ror ax,1 ; 0000111 ->
Ayrica RCR ve RCL çevirme komutlarida CL register ile kombine kullanilir.
Islevleri aynidir ancak C bayragi ile birlikte kullanilir. Bu sayede döndürme
islemini bayrak bazinda kontrol altina alabiliriz. Örnegin döndürülen sayinin 0 olmasi durumda.
mov ax,0111000
mov cl,5
rcl ax,cl
yada
mov ax,0111000
mov cl,5
rcr ax,cl
gibi rahatça kullanabiliriz.
0 yorum yazılmıştır