ALT RUTİNDEN GOTO İLE GERİ DÖNMEK

Başlatan humanus, 19 Mart 2009, 14:59:52

humanus

"CALL" komutu ile çağrılan bir alt rutin içerisinden "GOTO" komutu ile ana programın başka bir alanına dallanmak pratikte ne gibi bir problem yaratabilir. Bazen alt rutin içinde bir kıyaslama yapıp bunun sonucuna göre bir başka etikete gitmek gerekebiliyor. Ben bunun için alt rutin içinde bir yazmaç belirleyip onun aldığı değere göre geri dönüşte ilgili etikete dallandırıyorum programı. Ama ara sıra direkt alt rutin içinden GOTO komutu ile aynı sayfa içinde başka bir rutine direkt olarak gidiyorum. Bir sorun yaşamadım, ama hiçbir kitapta böyle bir uygulama görmedim. Konunun uzmanlarına danışmak istedim. İyi çalışmalar.

Salih

CALL komutu kullandığımızda geri dönüş adresleri LIFO (Son giren ilk çıkar) türü bir bellek mantığına göre saklanır. Her Call komutu bu belleğe geri dönüş adresini yerleştirir. Return komutu ise bu belleği bir kuyu gibi düşünürsek kuyunun en üstteki adresi alır ve kullanır. Eğer geri dönüşlerde Goto kullanır isek LIFO bellekteki sıra bozulur. Yani kuyudan almamız gereken geri dönüş adresi alınmamış olur. Bundan sonra başka bir altyordamdan Return kullanılırsa daha önce alınmamış dönüş adresi kullanılmış olur. Bu işlemde program mantığını bozar. Tek bir alt yordam varsa problem olmaz, herhalde? ama birden fazla altyordam varsa bilhassa altyordamdan başka bir altyordam çağrılıyorsa mutlaka problem olur.

Tagli

Dikkatli kullanılırsa oldukça faydalı olabilir. Assembly dilinde şarta bağlı ifadeleri elde etmenin en kolay yolu goto tablosu oluşturmaktır ve bunu bir call ile gidilmiş alt programda kullanmak tam olarak bahsedilen duruma örnektir.

Örneğin bir alt programa call ile gidildi ve bir x register'ının değerine göre goto ile başka bir yere dallanıldı. Dallanılan yerden return ile alt programın ilk çağrıldığı yere dönülür.

Ben bunu yazdığım programlarda sıklıkla kullanıyorum. Mesela PS/2 klavye ile ilgili bir program yazmıştım. Gelen scan kodlara göre ne yapılması gerektiği birbirine zincirleme bağlanmış goto tablolarıyla belirleniyor. Sadece başta bir call var. goto'lar ile istenilen yere ulaşılıp işlem yapılınca da return ile en başa dönülüyor.

Burda önemli olan nokta call sayısı kadar return olmasıdır.
Gökçe Tağlıoğlu

transistor

dikkat edilecek tek husus call dan sonra return demeyi unutmamak vede stacke dikkat etmek özellikle 18 serisine kadar 8 stack seviyesini göz ardı etmemek yoksa gerisi tamamen kodun akışına bağlı olarak sana kalmış
Herşey Vatan İçin.

bigbey

#4
Dikkatli kullanıldığı sürece hiç bir sorun olmaz. Zaten hepimiz bu tip yöntemleri kullanırız.CALL ile oluşan bir komut işlevi return komutunu görmezse daha önce verilen CALL, INTERRUPT   stack adresleri karışabilir.
CALL ile dallanılan bir diziden koşula göre GOTO ile dışarı çıkılabilir. gerekirse tekrar goto ile çıkılan satır hizasına bir label ile belirtilmiş ise tekrar GOTO komutu ile daha önceden call ile gidilmiş rutine geri dönülebilir. Veya GOTO ile gidilen yerden RETURN komutu ile CALL komut satırının bir altına geri dönülebilir.
TA6R

humanus

Zaman ayırıp cevaplayan arkadaşlara teşekkür ediyorum.

camby

