Bu sayfadaki yazılar
Sayfanın metni
Sayfa 19
Uzun zamandır ROM rutinlerini incelemek için gerekli hazırlıklarla uğraşıyorduk. Tabii ki bu arada birkaç önemli rutin gördük, ama bunların hiçbiri size söz verdiğim SIN, COS, vb. fonksiyonlarını yapmanızı sağlamıyordu. Geçen ay işlememiz gereken son konuyu, yani değişkenlerin ve dizilerin yapılarını da anlattıktan sonra, ertelenebilecek hiçbir konu kalmadı. Artık BASIC'in yapabileceği tüm matematik işlemlerini makine dilinde yaptırmayı sağlayacak bilgileri vereceğim. Ama her şeyden önce geçen sayının ROM'unda yapılan bir hatayı düzeltmek istiyorum: İlk örneğimizde 7 ile 13'ü birbiriyle çarpmak istiyorduk, ama çarpma rutininde $BA2B'ye değil $BF2B'ye sıçramanız gerektiği yazılmış. Aslında ufak bir hata gibi görülebilir, ama düzeltilmezse programınız hiçbir zaman çalışmaz. Doğru adresler için aynı sayıda yayınlanmış olan küçük tabloyu kullanmanız gerekiyor. Basit işlemler dışında kalan işlemleri tek tek vermek yerine, daha genel olan fonksiyonlardan bahsedeceğim biraz. Matematikçiler fonksiyonları
Y=F(X)
olarak yazmaya bayılırlar. Buradaki X, fonksiyonun girdisi, ya da argümanı, F fonksiyon ve Y'de sonuçtur. Kayan noktalı fonksiyonları çağırmadan önce argüman X, ya da kısaca FAC'a yerleştirilmiş olmalıdır. Sonuç Y, fonksiyondan dönüldükten sonra gene FAC'da bulunabilir. BASIC yorumlayıcısının kullandığı fonksiyonlar ve adreslerini Tablo 1'de görebilirsiniz. Bu tablodaki hesap uzunlukları PI sayısını argüman olarak verdikten sonra hesaplanmıştır.
Vedat Hallaç
İsim Adres Hesaplanma süresi - Açıklama ABS $BC58 0.0 ms mutlak değer ATN $E30E 44.6 ms arctanjant COS $E264 27.9 ms cosinüs EXP $BFED 26.6 ms e üzeri .. FRE $B37D 0.6 ms boş bellek miktarı INT $BCCC 0.9 ms tam değer fonksiyonu LOG $B9EA 22.2 ms doğal logaritma POS $B39E 0.3 ms cursor'un bulunduğu kolon RND $E097 3.5 ms rastlantısal sayı SGN $BC39 0.4 ms işaret SIN $E26B 24.5 ms sinüs SQR $BF71 51.2 ms kök TAN $E2B4 49.8 ms tanjant
BASIC işlemcisinin fonksiyonları ve adresleri.
Tablodan da görebileceğiniz gibi, fonksiyonların uzunlukları üç ana grupta toplanmış: Neredeyse 0 olanlar, 20-30 arası ve 44-50 arası. Ve gene fark edeceğiniz gibi; SIN, COS, EXP, LOG, TAN, ATN, SQR gibi komutlar göreli olarak daha uzun sürüyorlar. Bu fonksiyonların özellikleri, daha ön-
ce nasıl yapıldığını gördüğümüz dört işlemle hesaplanamamaları. Bunun yanında, değerlerinin de tam olarak bulunması imkansız. Ancak dört işlem kullanarak yaklaşık değerleri hesaplanabilir. Matematikçiler sağ olsunlar, bu tür fonksiyonların polinom gösterimi kullanılarak da hesaplanabileceğini bulmuşlar (konuya ilgi duyanlar MacLaurin ve Taylor Serileri konusunda bilgi edinmeye çalışabilirler). Bu polinomlar aşağıdaki formdadırlar:
A4a5Xx.54..
Eğer y'nin gerçek değerini bulmak isterseniz sonsuz sayıda terimi hesaplamalısınız. Tabii ki pratikte bunu yapmanız imkansız olacağı için gerçek değere yeterince yaklaştığınız bir noktada bu seriyi kesmeniz gereklidir. Bu da kaçınılmaz olarak gerçek değerden küçük bir miktar uzaklaştıracaktır sizi. Ne kadar fazla terim alırsanız o kadar kesin sonuçlar alırsınız, fakat hesabınız da oldukça uzar bu arada. Bu polinomların (diyelim ki) ilk altı terimini hesaplamak isterseniz
14 çarpım ve beş de toplama yapmanız gerekecektir (çarpılan terimleri birbirine eklemek için). Fakat bu işlemi yapmak için önerilen bir başka metod da vardır (Teşekkürler matematikçiler...). “Horner Metodu” adı verilen bu metod sayesinde beş terimlik bir işlemi parantezlere alarak şu şekilde yazabiliriz:
ya Xxtal
Bu sayede sadece beş çarpma ve beş toplama y'nin değerini hesaplamaya yetecektir. Genel olarak n. dereceden bir polinomun belli bir x için değerini hesaplamak
Klavyeyle gezinmek için ← ve → tuşları.
Sayfa 18
X değerini bir kere sola kaydırmak bu işlemi yapacak gibi görünebilir, ama sola kaydırmadan önce ilk iki biti temizlemeliyiz, çünkü sağa kaydırma işlemi sırasında ilk iki bitin değeri sıfırlanacaktır. Bu yüzden önce AND $FC komutuyla ilk iki biti sıfırlamamız, daha sonra ASL komutu yardımıyla ikiye çarpmalıyız. Şu anda çok dikkatli olmalıyız, çünkü carry flag'inde son hesabın en yüksek değerlikli biti var. Yapacağımız işlem carry'yi etkilerse bu bilgiyi kolaylıkla kaybedebiliriz. Bu yüzden ilk olarak A + 1'e sıfır eklemeliyiz. Bu biti korumaya aldıktan
$2000
$2001 $2002
$2003
$2140
Şekil 3 $2000'den başlayan bir ekranın kart boyutlarının adresleri
sonra gönül rahatlığıyla A'yı adresY'ye ekleyebiliriz. Eğer herhangi bir şeyi atlamadıysak şu anda adresin değerini hesaplamış olmalıyız. Buraya kadar yaptığımız işlemleri programımızı inceleyerek kontrol edin. Eğer anlamadığınız yerler olursa da bana yazın. Şimdi son iş olarak gerekli biti hesaplayıp AdresY'deki yerine yazmak kaldı. Yazının başlarında bit hesaplamak için bir sürü formül hesapladık, ama bu formülleri kullanmayacağız. Bunun yerine bit çiftini baytın en soluna koyacağız ve (X AND 3)'ün sonucu kadar bu bit çiftini sağa kaydıracağız (ikişerli olarak). Bu işlemin sonucu olarak X AND 3'ün değerleri şu sonuçları verecektir:
XAND3-0 - 4011000000 XAND3-İ - 9000110000 XAND3-2- 77000001100 XAND3-3- 000000011
(% işareti sayıların ikilik düzende olduğunu belirtir.) İlk olarak X AND 3'ün değerine göre, bir tablodan değer okuyup bu değerle adresY'yi AND'lemeliyiz. Bu tabloda şu değerler bulunmalıdır:
Buraya kadar olan yerde gerekli adreste bulunan noktayı sildik. Şimdi bu adrese koyulacak noktayı, kullanıcının seçtiği rengi verecek bit çiftiyle doldurmalıyız. Bu bit çiftini de bir tablodan okuyoruz: 11000000, 01100000, 00011000, 00000110. Şimdi de okunan bu bit çiftini X AND 3'ün değeri kadar sağa kaydırmalıyız (her seferinde iki bit kaydırarak). Küçük bir döngüyle bu kaydırma işini de hallettikten sonra adresY'de bulunan değeri alıp hesapladığımız bu değerle ORA'larsak ve adresY'ye geri yazarsak noktayı da basmış oluruz. Pek yerimiz kalmadığı için rutinleri detaylı olarak inceleyemeyeceğiz, ama bu işi yapabilecek kapasitede olduğunuza inanıyorum. Eğer bu programın çok yavaş nokta koyduğunu düşünüyorsanız, kullanıcıdan data almanın yeni bir yöntemini bulmalısınız. Benim burada kullandığım yöntem her data almak istediğinizde üç adet ROM rutini kullanıyor, ve bu rutinlerin hızlı olduğunu kimse söyleyemez. Bu rutinleri kullanmamak için ya doğrudan doğruya POKE'larla çalışan bir program yaparsınız ya da yeni ROM rutinleri bularak hızlı bir şekilde data okuyabilirsiniz. Eğer hesaplarda hız istiyorsanız, en uygun kısmı 320 ile çarpma rutininin sonuçlarını bir data tablosu olarak hazırlamak (düşük değerlikli baytlar bir yerde, yüksek değerlikler başka bir yerde), sonra da Y/8'inci elemanı doğrudan doğruya bu tablodan okumak size oldukça zaman kazandıracaktır. Aslında uygun tablolar hazırlayarak tüm hesaplamalardan kurtulabilirsiniz, ama bu şekilde oldukça fazla bellek harcarsınız. Aslında bu konuda daha uzun yazmak isterdim, ama yerim dolduğu için bu aylık burada kesmem gerekiyor. Gelecek ay görüşmek üzere hoşçakalın.
Şekil 4: Noktaların ikişer ikişer gruplanması