Assembly Programlama Dili (Bölüm -3 ) Asm Komutları

Programlama ve Script dilleri konusunda bilgi paylaşım alanıdır.
Cevapla
Kullanıcı avatarı
mayhemious
Kilobyte4
Kilobyte4
Mesajlar: 648
Kayıt: 17 Kas 2007, 13:14
cinsiyet: Erkek

Assembly Programlama Dili (Bölüm -3 ) Asm Komutları

Mesaj gönderen mayhemious »

ASSEMBLY KOMUTLARI :



Evet arkadaslar geldik komutlar bölümüne ,assembly ‘de komutları kendi aralarında bölümlere ayırmak bence daha iyi olacaktır.Böylece komutların ne islem yaptıklarını hangi komutların nereler de kullanıldıklarını anlamak daha kolay olur.Ayrıca verecegim bazı püf noktalar ile de komutlara bakarak ne üzerinde etkili olduklarını hemen kavrayacaksınız.Assembly ‘ de komutları Transfer Komutları, Matematiksel Komutlar, Mantık Komutları, ,Döngü Komutları , Atlama Komutları ve Kaydırma Komutları olarak inceleyecegiz .Çok gibi görünse de siz bir sefer bu makaleyi okudugunuz zaman bir çogunu hemen kavrayacaksınız.Neyse Transfer Komutları ile baslayalım.

Transfer (Veri Tasıma )Komutları :

Bu grup içerisindeki komutlar herhangi bir bilgiyi register-register, bellek-register ve register-bellek bölgeleri arasında transfer etmek için kullanılır.Baslıcaları su sekildedir.

MOV Komutu: Arkadaslar önceki bölümlerde birkaç örnek verirken bu komutu kullanmıstım.simdi bu komutu yakından inceleyecegiz anlasılması kolay bir komut.Adını zannedersem “Move”(tası) kelimesinden almıs.Kullanımı :



Mov Hedef , Kaynak



mov register, register

mov bellek, register

mov register, bellek

mov [adres+register], register

mov register, [adres+register]

vb .sekildedir.Yalnız dikkat edin burada ters bir durum var ,ilk önce hedef sonra ise kaynak adres yazılır mesela Windows da bir veri kopyalarken dikkat ettiyseniz orada önce kaynak ,sonra da hedef bölge yazılır,burada ise tam tersidir.Assembly komutlarının hepsinde önce komut sonra hedef ve araya ( , )virgül koyarak kaynak adres yazılır.Diger gösterimler ise Mov komutu ile bu bellek ve registerler (kaydedici) arasında ne sekilde veri transferi yapılabilecegini gösterir.Bu komutun bayrak registerleri üzerinde herhangi bir etkisi yoktur.Unutmadan sunu da söyleyeyim tasıma yaptıgınız veri ile register aynı degerde olmalıdır.

MOV AX, 1525h
MOV DS, AX

Yukarıda ki örnekte 2 byte lik 1525h (hexdecimal) deger AX (AX burada 16 bit yani 2 bytedir)registere aktarılıyor.Sonra ise AX deki deger DS ‘ye (Data Segment) yazdırılıyor.

LEA (Load Effective Address) Komutu :Bu komut ise Etkin Adresi Yükle anlamındadır.Bu komut Mov komutuna benzetilebilir ancak aralarında etkin bir fark vardır.Mov komutu ile registere bir yerdeki(hafızadan veya registerden) deger yüklersiniz.Oysa LEA komutu ile registere o yerdeki degeri degil,oranın adresini yüklersiniz.Bu sekilde iki yada üç komut ile yapılacak bir islemi tek bir komut ile yapmıs olursunuz. Kısaca ;LEA komutunun genel kullanım amacı herhangi bir register’a bir bellek adresini yüklemektir. Asagıdaki kullanım sekli ve örnek açıklayıcı olacaktır.

lea register, adres
lea register, [adres]



dizi db ‘Merhaba’,0



Bu sekilde ki örnekte lea eax, dizi seklinde yazarsam eax registere ‘Merhaba’ degeri degil de,bulundugu yerin adresi yüklenir. Böylece biz bu verinin basından itibaren istedigimiz gibi çalısma yapabiliriz. Bu komutun da bayrak registerleri üzerinde herhangi bir etkisi yoktur.

