Bu sayfadaki yazılar
Sayfanın metni
Sayfa 18
JSR $0073
komutu yer almaktadır. $0073'te yer alan rutin, bilgisayarınızda yer alan tek RAM rutinidir. Bu rutinin RAM'de yer almasının sebebi de kendini değiştiren bir rutin olmasıdır. $0073'e her sıçradığınızda ilk olarak $007A-$007B birleşik adresinde yer alan değer bir artırılır, sonra da bu iki adresin gösterdiği bellek alanında yer alan karakter alınır. Bu alınan bayt (ya da karakter) $20 değilse, baytın sayı ya da karakter olmasına göre bazı flag'lerin durumları ayarlanır. rutinden dönüldüğü anda A registerinde (Akümülatörde) alınan bayt bulunur. Bu rutinden dönüşte A'da hiçbir zaman $20 bulunmaz. Eğer bu rutin ROM'da yer alsaydı, kendi kendini değiştiremeyecek, dolayısıyla çalışmayacaktı. Madem ROM rutini bu komutla başlıyor, biz de programımızı bu komutla başlatalım. Daha sonra A'da istediğimiz karakterin olup olmadığını kontrol edelim. Tabii ki önce ekleyeceğimiz komutun ne olacağına karar vermeliyiz. Bildiğiniz gibi Commodore'a eklenen komutların sayısı iki-üç gibiyse genelde yana ok tuşu arkasına konan bir harf şeklinde komutlarımız olur (“e-A” gibi). Belki de ilk teyp turbolarından olan pinky turbo'- nun LOAD, SAVE ve VERİFY yerine * ve “ kullanması yana ok standardını başlatmıştır. Sebebi ne olursa olsun, çoğu kullanıcı gi-
LDA STA LDA STA RTS LDA STA
#S16 S0308 #SCO
#SE4
#SAT
JSR 80073
$COSO $CO53 $CO56 $CO59 $Co5C
JSR $0073 $CIE4 JSR
Tablo-1: Grafik işlemlerini komut haline getirmek için eklenmesi gereken komutların hepsi.
$C100 $C12D $C146 $C19B $CIE4
bi ben de yana ok tuşunun büyüsüne kapılanlardanım ve komutların “ “ B”, RI,R2,R3” ve X,Y,RENK” olmasına karar verdim. İtirazı olan varsa beri gelsin. Komutların beşi de yana ok ( klavyenin sol üst köşesinde yer alan tuş) ile başladığından, programımız JSR $0073'den hemen sonra bu karakterin olup olmadığına bakmalı. Bu karakterin kodu $5F olduğuna göre CMP 5F gibi basit bir komutla BASIC eklemesinin ilk adımı atılmış oldu. Bu satırdan sonra gelen BEO Komut-Olabilir yardımıyla, eğer yana ok karakteri varsa A, B, C, D ve E harflerinin kontrol edileceği yere sıçrıyoruz. Tabii ki karakter beklediğimiz yana ok değilse, komutun BASIC'e ait olduğuna karar vererek kontrolü BA-SIC'e bırakıyoruz. Tabi ki not aldığımız $ATE4 adresine sıçrayarak değil. Gizli bir iş yaparken arkanızda iz bırakmamayı öğrenmelisiniz. Casus rutinimiz en başta yer alan JSR $0073'ü gerçekleştirdiği için (ve A'da yer alan baytı hâlâ kaybetmediğimiz için) $A7ET'ye sıçramalıyız. Bu işlemi yaptığımızda, eğer komut bize ait değilse BASIC için hiçbir şey farketmeyecektir. SA7E7T'de yer alan rutin (bütün aptallığıyla) $0073'e sıçradığını ve A'da yer alan baytın buradan geldiğini sanacaktır (“Bak, kuş!” numarasının bundan daha etkili olduğu bir alan daha yoktur sanırım). Bundan sonra olacaklar bizim rutinimizi kesinlikle ilgilendirmez. Eğer normal bir kömut verildiyse bu komut işletilecek, hatalı bir şeyler girildiyse de ?SYNTAX ERROR'la karşılaşılacaktır (Girilen “hatalı bizim komutumuz olmadığı “zamanlar). Bizim komutumuz girilmediği zaman işlerin yolunda gitmesini kolayca sağladık. Peki girilenler bizim komutlarımızsa ne yapacağız? Eğer sıfırdan rutinler yazıyor olsaydık işimiz kolaydı: Komutla ilgili tüm işlemi bitirin, $007A-$007B'yi komutumuzun sonrasında bırakıp SA7E4'e sıçrardık, olurdu. Oysa şu anda hazır bir rutin var (beş ko-
"mutluk grafik paketi) ve bu rutinde gerekli komutun işlemini yaptıktan sonra ROM'a geri dönmeliyiz. Bunu nasıl yapabiliriz? Bu işi yapmanın en kolay yolu, ilgili rutini JSR ile çağırdıktan sonra ROM'a JMP ile sıçramaktır. Bunu yapmak yeni yeni teorik bilgi yüklenmekten kolay olabilir. Ama ben birbirinin aynı beş ayrı komutu ard arda vermenizi engellemek için (ve kafanızı biraz meşgul etmek için) yeni bir komut anlatmak istiyorum. JSR Komutu ve Yığıt (Stack)
Bilgisayarınızın alt programlardan geri dönerken nasıl olup da yerini unutmadığını hiç düşündünüz mü? Ya da bir interrupt oluştuğunda kısa interrupt servis rutinini çalıştırıp sonra hiçbir şey olmamış gibi aynı yere dönebildiğini? Bir yerlerde sizin hafızanıza karışmadan bekleyen ve bu işleri düzenleyen bir hafızaya ihtiyaç vardır Commodore'unuzun. Bu ek hafızaya STACK adı verilir. Sadece C-64'ün değil, tüm bilgisayarların temelde aynı mantığı kullanan yığıtları bulunur. Kimi bilgisayarın tüm RAM'i yığıt olarak kullanabilirken, kiminin onlarca ayrı yığıtı bulunabilir. Fakat bunlar içinde anlaşılması en basit olanı ve en sabit olanı C-64'ün yığıtıdır sanırım. $0100-$01FF arasında yer
Klavyeyle gezinmek için ← ve → tuşları.
Sayfa 19
19 alan yığıt, $O1FF'den aşağı doğru genişler. — ye çalışırken de yığıtta yer alan değerlerden — larımızdan üçü hatasız bir şekilde çalışabi- Yani yığıta bir değer atmaya kalkarsanız yığıt — faydalanacak. Tabii ki bu değerler bizim yı- — liyor. Yani yapılan en ufak bir değişiklikte bir alt bayta geçer. Yığıtı bir tabak yığını ola- — ğıtta sakladığımız değerlerden başkası olma- — bu üç komut çalışma yeteneğini kaybediyor. rak düşünebilirsiniz. Her koyduğunuz tabak — yacak. Böylece bilgisayarımızı iyice dolan- — Neyse ki asıl problem çıkartan kısım virgül bir diğerinin üstüne gelir. Daha sonra buta- — dırmış olacağız. kontrüllerinin ilki. Yani bunu kaldırdığımızbak yığınından bir şeyler almaya kalktığınız- İsterseniz bu anlattıklarımı Tablo 1'deyer — da (daha doğrusu JSR $0073 ile değiştirdida, sadece en üstteki tabağı olabilirsiniz. Yani ard arda üç değeri yığıta attığınızda, aldığınız ilk değer üçüncüsü olur. Yığıt konusunu detaylı olarak makine dili kursunda ele alacağım, bu yüzden şimdilik bu kadarı yeterli olacaktır. Şimdi de bilgisayarınızın kaldığı yeri unutmamak için nasıl bir yöntem izlediğine göz atalım: Bildiğiniz (ya da şimdi öğreneceğiniz) gibi bilgisayarınızın PC adı verilen 16 bitlik bir registeri vardır ve o anda işletilmekte olan komuta ait bilginin bulunduğu adresi gösterir bu register. BASIC'teyken SYS 49152 verdiğinizde, PC'ye $CO0O değeri atanır sadece (aslında bu yapılan işlemden çok bir sonuçtur). Fakat, PC sadece tek bir değeri aklında tutabildiği için, alt programlara gitmeden önce, bir şekilde nereye geri dönmesi gerektiğini hatırlayabilmelidir. Bunun için demin anlattığım yığıt kullanılır. Alt rutine sıçranması gerektiğini gösteren JSR komutu görüldüğünde bunu takip eden iki bayt alınır ve ikinci bayt gösterilirken PC'nin sırasıyla yüksek ve düşük değerlikli baytları yığıta atıhır. Bu baytlar yığıtta yukarıdan aşağı doğ- Tu yer alacağından, 6508 için standart olan düşük-yüksek değerlikli bayt sistemi konmuş olur. Tabii ki yığıta atıldığı anda JSR'yi takip eden ikinci baytı gösteren PC, bir sonraki komuttan bir bayt geridedir. Yani yığıtta yer alan değer bir artırıldığında alt programdan geri dönüldüğünde işletilecek komutun adresi elde edilir. Alt program, işini bitirdiği zaman bir RTS komutuyla bunu belli eder. RTS komutu hemen yığıtta yer alan iki baytı alır, bunları doğru sırada PC'ye yerleştirir, PC'yi bir artırır ve programın çalışmasına devam eder. Nereden mi? Tabii ki JSR komutunu takip eden komuttan. Bu yüzden alt programlara girerken kaç tane değeri yığıta attıysanız bu kadar değeri yığıttan çekmelisiniz. Yoksa, bilgisayarınız sizin yığıtta sakladığınız verileri alıp, bu verilerin adresine sıçramaya çalışır RTS'yi görünce. Bizim komut ekleyicide yapmayı düşündüğümüz işlem de tam anlamıyla bu, RTS ile BASIC'e döneceğini sanan grafik rutinlerine sıçramadan önce yığıta ROM'da dönülmesi gereken yerin adresini atacağız. Grafik komutlarını da JSR ile değil, JMP ile çağıracağız. Böylece bilgisayar bu rutinlerin nereden çağrıldığını hatırlayacak. Geri dönmealan programda da takip etmeye çalışın. Eğer takip edemezseniz, beni izlemeye devam edin. İlk olarak SA7 ve $E3 değerlerini yığıta atıyoruz (PHA komutu A'yı yığıtın en son değeri olarak tanımlar ve yığıtı bir aşağı indirir). Böylece RTS görüldüğü anda SATE3 4 1-$ATE4 adresine sıçranacağını garanti ediyoruz. Demek ki grafik bittiğinde, $7A-$7B'yi gerektiği şekilde bırakırsak (ki bırakmayacağız) RTS görüldüğünde komutumuz hiç işlenmemiş gibi yoluna devam edecek ROM. Buraya kadar da her şey kontrol altında.
Şimdi A, B, vb. kontrolünü yapalım. Demin JSR $0073 ile yana ok karakterini bulduğumuza göre bu harfle olan işimizi bitirdik. Şimdi sıradaki harfi alalım:
JSRS$0073 ve “A” olup olmadığını görelim:
CMP #41 BEO$COS0
A değilse:
CMP # 42 BEO$COS3
Eğer A, B, C, D ya da E değilse: RTS
Yani ROM'a: “Komut bize ait değil, yana okunuzu ve bir sonraki harfi yedim. Kalanıyla ne yaparsanız yapın” diyerek kaçıyoruz. Neyse ki ROM'da yana ok'la başlayan bir “komut yok. Sonuç zaten bir ERROR olacaktı. İki karakter eksik ya da fazla olmuş, bir hata için farketmez. Tablo 1'de de rahatlıkla görebileceğiniz gibi $C0S50'den itibaren grafik işlemlerine JMP'ler yapılıyor. Bu rutinlerden ilk üçü, yani kullanıcıdan bir parametre istemeyenler oldukları gibi çalışabiliyor. Ama kullanıcının bazı şeyleri girmesini bekleyen son ikisi SYNTAX ERROR veriyor. Bunun sebebi, BASIC'in bir komutla işi bittiğinde $7A ve $7B'yi yeni komutun ilk karakterinde bırakması, oysa bizim rutinin eski komutun son karakterinde bırakması, Bu işi kolayca halledebileceğini sanan arkadaşlarınız yanılıyor, çünkü komutğimizde) problemi halledebiliriz. Hem hoş bir yan etkisi de oluyor. Komutumuz: değil, «—D 1,2,3 olarak çalışır. Yani tam bir komut gibi... Ama nedense bu kadarla kalmıyor problemler. komut işini bitirdikten sonra (gene bu son iki komutun marifeti bu) $7A-$7B'yi gerekenden bir ileride bırakıyor. Bu yüzden de komuttan sonra gelen iki nokta üstüste (:) farkedilmiyor ve alıyorsunuz SYNTAX ERROR'u. Grafik rutinleri üzerinde oynamadan bu hatayı düzeltemeyeceğimi farkedince, bir hile buldum. Her «-D ve &«E komutundan sonra iki kere iki nokta üstüste koyarsanız ve sonraki komutu öyle girerseniz, ya da sonraki komut diye bir şey yoksa bir tane iki nokta üstüste kullanırsanız bu SYNTAX ERROR'dan kurtulabilirsiniz. Her ne kadar can sıkıcı bir kullanım tarzıysa da en kolay bu şekilde hatadan kurtulabiliyoruz. Tabii ki hazır yazılmış bir programı komut haline çevirmiyorsanız, bu tür hatalardan kurtulmanız çok kolay. Hatayı farkeder farketmez başını ezebilirsiniz, ya da komutların $7A'yı bıraktığı noktayı aynı tutabilirsiniz. Ama bir programı fazla değiştirmek istemediğinizde bu tür hatalarla karşılaşmanız çok normaldir (özellikle de parametreleri okuyanlarda): Bu eklemeleri de yapınca grafik komutlarınız tam olarak komut halini almış oldular: Grafik ekranı açma. «-B: Grafik ekranını kapama. Grafik ekranını temizleme. «-D,RI,R2,R3: Çok renk modunun renklerini belirleme. #-E,X,Y,R: X,Y koordinatına R renkli nokta koyma (R - 0 ise silme). Son bir şey daha var: RUN/STOP-RESTORE kombinasyonu $0308-$0309 adres çiftinin değerini düzeltmez. Yani bilgisayarınızı RESET'leyene kadar, ya da doğru değeri bu adreslere girene kadar eklediğiniz komutlardan kurtulamazsınız. Bu yüzden $C0OOB adresinde bu adreslerin değerini düzelten rutini de ekledim. Bu aylık yazımız da bu kadar. Gelecek ay hepinizle görüşmek üzere hoşçakalın.