AMIGA ASSEMBLER

Merhaba! İşte yine birlikteyiz. Bakalım bu ay postadan neler çıktı? Tolga ATUĞ arkadaşımız, tekrar yazarak birkaç ufak sorununu belirtmiş. Bunlardan ilki, Örnek 17.1'de 59. satırda basımda oluşan bir hata. Dergimizde 'add.l #$54,a0' olarak basılan satır 'add.l #$54,a0' olmalı. Herhalde add komutunun da işlevini öğrendik? Tolga, yardımcı olarak kullanılabilecek kitapları listelememi istiyor. İşte size gerekli olabilecek kitaplar: * ROM Kernel Reference Manual: Libraries and Devices * ROM Kernel Reference Manual: Exec * ROM Kernel Reference Manual: Autodocs and Includes * Hardware Reference Manual * Mapping the Amiga Bunun dışında, Abacus'un Assembler kitabı da bir hayli yararlı. Edinmenizde fayda var, ama şart değil. Diğer mektup ise Gürkan YENİÇERİ'den gelmekte. Bu arkadaşımızın da karşılaştığı en önemli sorun, bazı programlarda compile esnasında 'word at odd address' hatası vermesi. Bunun çözümü gayet basit. Hata veren satırdan öncesine bir satır ekleyerek buraya 'even' komutunu yazmak yeterli. Bu iki kısa mektuptan sonra, bu ayki konularımıza geçebiliriz. Bu ay biraz hızlı bir geçiş yapacağım. Fark ettiyseniz, bu ay yazabileceğiniz bir program yok. Bunun nedeni, bu ay birkaç library fonksiyonu açıklayacak olmam. Ayrıca assembler komutları tablosu da bir hayli yer kaplıyor. Geçen aylarda pencerelerin nasıl açıldığını, buraya nasıl basım yapıldığını görmüştük. İlk inceleyeceğimiz library fonksiyonu, MoveWindow. Bu fonksiyon intuition library'de bulunmakta ve istediğimiz pencereyi istediğimiz yönde kaydırmaya yaramakta. Parametreleri sadece üç tane: Window, dx ve dy. Window, pozisyonu değiştirilecek pencerenin pointer'ı, dx ve dy ise dikey ve yatayda kayma değerleridir. dx negatif bir sayı olduğunda pencere sola, dy negatif olduğunda pencere yukarı doğru verilen piksel kadar kayacaktır. Aşağıdaki ufak rutinde, pencerenin pozisyonu 2'şer piksel sola çekilerek kaydırılıyor. Pencere koordinatı 0 olduğunda da ana programa dönülüyor. Tabii ki pencere boyutları ekrandan büyük olmak zorunda.

MoveWindow:
move.l
move.l
move.l #-2,d0
move.l #0,d1
-168(a6)
move.l WindowPtr,a0
move.w — 4(a0),d0
tst.w d0
bne.s MoveWindow

Gayet kolay, değil mi? MoveScreen fonksiyonu da aynı şekilde çalışır. Bu fonksiyonda, sadece window structure adresi yerine screen structure adresini a0'a yazmamız gerekmekte. Fonksiyonun ofseti de -162 (-$a2). Gelin şimdi de bir guru verdirelim bilgisayarımıza. Hemen telaşlanmayın; bu guru kontrollüdür. Sistem crash etmeyecek, fakat o ünlü kırmızı kutu yanıp sönecektir. Kutunun içine de istediğimiz yazıyı yazabiliriz. DisplayAlert fonksiyonun kullanımı gayet basit; sadece alert tipini, text string'ini ve toplam yüksekliği bilgisayara girmemiz yetiyor. String'in başlangıç adresini a0 register'ına, uzunluğunu ise d1'e atıyoruz. String tipi ise d0 register'ı aracılığıyla belirlenmekte. Buraya 0 değerini yazdığınızda, RECOVERABLE ALERT tipini seçmiş oluyorsunuz. Bu, alert kutusu gösterildikten sonra mouse tuşuna basılırsa, programınıza geri dönmeyi sağlar. Şayet fonksiyonu çağırmadan önce d0'ın 15. bitini set ederseniz, (-$80000000) DEADEND ALERT yaratmış olursunuz. Alert kutusu çıktıktan sonra mouse tuşuna bastığınızda bilgisayar resetlenecektir. String'imiz özel bir şekilde verilmek zorunda. String içinde koordinatlar ve devam etme bilgileri de bulunmakta. Koordinatları ASCII string'in kendisinden önce word ve byte olarak vermeliyiz. İlk word, basılacak string'in kutu içerisindeki x koordinatı, ardından gelen byte ise y koordinatıdır. Bundan sonra gelen ASCII byte'lar string'in kendisini oluşturur. String'in sonunda bir 0 byte'ı olmalıdır. En son byte ise başka string satırı olup olmadığını gösterir. Eğer bu byte 0'dan farklıysa, bu byte'ı diğer string tanımlamaları izler. Başka string tanımlaması yoksa, en son byte 0 değerini taşımalıdır. Aşağıda alert rutinini çağıran ufak bir altrutin görebilirsiniz.