MOVS (Move String)Komutu: Arkadaslar en güçlü dizi (String)veri transfer komutu olan MOVS hafızanın bir alanından diger bir alanına veri aktarımı yapar.Yanına aldıgı B,W,D takıları ile ayrı bir opkod halini alır ve buna göre bitte islem yapar. Diger bir deyisle, bu komut hafızadan- hafızaya veri transferi yapar. Bir MOVS komutu SI(Source index) ile adreslenen hafıza degerini, DI (Destination index) ile adreslenen hafıza alanına aktarır.Yani bir nevi Kaynak-Hedef iliskisi.

MOVSB = 1 byte islem için - BYTE(8 bit)
MOVSW = 2 byte islem için - WORD(16 bit)
MOVSD = 4 byte islem için - DOUBLEWORD(32 bit)

LODS (Load)komutu: Bu da MOVS komutu gibi yanına aldıgı ekin boyutuna göre 8 ile 32 bit arasında islem gücü kazanır. Temel görevi SI (yada ESI) registerin gösterdigi noktadaki degeri alıp bit degerine göre (AL, AX, EAX) registere (Load)yüklemektir. Ayrıca LODS komutu degeri yükledikten sonra SI registerin degerini kullanılan bit degerine göre arttırarak sonraki veriye göre ayarlamıs olur. Bu 8 bit lik veri için 1 byte- 16 bit lik bir veri için 2 byte - ve 32 bit lik bir veri çin 4 byte otomatik olarak toplanacak demektir.

LODSB = 1 byte islem için (8 bit)
LODSW = 2 byte islem için (16 bit)
LODSD = 4 byte islem için (32 bit)

CMPS (Compare)Komutu : CMP komutunun bir degisigi olan bu komut tekil olarak digerleri gibi yanına aldıgı ek ile orantılı olarak bit sayısı kadar islem(Karsılastırma) yapar.Yine bu komut SI (veya ESI) ve DI (veya EDI) registerler ile birlikte çalısır.Bu komut tüm karsılastırma ve test komutları gibi bayrak registeri etkiler. Bu komutu kısaca SI register ile gösterilen bölgeyi DI ile gösterilen bölge ile karsılastırır diye açıklayabiliriz.. Bu komut ileride görecegimiz karsılastırma komutları gibi registerler karsılastırması yapmaz. Karsılastırma sonucunu ZF (zero flag) ile alırız. Eger iki bölgede verdigimiz bir degerin karsılastırılması sonucu aynı ise ZF set (1) olur. Eger yanlıs ise ZF reset (0) olur.

XCHG (exchange) Komutu : Exchange komutu iki degerin karsılıklı olarak yer degistirilmesi için kullanılır.Karsılıklı olarak registerler birbirlerinin degerlerini alırlar. Tabi yine degisim yapılacak degerlerin de aynı boyda olması gerekmektedir.Bu komut da flag register’lar üzerinde herhangi bir degisiklik yapmaz. Kullanımı çok basittir arkadaslar.

Xchg register,bellek

Xchg bellek,register



Mov ax,1234 ( ax =1234 örnekteki degerler 16 bittir.)

Mov bx,5678 (bx = 5678 )

Xchg ax,bx (ax =5678 - bx =1234 degerler yer degisti)

XLAT Komutu :XLAT komutu esas olarak BX (veya EBX) ve AL registeri esas alarak çalısır Genellikle tablo olarak tasarlanan dizilere erismek için kullanılır. AL kaydedicisine tablonun elemanlarından birini yükler. Bu komutu asagıdaki örnege bakarak daha iyi anlayabilirsiniz.

Tablo DB A, B, C, D, E, F

Bu tablonun 4. elemanını AL’ye yüklemek istersek;

MOV AL, 04 ; 04 .eleman sorguluyoruz.İndeks degeri (Diziler 0 dan baslar)
LEA BX, Tablo ; BX’e (taban kaydedici) Tablonun ofset adresi yükleniyor
XLAT ; Tablonun 4. elemanına erisilip E’nin ASCII karakterin hex karsılıgı AL’ye yükleniyor(AL=105)

PUSH-PUSHA-PUSHF—POP-POPA-POPF Komutları :

