ASSEMBLY İLE DÖNGÜ KOMUTLARI ve ALT PROGRAMLAR
DÖNGÜ KOMUTU (Loop)
Assembly dilinde de istenilen komutların istenilen sayıda tekrar edilmesi sağlanabilir. Bu tekrarlama işlemini isterseniz dallanma komutlarıyla da yapabilirsiniz. Ancak döngü komutuyla basit bir şekilde döngü oluşturuluyor.
Loop komutuyla istenilen adresten itibaren, loop komutuna kadar olan, aradaki komutların tekrar etmesi sağlanır.
Tekrar sayısını cx veya ecx kaydedicisinin değerini değiştirerek belirleyebilirsiniz.Diyelimki cx kaydedicisine 4 verdiniz. Döngü her çalıştığında cx kaydedicisinin değeri 1 azalacaktır. Cx kaydedicisinin değeri 0 olana kadar, belirtilen işlemler tekrar eder.
Örnek:
mov cx,4
@baslangic: //döngünün başlangıcı
tekar edecek komutlar //Bu komutlar tekrar edecek
.....................
.....................
Loop @baslangic //döngü sonu
Örnek program: İstenen sayıdan saymaya başlayıp(istenilen artım sayısıyla [Üçer üçer, beşer beşer, .....]) , sayıları toplayan program.
procedure TForm1.Button1Click(Sender: TObject);
var
basdeger,sonuc,artim:integer;
tekrarsayisi:integer;
begin
tekrarsayisi:=strtoint(edit1.text);//Bu işlem kaçkez tekrarlanacak?
basdeger:=strtoint(edit2.text); //Hangi sayıdan itibaren sayma işlemine başlanacak?
artim:=strtoint(edit3.text);//Her tekrar işleminde sayı ne kadar artacak?
asm
mov ecx,tekrarsayisi {tekrar sayısı ecx değişkenine aktarılıyor [zorunlu]}
mov eax,0 {başlangıç değeri}
mov ebx,0
@@dongu: {@@dongu etiketiyle loop komutu arasındaki komutlar tekrar edecekler}
inc ebx
add eax,ebx {Her seferinde artim değişkeninin değeri kadar eax kaydedicisinin değeri artacak}
loop @@dongu
mov sonuc,eax {eax kaydedicisinin değeri sonuc değişkenine aktarılıyor}
end;
showmessage('Sonuç:'+inttostr(sonuc));
end;
Dikkat!!! Eğer döngü içindeki bir işlem cx veya ecx kaydedicisinin değerini değiştirirse döngünün tekrar sayısıda değişecektir. Örneğin döngü içinde cx veya ecx kaydedicisine sabit bir değer verirseniz(0 dışında) sonsuz döngü oluşacaktır.Bunun yerine şarta bağlı olarak sabit değer verebilirsiniz.
Örnek program: Girilen sayının faktöriyelini bulan program (İnteger 32 birlik olduğu için çok büyük sayılar girilmemelidir.)
Faktöriyel: 4! (dört faktöriyel) -> 1*2*3*4
5! (beş faktöriyel) -> 1*2*3*4*5
6! (altı faktöriyel) -> 1*2*3*4*5*6
Program:
procedure TForm1.Button1Click(Sender: TObject);
var
faktor,sonuc:integer;
begin
faktor:=strtoint(edit1.text);
asm
mov ecx,faktor
mov eax,1 //eax e başlangıç değeri olarak 1 veriliyor
mov ebx,1 //ebx e başlangıç değeri olarak 1 veriliyor
@@dongu:
mul ebx //eax ve ebx çarpılıyor , sonuç eax e aktarılıyor..
inc ebx // ebx in değeri 1 arttırılıyor..
loop @@dongu
mov sonuc,eax
end;
showmessage('Sonuç:'+inttostr(sonuc));
end;
Çeşitli döngü komutları: Kullanımları Loop komutuyla aynı
Loopz komutu(Loope ile aynı):
Bu döngü komutuyla, cx veya ecx kaydedicisinin değeri 0 olana kadar veya zero bayrağının değeri 0 olana kadar döngü devam edecektir. Bu şartlardan biri veya her ikiside gerçekleştiği anda döngüden çıkılacaktır.
Loopnz komutu(Loopne ile aynı):
Bu döngü komutuyla cx veya ecx'in değeri 0 olana kadar veya zero flağı set(1) edilene kadar ya da her iki şart birlikte gerçekleşene kadar döngü kurulmuş olur.
ALT PROGRAMLAR: Assembly ile de alt programlar oluşturup daha sonra istediğiniz yerden bu alt programı çağırabilirsiniz. Yapmanız gereken ana programın üst kısmında alt programlarınızı yazmanız. Alt programı ana programın üstünde yazmak zorunda değilsiniz. Ancak ana programın üstünde tanımlamanız daha kullanışlı. Neden? Çünkü Assembly yapısal bir programlama dili değil. İlk satırdan itibaren çalışmaya başlıyor. Eğer programın akışını yönlendirmezseniz, siz istesenizde istemesenizde alt program en az bir kez çalışacaktır. Bunu kolay bir şekilde engelleyebiliriz. Diyelimki birsürü alt programınız var. Üst tarafa alt programları yazdınız. Alt tarafta ana program bloğu var. Alt programların sizin komtrolünüz dışında çalışmasını istemiyorsunuz. O zaman programın en başına koşulsuz dallanma komutunu koyuyor ve programın akışını ana programın başladığı yere aktarıyoruz. Böylece alt programlar bizim isteğimiz dışında çalışmıyor. İsterseniz bu yapıyı kullanmayabilirsiniz. Ancak o zaman birsürü koşullu ya da koşulsuz dallanma komutu kullanmanız gerekecektir.
Diyeceksiniz ki "Alt programa ne hacet, ben aynı işi dallanma komutlarıyla da yapabilirim.". Evet ama dallanma komutuyla programın akışını değiştirdiniz. İstediğiniz program parçası çalıştı, peki ama program akışı kaldığı yerden nasıl devam edecek?
İşte alt programlar sayesinde program akışı, alt program çalışmasını bitirdikten sonra kaldığı yerden devam ediyor.
Alt programlarda Call ve Ret komutları kullanılır. Call komutuyla önceden oluşturulan alt program çağrılır. Ret komutuysa alt programın sonunda bulunur ve alt programın bittiğini gösterir. İşlemci ret komutunu gördüğünde Call komutunun altındaki satırdan itibaren çalışmaya devam eder. Dikkat!! Call komutundan önce ret komutu kullanılamazzzz. Hata oluşur!! İlkönce call, sonra ret....
Komutların kullanımı: Call adres --> adres dallanılacak alt programın adresidir.
Ret komutuysa alt programın sonunda bulunur.
Çalışan alt programı sonlandırmanın iki yöntemi vardır. 1 Ret komutuyla 2 Retf komutuyla
Eğer alt programla, alt programın çağrıldığı kısım(Call komutu) aynı bellek bölgesindeyse(segment) Ret, aynı bellek bölgesinde değilse(birbirlerine uzaksalar) Retf komutu kullanılır.
Örnek program: Girilen sayının istenilen kuvvetini hesaplayan program.
procedure TForm1.Button1Click(Sender: TObject);
var
sayi,kuvvet,sonuc:integer;
begin
sayi:=strtoint(edit1.text);
kuvveti:=strtoint(edit2.text);
asm
mov ebx,sayi
mov ecx,kuvveti
mov eax,1 //çarpmanın etkisiz elemanı...:)
jmp @dongu //alt program çalışmadan ana program kısmına dallanılıyor.
@altprogram: //alt program başlangıcı
mul ebx
ret //alt programın çalışması bitiyor
@dongu: //dikkat ettiyseniz döngü içinde istediğiniz kadar alt programı tekrar tekrar çağırabiliyorsunuz...
call @altprogram //alt program çağrılıyor
loop @dongu
mov sonuc,eax
end;
showmessage('Sonuç:'+inttostr(sonuc));
end;
İleride göreceğimiz dersler: Döndürme komutları, string komutları(belki), kesmeler(interrupt)...Assembly çok basitmiş değil mi? Ben 1-2 ay içinde kendi kendime öğrendim. Size de öğretmek istedim :)
Zaten programlama mantığını bir kere öğrendikten sonra programlama dillerini öğrenmeniz çok kolay oluyor. Öğrenmeniz gereken sadece hangi işlemi hangi komutla yapacağınız.
Delphi ile ilgili örnek pek olmadığı halde, deneme-yanılma yöntemiyle de pekçok şey bulunabiliyor...
Muharrem YILDIZ
kasimyildizi@yahoo.com, muharremyildizxxx@hotmail.com