Alert:
move.l  IntBase,a6
move.l — #0,d0
move.l — #Str,a0
move.l — #12,di
jsr — -90(a6)
Tts
Str:
de.w 92
dc.b 2
dc.b — 'Bubiralert'tir.',0
dc.b 0

Dilerseniz bir de birden çok satırlı alert için de bir örnek rutin vereyim.

Alert:
move.!  IntBase,a6
move.l — #0,d0
move.l — #Str,a0)
move.l #22, dl
İsr -90(a6)
Str:
de.w 108
dc.b 2
dc.b 'AMIGA
dc.b “1
de.w 92
dc.b 12
dc.b "Bu bir alert'tir.”,0
de.b 0

Bu ay inceleyeceğimiz başka bir fonksiyon da, yine Intuition library'de yer alan ClearPointer fonksiyonu. Bu fonksiyon ile istediğiniz window'un pointer'ını ROM'daki sabit pointer göstergeciyle değiştirebilirsiniz. Fonksiyonu çağırmak için sadece window pointer'ını a0'a atmamız ve 'jsr -60(a6)' ile de fonksiyonu çağırmamız yeterli. Artık pointer'ını sildiğiniz window'u aktif yaptığınızda, pointer değişerek ROM'dakinin kopyası olacaktır. Diğer çok kullanılan bir fonksiyon da PrintIText. Bunun yardımıyla bir pencere ya da screen'in içine intuition text'i yazdırabilirsiniz. Intuition text'in graphics library'deki Text fonksiyonundan farkı, intuition text'in window değişimlerinden silinip bozulmaması. Graphics library'deki text fonksiyonunu kullanarak bir pencere içine yazı yazdırdığımızda ve pencereyi küçülttüğümüzde, yazının pencere boyutu dışında kalan kısmı silinir. Fakat pencereyi tekrar büyüttüğümüzde yazımızın silinen bu kısmı tekrar yerine konmaz. Oysa intuition text'te yazımızı bozan her işlemden sonra window içeriği refresh edilerek bozulmanın tekrar düzelmesi sağlanır. Bütün bu işlemler otomatik olarak intuition sistemi tarafından gerçekleştirilir. PrintIText çağrılmadan önce 4 register belli parametrelerle yüklenmelidir. Bunlardan ilki, ekran ya da window'a ait rastport adresinin atandığı a0 register'ıdır. Yazı string'imizin başlangıç adresi ise a1 adres register'ına atanmalıdır. Yazı string'inin sonuna bir 0 byte'ı koymayı da unutmayın! d0 ve d1 register'ları ise yazının rastport'ta basılacağı x ve y koordinatlarını barındırır. 'jsr -216(a6)' ile de fonksiyonumuzu çağrabiliriz. Tabii ki her zaman olduğu gibi uygun library önceden açılmış olmalı (bizim durumumuzda intuition library) ve bunun base adresi a6 register'ında bulunmalıdır. Intuition library'de iki değişik fonksiyon da ScreenToBack ve ScreenToFront fonksiyonlarıdır. Bunlar yardımıyla istediğiniz ekranı öne çıkarabilir ya da en arkaya koyabiliriz. Bu fonksiyonların kullanımı tabii ki birden fazla screen kullandığınızda yararlı sonuçlar verebilir. Ön plana çıkarılması ya da arkaya atılması istenen pencerenin pointer'ını a0 register'ına atadıktan sonra, uygun fonksiyonu çağırmamız işlemin uygulanması için yeterli olacaktır. ScreenToFront fonksiyonun ofseti -252 (-$fc), ScreenToBack'inki ise -246 (-$f6)'dır. Aynı şekilde de WindowToBack ve WindowToFront fonksiyonları çalışmaktalar. Bunlarda da sadece window pointer'ını a0'a koymanız ve jsr yardımıyla fonksiyonu çağırmanız yeterli. Bu iki fonksiyon da aynı screen'lerde olduğu gibi pencereyi ön plana çıkarır ya da en arkaya atar. WindowToBack'in ofseti -306 (-$132), WindowToFront'un ofseti ise -312 (-$138)'dir. DisplayBeep fonksiyonu yardımıyla istediğiniz screen üzerinde bir anlık bir flash etkisi yaratabilirsiniz. Bu şekilde kullanıcıya hata yaptığını kolaylıkla bildirebilirsiniz. Bu fonksiyonu kullanmak için, sadece flash ettirilecek olan screen'in pointer'ı a0 adres register'ına atanmalı ve 'jsr -96(a6)' yardımıyla da fonksiyonun kendisi çağrılmalıdır. Herhalde bu aylık bu kadar intuition library açıklamaları yeter. Şimdi dilerseniz biraz da graphics library'sine göz atalım. Burada ilgimi ilk çeken fonksiyon BltClear. Bu fonksiyon yardımıyla blitter'ı kullanarak yüksek hızda hafıza temizleyebiliriz. Fakat bunun için temizlenecek hafıza bölgesinin blitter erişim alanı içinde bulunması şart. A3000'lerde bu alan ilk 2 MByte'lık bölgedir, fakat çoğumuz normal bir Amiga kullandığı için bu bölgeyi 512 KByte (Chip memory) ile sınırlamak zorunda kalıyoruz. Olsun, zaten bu fonksiyon daha çok grafik gösterimi olan programlarda kullanılabilir. Ekrandan hızla bir bölge silineceği zaman bu fonksiyon işimizi görür. Chip memory dışında kalan bölgeler için de, ne yazık ki dededen kalma yöntem olan loop içinde her byte'ı teker teker silme şeklini kullanmak zorundayız. BltClear fonksiyonu, iki şekilde çalışabilir. İlk yöntemde verilen adresten sonraki byte'lar direkt silinir. İkinci yöntem ise hafızadan dörtgen bir alanı silmek için kullanılır. Bu yöntem, grafik ağırlıklı programlarda bir hayli kullanılmakta. İlk önce dilerseniz ilk yönteme bir göz atalım. a1 adres register'ına silinecek bölgenin başlangıç adresi yazılmalı. d0 register'ında ise silinecek bölgenin byte olarak uzunluğu girilir. Bu değerin çift bir sayı olmasına dikkat edin. d1 register'ı ise silme şeklini belirleyen flag'dır. Burada normal silme modunu kullandığımızdan 1. biti set etmemiz gerekir. 0. bit (000000000x) set edilmiş ise blitter'ın yaptığı işlemleri bitirmesi beklenir. Demek ki, düz silme için d1 register'ına yazacağımız değer 3 olmalı. Fonksiyonu -300 (-$12c) ofsetiyle çağırabiliriz. İkinci silme modundaysa demin de belirttiğim gibi hafızadan dörtgen bir alan temizlenebilir. Bunun için d1'e 1 değerini yazmak gerekmekte. d0 ise hem dikey, hem de yatay boyutu belirlemek için kullanılır. Alt değerlikli 16 bit yatayda silinecek byte adedi (1 byte=8 piksel!), diğer 16 bit ise dikeydeki satır adedini belirler. Yataydaki byte adedi 128'i, dikeydeki satır adedi de 1024'ü geçmemelidir. Eh, bu aylık da ne yazık ki yerim doldu. Yine size bir dahaki aya görüşmek üzere hoşça kalın demekten başka bir şey kalmıyor.