Arkadaslar Yıgın (Stack) konusunu önceki bölümde anlatmıstım. Bu yıgın dedigimiz bölge döngülerin döngü sayısını tutmak içinde kullanılır. Ayrıca Bayrak registerlerin (F veya EF) durumu da yıgın içinde saklanılabilir.Matematiksel islemlerde de yıgın kullanılır. Bu anlamda yıgın çok önemlidir.İste bu yıgına veriyi atmak ve geri almak için de PUSH ve POP komutlarını kullanırız. PUSH ve POP komutları kullanıldıgında yıgın bölgesinin isaretçisi olan SP (Stack Pointer ) kaydedicisinin durumu da degisir. Tabiî ki bu yıgına attıgımız veya yıgından çektigimiz degerin boyutuna baglıdır. 2 byte’lık deger ile islem yaparak yıgına 2 byte lık bir deger atarsak (mesela bu AX kaydedicisinin içerigi olabilir) SP’nin degeri de 2 byte azalır.Anlamadıysanız bir önceki konudan stack konusunu tekrar okuyabilirsiniz…

PUSH komutu herhangi bir bilgiyi bellegin stack adı verilen bölümüne kaydetmek için kullanılır;diye tanımlayabiliriz.PUSH komutu ile stack üzerine atılacak bilgi en az 16-bit uzunlugunda olmalıdır.Komut asagıdaki gibidir.

PUSH deger

Yukarıda “deger” ile gösterilen kısım daha öncede belirttigim gibi 16-bit uzunlugunda olmalıdır. Bunun yanı sıra “deger” ile gösterilen kısım sabit bir deger alamaz. Yani PUSH ile stack üzerine yazabilecegimiz deger ya bir register içerisindeki deger yada bir bellek bölgesindeki deger olmalıdır.

mov eax,1234 AX = 1234h degeri atıyorum

push eax AX ‘teki deger simdi STACK ‘ta ve SP-2 olarak azaldı.

POP komutu ile de stack üzerinden bilgi okuması yaparız. Yani PUSH komutu ile yıgına gönderdigimiz bilgileri POP komutu ile de geri okuruz. Okunacak bilgi 16-bit uzunlugunda olmalıdır.POP komutu ile alınan bilgi stack üzerine yazılan son bilgidir. PUSH ve POP komutları ile bilgi transferi yapılırken yazılan ve okunan bilgilerin sıralaması önemlidir, yine bir önceki konuda açıkladım. Programlar yazılırken stack üzerindeki islemlerde hesaplama hatası yapmamak için buna dikkat etmek gerekir.

mov eax,1234 = yukarıdaki örnegimiz

push eax = satck ‘a atıldı

xor eax,eax = eax ‘i bosaltıyorum

pop eax = eax-1234 degeri geri yükledim.

PUSHA-POPA :Bazen bütün register’ların yıgında saklanması gerekebilir. Örnegin bir donanım kesmesi olustugunda çagrılacak bir kod yazmak istersek kesme çıkısında bütün register’ların ilk konumuna getirilmesi gerekir. Bunun için kesme koduna giriste bütün register’lar stack’ta saklanmalı, ve çıkısta da hepsi geri alınmalıdır.

İste bu islemi kolaylastırmak 80386 sonrası islemcilere tek komutla bütün registerleri yıgına atan ve yine tek komutla hepsini yıgından geri alan PUSHA ve POPA komutu eklenmistir. Kısaca; PUSHA komutu sırasıyla 16 bit sistemde AX, CX, DX, BX, SP, BP, SI, DI kaydedicilerinin degerlerini stack’a atar.POPA da ters sırada geri çeker.

PUSHF : PUSHF komutu da PUSH komutu gibi stack üzerine bilgi aktarır. Yalnız burada ki tek fark, PUSHF komutu ile aktarılacak bilginin herhangi bir register yada bellek bölgesinden degil de flag (bayrak) register’dan alınmasıdır.Yani bayrak registerlerin degeri Stack üzerine atılır.Sonunda ki “F” harfi Flag ( bayrak )anlamında oldugu için karıstırmayacagınıza eminim.Bir de atılacak bilgi dogrudan 16-bit uzunlugundaki flag register içerisindeki degerdir.Komut herhangi bir islem sırasında bayrak register’ın mevcut degerini korumak için kullanılır.Yine PUSH komutunda oldugu gibi PUSHF komutu da atılan degerin boyutuna göre SP ’nin degerini azaltır. Asagıdaki gibi tek basına kullanılır…

PUSHF