Bir pini kapatma butonu olarak atadım. kesme ile yapmak istiorum ve sanırım RB0 bacağına bağlamam gerekiyor , Bu butona basıldığında 0x04'e mi gidiyoruz , oraya gittikten sonra dönüş olarak programın kaldığı yere değil de tekrar başlangıç pozisyonuna dönmek istiyorum , bunun için alt programda iken kaydedilen dönüş adresini değiştiren bir kod mu yazmam lazım?
8 seviye stack , en fazla içe içe 8 alt program mı yapabiliriz anlamına geliyor?

Tagli

Evet, kesme gelince program mevcut program counter (PC) değerini yığının tepesine yerleştirir ve 4'e gider. Bu adresi 10, 12, 16 serilerinde buradan silemezsin (17'yi hiç bilmiyorum). Bu durumda kesmeden sonra programın başına gitmen mümkün değil. Aslında gidersin gitmesine ama kullanmayacağın adresler yğında kalacağından bir süre sonra program kafayı yiyebilir. Ama belki herşey yolunda da gidebilir, çünkü yığın dairesel yapıdadır, eski değerlerin silinmesi, onları zaten kullanmayacaksan sorun olmayabilir. 18 serisinde (ve üst modellerde) POP komutu ile yığının tepesindeki dönüş değerini silebilirsin.

Ama amacın kapama düğmesi (veya bir çeşit reset) ise bunu yazılımla yapmana gerek olmayabilir. Neden düğmeyi enerji hattına bağlamıyorsun? Basınca zaten PIC resetlenir. Eğer RAM'deki değerlerin korunmasını istiyorsan bu sana uymaz elbette. Bu durumda kesme gelmesini beklediğin döngülerin içine bir biti kontrol eden bir düzenek koyarsın, kesme de bu biti 1 yapıp kaldığı yere döner. Döngüde bitin 1 olduğunu görünce programın başına gidersin.
Gökçe Tağlıoğlu

camby

evet ben de dediğiniz gibi düşündüm ama Kapatmayı ile kesme yapmak istiyorum ve program da çok uzun olduğu için kesmenin nerde olacağını doğal olarak kestiremiyorum , mclr ucu tabi de ilk etapta tercihim ama bu şekilde yazılımsal bir reset elbet vardır diye düşündüm..
Yardımların için teşekkürler

camby

#9
GOTO tablosu  işimi gördü baya , fakat merak ettiğim konu , stack erişimi nasıl yapılıyor?

Edit : 16f877a datasheet'i demiş :
Alıntı YapThe stack space is not part of
either program or data space and the stack pointer is not
readable or writable.

fatihinanc

hocam yine 877nin datasheetinde yaziyor.

the stack pointer is not readable or writable...
Kainat dediğimiz kitap, yazıldığı dil ve harfler öğrenilmedikçe anlaşılamaz.  (Galileo Galilei)

Tagli

18 serisinde yapabilirsin ama. İşletim sistemi çalıştırabilmelerine olanak veren özellik bu zaten.
Gökçe Tağlıoğlu

fatihinanc

Hocam konuyu biraz daha açabilir misiniz?
Yani işlemler yığın yazmaçtaki durumlara göre mi kontrol ediliyor?
Kainat dediğimiz kitap, yazıldığı dil ve harfler öğrenilmedikçe anlaşılamaz.  (Galileo Galilei)

Tagli

İşletim sistemlerinin temelinde yürürlükte olan bir işlemi olduğu gibi dondurup beklemeye alabilmek ve yerine başka bir işlemi geçirebilmek yatar. Bir işlemin o anki durumunu ise hafızadaki değişkenler, ve en önemlisi de o işleme özgü yığın belirler. Yani başka bir işleme geçilebilmesi için o anki yığının bir yere kopyalanabilmesi, ve yerine yeni işlemin yığınının yazılabilmesi gerekir. Ancak bu şekilde işlemler arasında geçiş mümkün olabilir. 18 serisinde donanımsal yığına yazılımsal olarak müdahele imkanı, bu işlemcilerde işletim sistemi çalıştırılabilmesine olanak tanır.
Gökçe Tağlıoğlu

fatihinanc

Anladım hocam ama kafama bir soru takıldı.
Diyelim ki yığn yazmacımız 8byte bu 8 byte aşılmadığı sürece neden o andaki yığın adresi kopyalanmak istensin ki ?
Kainat dediğimiz kitap, yazıldığı dil ve harfler öğrenilmedikçe anlaşılamaz.  (Galileo Galilei)