TABLO 1 - Çeşitli library fonksiyonları

Fonksiyon ismi: DisplayAlert DisplayBeep MoveScreen Bulunduğu library: intuition.library intuition.library intuition.library Ofseti: -90 (-$5a) -96 (-$60) -162 (-$a2) Parametreleri: * giriş bilgileri: AlertNumber->d0; String->a0; Height->d1 Screen->a0 Screen->a0; dx->d0; dy->d1 * çıkış bilgileri: RECOVERABLE ALERT kullanıldığında sol mouse tuşuna basıldığında 0, sağ tuşa basıldığında -1. yok yok Fonksiyon ismi: MoveWindow ClearPointer PrintIText ScreenToFront Bulunduğu library: intuition.library intuition.library intuition.library intuition.library Ofseti: -168 (-$a8) -60 (-$3c) -216 (-$d8) -252 (-$fc) Parametreleri: * giriş bilgileri: Window->a0; dx->d0; dy->d1 Window->a0 RastPort->a0; Intuitext->a1 Screen->a0 * çıkış bilgileri: yok yok yok yok Fonksiyon ismi: ScreenToBack WindowToFront WindowToBack BltClear Bulunduğu library: intuition.library intuition.library intuition.library graphics.library Ofseti: -246 (-$f6) -312 (-$138) -306 (-$132) -300 (-$12c) Parametreleri: * giriş bilgileri: Window->a0 Window->a0 Window->a0 Memory->a1; Size->d0; Flags->d1 * çıkış bilgileri: yok yok yok yok