POPF : POPF komutu ile de arkadaslar stack üzerine attıgımız bayrak degerlerini ,yine 16-bit’lik bayrak register’a geri aktarırız. Ancak geri aldıgımız bu 16 bitin hepsi islemci tarafından dikkate alınmaz.Anlasılacagı gibi POPF komutu bayrak register ’ın degerlerini tamamen degistirmektedir. Sonunda ki “F” harfi Flag ( bayrak )anlamındadır.Komut tıpkı PUSHF komutunda oldugu gibi tek basına kullanılır.



Matematiksel (Aritmetik) Komutlar :

Assembly de bütün register arasında standart toplama, çıkarma, çarpma ve bölme islemleri rahatça yapılabilir arkadaslar.Ben de burada standart olarak 4 bölüme ayırıp açıkladım. Aritmetiksel komutların

icrası sırasında flag registerler degisiklige ugrar.



a - ADD ve ADC (Toplama)Komutları : ADD komutu toplama islemini gerçeklestirmek için kullanılır. ADD komutu ile “kaynak” içerisindeki deger “hedef” ile toplanıp tekrar “hedef” register içerisine kaydedilir. “Hedef” ve “kaynak” alanları da register-register, bellek-register, register-bellek gibi çiftlerden birisi olabilir.Örnek olarak;

MOV AX, 5 à ax içerisine 5 degerini yazdık.
ADD AX, 6 à Ax deki deger ile 6 yı toplayıp tekrar Ax ‘e kaydettik.

Yukarıdaki örnekte AX registerimizin degeri 11 olacak ve hexdecimal karsılıgı olarak 0Bh yazılacaktı.ADC komutu da tıpkı ADD komutu gibi toplama islemi için kullanılır arkadaslar.Aralarındaki tek fark ise ADC komutunda toplama islemine bir de carry (elde biti) flag’ın degerinin eklenmesidir.Yukarıdaki örnekte islemin sonucun da eger carry flag’ın degeri 1 olsa idi, o zaman bizim islemimizin sonucu da 11 degil 12 olarak çıkacaktı. Gösterimi daha anlasılır olacaktır.

register = hedef + kaynak + carry flag’ın degeri

b- SUB , SBB ve CMP ( Çıkartma ) Komutları :

SUB (Subtract )komutu çıkarma islemi için kullanılır. Kullanımı ADD komutunda oldugu gibidir. “Kaynak” içerisindeki deger “hedef” içerisinden çıkartılıp sonuç “hedef” register içerisinde saklanır.su sekilde örnek gösterebiliriz.

Mov ax,8

Mov bx,3

Sub ax,bx sonuç ax = 5

SBB Komutu (Subtract with Barrow) ise SUB komutunun Carry'li versiyonudur. Ödünç ile toplama komutu olan SBB, operand ile beraber elde (Carry) bayragını çıkarmada kullanır.Yani SBB komutu ile SUB arasındaki iliski, ADD komutu ile ADC arasındaki iliski ile aynıdır.SUB komutu ile aynı islem yapılır yalnız burada “hedef” alana atılan degerden carry flag’ın degeri de çıkartılır.

register = hedef – kaynak – carry flag’ın degeri seklinde gösterebiliriz.

CMP bu komut aslın da karsılastırma komutu gibi görünse de arkadaslar CMP komutu kullanım bakımından tamamen SUB komutu gibidir. Ancak islemin sonucunu herhangi bir kaydediciye yüklemez ,çıkartma isleminden sonra yalnızca bayraklar etkilenir aralarında ki fark sadece budur. CMP ’nin anlamı "compare" yani karsılastır demektir. Bu komut A, C, O, P, S ve Z bayraklarını etkiler.CMP komutundan sonra sonuca göre genellikle kosullu dallanma komutları ile programın akısı degistirilir.
Cmp ax, bx
Yukarıdaki örnekte Ax den BX çıkarılıyor AX, BX’e esit ise islemin sonucu sıfır olur ve zero flag 1 degerini alır.


INC – DEC (Artırma-Eksiltme ) Komutları :INC ve DEC komutları registerleri, adresleri, yada degerleri azaltmak - arttırmak içindir. Her iki komutta her çalısmasında sadece 1 byte lık azaltma veya arttırma yapmaktadır. Daha fazla adımlarda azaltma-arttırma yapmak için ADD ve SUB komutlarını kullanmalıyız. DEC ve INC komutları olusturdukları yeni degerlere göre bayrak registeri etkilerler.

Kısaca INC komutu kendisine verilen register yada bellek bölgesi içerisindeki degeri bir arttırır. C

dilindeki “++” komutu ile aynı isi yapmaktadır .Yada VB deki “a = a + 1” ile aynı anlamdadır.

Add ax,1 komutu da aynı isi yapar fakat asagıda ki örnek daha hızlı çalısır.

inc ax (ax= ++)

DEC komutu da kendisine verilen register yada bellek bölgesi içerisindeki degeri bir azaltır.Yine C dilindeki “--“ komutuna ,yada VB dilindeki “ a = a – 1 ” komutuna karsılık gelmektedir.

Dec ax (ax = -- anlamın da ve oldukça hızlı çalısır)

MUL ve IMUL (Çarpma) Komutları :Çarpma islevide registerler arasında , adresler arasında, ve kendi arasında uygulanabilir. Çarpma islemi MUL ve IMUL komutları ile gerçeklesmektedir. İkisini amacı çarpim oldugu halde MUL ve IMUL arasında farklılıklar vardır. MUL isaretsiz çarpma ,IMUL ise isareti dikkate alarak çarpma islemlerini yapar.Arıca IMUL komutu 2 veya çarpıma olanak vermekte ve kullanım sekli daha genistir. IMUL komutu 32 bit islemler için idealdir.

MUL :Aritmetiksel olarak çarpma islemi iki deger ile gerçeklestirilmesine karsın MUL komutu sadece bir deger alır. MUL komutu ile kullanılan deger gizli olarak ax /al içerisindeki deger ile çarpma islemine tabi tutulur.söyle ki;

mov ax,0045 -ax = 45

mov bx,0011 -bx =11

mul bx -ax * bx = sonuç yine ax registere aktarılır .

Yukarıdaki örnekten anlasılacagı gibi daima AX (AL ve EAX register) asıl çarpılandır.Eger bir çarpma islemi sonucu ax registerin alabilecegi en büyük degeri geçiyorsa geçme sayısı DX registere aktarılır. Eger geçme yoksa DX registerde bir degisme olmaz.

IMUL : IMUL komutu da MUL komutu gibi çarpma islemi için kullanılır tek fark IMUL komutunun isaretli sayılar üzerindeki islemler için kullanılan bir komut olmasıdır.Ayrıca IMUL komutu çoklu register ve büyük degerlerle islem yapmaya olanak vermektedir. Yanlız MUL komutunda oldugu gibi tasma oldugunda DX register aktarılma yapılmaz. IMUL ile üçlü çarpımda mümkündür.


mov ax, 04h
mov bx,05h
imul ax,bx,8h ; [AX*BX] * 8 = 160

Yukarıda sadece küçük sayılarla örnek verdim anlasılması için yoksa bu komutla daha büyük sayılar çarpılabilir.32 bit islemcilerde bu komut kullanılır.

DIV ve IDIV (Bölme) Komutları : Bölme komutuda DIV ve IDIV olmak üzere kapsamlı olarak iki tanedir. DIV komut da MUL komutundan oldugu gibi sadece bir deger ile isleme girer ve gizli olarak AX register’ını kullanır. Yani islem sonundaki bölüm degeri AX ve kalan degeri de DX içerisine atılır.DIV division yani bölme kelimesinin kısaltmasıdır, dikkat edilmesi gereken bir diger husus da sıfır ile bölme durumudur. Diger islemlerde oldugu gibi bölme isleminde de matematik kuralları geçerlidir ve matematikte "sıfıra bölme" anlamsızdır. CPU' da sıfıra bölüm için özel bir kesme(interrupt) ayırmıstır ve böyle bir durum da islemi durdurur.

Mov ax,10

Mov bx,3

DİV bx

bx deki 3 degeri ax deki 10 degerine bölünüyor ve ax de 3 degeri ,kalan 1 ise DX registerde saklanıyor.

IDIV komutu ise aynı IMUL komutunda oldugu gibi daha yüksek islemler için idealdir.Ayrıca IDIV komutu isaretli sayılar üzerinde islem yapmak için kullanılır.Bu komutu fazla kullanmayacagınızdan bu kadar yeterlidir diye düsünüyorum.
Cevapla

“Programlama ve Script dilleri” sayfasına dön