Rom

erkese merhaba. Hatırlayacağınız gibi geçen sayıda polinomların yardımıyla bazı yılarının nasıl hesaplanacağı konusuna ise yazımda değinmeyeceğim, çünkü türev almayı çok iyi bilmeden bu polinomların katsayılarını hesaplayamazsınız. Eğer bu konuyla ilgileniyorsanız Ve fonksiyonların türevlerini rahatça alabiliyorsunuz ya Taylor ve McLaurin serileri konusunda ufak bir araştırma yapın, ya da bana yazarak basit bir şekilde katsayıların nasıl hesaplanacağını öğrenin. Ama bilgisayarınıza yeni fonksiyonlar eklemek gibi bir niyetiniz yoksa (ARC-COS gibi) bu fazladan bilgiye ihtiyacınız olmayacaktır. Eğer bir fonksiyon eklemeyi kafanıza koyduysanız, fakat matematik kısmından sıkılıyorsanız, ekleyeceğiniz fonksiyonun katsayılarını tanıdığınız bir matemasiniz. Bana bu konuda da yazabilirsiniz, fakat size vereceğim cevap bir matematik öğretmenininki kadar garantili olmayacaktır. Zaten büyük bir çoğunluğunuz bu konuda Geçen sayıda sizlere sorduğum faktöriyel hesaplama rutini konusunda hiç mektup ulaşmadı elime. Ama gene de size söz verdiğim gibi gelecek sayıya kadar bekledikten sonra doğru (en doğrusu olmasa da) rutin ve (eğer yollarsanız) sizin çözümlerinizi yayınlayacağım. Kısacası beklemedeyim. Eğer belli bir yerinde takıldıysanız, takıldığınız yer konusunda da bana danışın. Bu kadar çok konuda “bana yazın', *bana sorun' gibi lafları söylememin sebebi, sizlerden gelen mektupların arkasının kesilmiş olması, Sizlerden gelen bir yönlendirme olmadan konu seçiminde körlemesine gitmekten başka çarem kalmadığını uzun zamandır söylüyorum. Yaklaşık iki aydır sizlerden mektup olmadığım için bu konuların büyük bir kitleye hitap edemediğini düşünmeye baş-

Rom

Vedat Hallaç ladım. Bu yüzden gelecek sayıdan itibaren bu yazıyı bitirmeyi ve yeni Commodore'cular için bir makine dili kursuna başlamayı düşünüyorum. Bu kurs, makine dilinden hiç anlamayanlara göre düzenlenecek. Makine dili öğrenmek için çırpınan arkadaşlarınızı da belli bir seviyeye getirdikten sonra ROM'- un kullanımı gibi konulara geri döneceğiz. Gelecek sayıda bu konuda daha ayrıntılı bilgi bulabilirsiniz. Bu sayıda basit bir polinom hesaplatma örneğini verdikten sonra makine dilinin gerçekten de işe yarar konularda kullanılabileceğini gösteren bir program inceleyeceğiz. Son olarak da ROM'da bulunan önemli rutinlerin adreslerini ve bazı sabitlerin bulunduğu yerleri içeren bazı tablolarımız olacak. Hepimize kolay gelsin. Biliyorum, hepiniz polinom hesaplamaktan bıktınız, çünkü görünürde pek bir işinize yaramıyor. Ben de polinom hesaplamaktan bıktım, çünkü kullanıcı aşamasında gerekten de işe yaramıyor. Ama başladığımız işi tam olarak bitirmek için son bir polinom örneği daha yapmamız gerekiyor. Ayrıca, bu son örnekteki tipte bulunan polinomlar, çoğu fonksiyonun hesaplanmasında kullanılırlar. Bazı polinomlar aşağıdaki formda bulunabilir:

İ 34a2xx 174... Bu polinomu yeniden düzenlersek:

ral 2 *a3x(X12)134...)

Bunu hesaplamak için X yerine X 2koyarak polinomun değerini hesapladıktan sonra sonucu Y ile çarpmanız gerekir. Daha doğrusu ROM'da bu işi yapacak rutin bulunmasaydı yukarıda saydıklarımı yapmanız gerekecekti. Çoğu fonksiyonun polinomu bu formda olduğu için ROM'unuzda bu tip polinomların değerini hesaplayacak program hazır olarak kullanılmayı bekliyor. Bu şekilde tanımlanan bir polinomun değerini hesaplamak için geçen sefer anlattığım türde bir yapı oluşturduktan sonra (Başta polinomun derecesi, sonra da katsayılarının bulunduğu yapı. Hatırladınız mı?) $E043 adresine sıçramanız gereklidir. Bu polinomların işe yarayabilmesi için giriş değerinin belli sınırlar içine getirilmesi gereklidir. Periyodik bir fonksiyon kullanıyorsanız bu işi yapmak siiçin problem olmayacaktır. Mesela SIN (3 Xpi)'yi hesaplamaya çalışmak yerine SIN (pi)'yi hesaplamak yerinde olacaktır. Tabii ki ROM'da bulunan SIN fonksiyonu bu ayarlamaları sizin için yapacaktır. İsterseniz örneği bir an önce vereyim de bu sıkıcı konudan kurtulalım. Polinomumuz şöyle bir şey olsun:

Y-6Xx40.5xx13-0.11xx17

Bu polinomda ilk olarak x^5'li terimin eksik olduğunu fark etmenizi bekliyorum. Bu katsayı yerine sıfır koyarsak polinomumuz şu şekle girecektir: y=6x^6+0.5x^13+0x^15+(-0.11)x^7. Bu polinomu hesaplayan rutini yazmak çocuk oyuncağı. Tablo 1'e bakın.

*-828
POLY2-$E043
LDA #<KATSAYI
LDY #>KATSAYI
JMP POLY2
*BYT 3 derecesi
*FLP -.11 ;son katsayı
*FLP O
*FLP 0.5
.FLP 6
KATSAYI
katsayı

Tablo-1: Örnek polinomun değerini hesaplattıran program.

Geçen sayıda sizin assembler'ınızın .FLP gibi bir işlemi olmayabileceğini söylemiştim. Eğer bu işlem assembler'ınızda yer almıyorsa sayıların değerini şu yöntemle bulabilirsiniz: 1. BASIC'de hiç değişken yokken “A” komutunu girerek A değişkenine ikilik gösterimini bulmak istediğiniz sayıyı yerleştirin.

2. Bir monitör programına girin. Kartuşunuzun böyle bir programı varsa onu kullanın, yoksa 1. basamağı yapmadan önce monitör programını belleğe yükleyin ve BASIC'de kalın. 3. $2D-$2E adreslerinden yararlanarak ilk değişkenin yerini öğrenin. 4. Bu değişkenin harflerinden sonra gelen (hatırlarsanız ilk iki bayt değişkenin harflerini tutuyordu) beş baytın değerini bir yere not edin. Tablo 1'de de görebileceğiniz gibi polinom derecesi olarak 7 değil de 3 kullandık. Bunun sebebi, polinomu başta gösterdiğim gibi ayırdığınızda x 7'li terimin (X 12) 1 3 olarak görünmesidir. : Birkaç değer için fonksiyonumuzu denersek şu sonuçları elde ederiz: USR(0) =0 USR(1) =6.39 USR(2) = 1.92 USR(.75) =4.69625427 Daha kullanışlı konular da var... Kayan noktalı gösterimle ilgili konumuzu kapatırken çoğu zaman karşınıza çıkan bir problemin çözümünde makine dilinin ne kadar faydalı olacağını göreceğiz: Sayılarla dolu bir diziyi sıralamak. Makine dili programımız Tablo 2'deki rutinin yaptığı işi gerçekleştirmeye çalışacak.

100 FOR I-1 TO N : FL-0
110 FOR J-N TO I STEP -1
120 IF A(J-1)>A(J) THEN H-A(J)
130 NEXT J
140 IF THEN RETURN
150 NEXT I : RETURN

göre, bu sayıyla bir karşılaştırma daha yapmak pek de akıllıca olmayacaktır. Bu yüzden iç döngünün değeri son sayıdan ilk döngünün değerine kadar değişiyor yalnızca. Bu sayede karşılaştırma sayısını azaltarak hızı artırıyoruz. Bu işlemi yapılan bir ek daha var. Her “en küçük bulma” işlemi başında bir flag'i sıfırlıyoruz. Eğer yer değiştirme olursa bu flag'in değerini 1 yapıyoruz. Eğer “en küçüğü bulma” işlemi bittiği halde bu flag sıfırsa, bu taramada hiç yer değiştirilme yapılmamış olduğunu ve dolayısıyla dizinin sıralanmış olduğunu anlıyoruz. Bu karşılaştırma, özellikle yarı sıralı dizilerde dikkate değer bir hız artışı sağlıyor. İlk taramamız N'inci elemandan 0'ıncı elemana kadar tarıyor. İkinci turda ise N.'den 1.'ye kadar taranıyor ve bu işlem bu şekilde sürüyor. İsterseniz ilk olarak bazı koşullar koyarak bu sıralama rutinini olabildiğince basitleştirelim: 1. Dizimiz, dizi listesindeki ilk eleman olmalı.

2. Dizimiz tek boyutlu olmalı. 3. Dizimiz noktalı sayılardan oluşmalı (Tam sayı veya string'ler bu kuralları ihlal eder). Eğer dizilerin bellekte nasıl saklandığını hatırlarsanız (ya da geçen sayıyı bir daha

A(I)SA(J-1) : A(J-1)-H

Tablo-2: A(N) dizisini sıraya sokacak BASIC alt programı.

Bu program A(N) dizisinde yer alan sayıları küçükten büyüğe doğru sıralayacaktır. Çalıştırmak için ise sadece GOSUB 100 demeniz gereklidir. Rutin, en basit algoritma olan kabarcık sıralama (namı diğer BUBBLE SORT) tekniğini kullanıyor. Algoritmanın mantığı içerir. Eğer ardışık iki sayıdan ilki daha büyükse, onların yerleri değiştirilir. Tüm sayılar bu şekilde yukarıdan aşağı doğru tarandığı zaman en alttaki sayı en büyük sayı olur. Eğer tarama aşağıdan yukarı doğru yapılırsa (ki Tablo 2'de bu sistem kullanılmış) en üstteki sayı en küçük sayı olur. Tüm diziyi sıralamak istediğimize göre, bu işlemi tüm sayılar için tek tek yapmalıyız. Ama en üstteki sayının en küçük sayı olduğunu bildiğimize okursanız) bu kuralların sebebini daha kolay anlayacaksınız. Dizinin ilk eleman olması, diziler arasında doğru olanını bulmaya çalışmak gibi zahmetli(!) bir işten kurtaracaktır bizi. Tek boyutlu bir dizi kullandığımızda, elemanların yerini bulmaya çalışmak gibi işlerle uğraşmayız, çünkü ardışık iki eleman arasında beş bayt bulunduğunu biliriz. Son şık basit bir kontrolü daha yapmaktan kurtarıyor bizi. Eğer sıralanacak dizi tam sayı ya da string'lerden oluşuyorsa değişik yapıları test etmemiz gerekecekti, ki bu da daha uzun bir program oluşturacaktı. Tabii ki daha kapsamlı bir program daha çok işinize yarayacaktır. Fakat bu yazıya ayrılan sayfaların sayısı bu kadar detaylı bir çalışmaya izin vermiyor.

En iyisi, lafı daha fazla uzatmamak. Programın assembler listesini Tablo 3'te görebileceğiniz için detaylı olarak buraya yazmayacağım. Program MDE listesini döküm ekinde bulabilirsiniz.

-
- $57
« $59
- $5B
« $BBA2
$BCSB
ARRTAB
4802
uzunluğunu ekle
ş;N pointeri dizi
göstersin.
(ARRTAB) ,Y
»
NPNT*1
KPNT
45805
NPRT

sonunun beş eksiği son elemanın adresini verir. Lı ARRTAB

Li
BE

41 pointer'ı dizinin ilk elemanını göstersin )

KA
>»
ğ

temizle

BAR
bel
>
35
STA
TAY iyüksek değerlikli Y'ye
'TXA şdüşük değerlikli A'ya
FAC'a
maya kalkarsanız, ilk baştaki doksan değe-
rin sıfır olduğunuz ve sonraki sayıların (eğer
sayılarınızın hepsi pozitifse) sizin dizinizin
sıralanmış hali olduğunu görürsünüz. Bu
yüzden, DIM kullanmadan açılan dizilerde
(eğer eleman sayısı 10'dan azsa DIM komu-
LDA JPNT
JSR COMPARE ile FAC'ı karşılaştır
BM büyük ise dallar
LOY büyük
STY FLAG #Flagsd
SWAP LDA (JPNT),Y
TAX
LDA (JPRTİ),Y
ile
TXA
STA (JPNT1),Y
BPL SWAP
NOSWAP LDA
SEC
sac 4505
STA JPNT
BC$ TESTİ
DEC
TESTİ CMP I1PNT
BNE — JDÖNGÜSÜ
LOA
CHP
BNE
LDA FLAĞ
BEO BİTİR şEvet.
LDA IPNT
ADC
STA IPNT
BOC TESTİ
ENC
TESTİ CMP
BNE — İDÖNGÜSÜ
LDA
CMP #İ-N?
BNE ;Hayır.
BİTİR RTS şEvet.
FLAG *BYTEO
NPNT

Tablo-3: Sıralama işlemini makine dilinde yapacak olan programın assembly listesi.

Bu program A(N) dizisini deminki BASIC program kadar iyi sıralar. Peki BASIC'den kolayca yazmak dururken neden bu karmaşık makine dili rutinleriyle boğuştuk? Bu sorunun cevabını yer alan ufak hız karşılaştırması gösterecektir. Makine dili rutinini yükledikten sonra kalacak yerlere SYS 828'leri koymanız gereklidir. Ama demin olması gerektiğini söyleyerek sıralanmayacaktır. Eğer 100'lük bir dizinin on elemanını doldurup bunu sıralatmanıza ihtiyacınız yoktur. Programın en başında kullanacağınız bir A(5) 53 komutu A için 10'luk bir dizi açacaktır.) 10'dan az eleman kullandığınızda doğru sonucu elde edemezsiniz. Tablo 4'de de gördüğünüz gibi makine dili programımız dizi boyutu büyüdükçe daha fazla zaman kazanmanızı sağlıyor. Eğer bu program bile size yavaş geliyorsa (çok büyük dizileri sıralamak için), daha etkin sıralama algoritmaları kullanmalısınız. Geçen sayılarımızda Sinan sıralamalar konusuna değinmişti. O yazıdan Quick sort algoritmasının mantığını öğrenebilirsiniz. Eğer makine dilinde kendinize gerçekten güveniyorsanız quick sort'u yapmayı bir deneyin. Gerçekten de kendi yığıt'ınızı (stack'inizi) oluşturmanız ve belli sayıları bu yığıta mantıklı bir şekilde atmanız gerekecek. Bu yüzden bu algoritmanın makine diliyle gerçekleştirilmesi oldukça (oldukçadan daha fazla) zordur. Biraz alıştırma yapmak isterseniz, burada yayınlanan sort programını adam etmeyi deneyin. Mesela gerekli kontrolleri yaparak herhangi bir kayan noktalı diziyi sıralamasını sağlayın (sadece ilk diziyi değil). Ya da tam sayı ve string'leri de sıralayabilen genel bir sıralama programı yazın. Tabii her zaman söyledim, söyleye söyleye dilimi kafamdan daha tüylü hale getirdim lafımı tekrarlayacağım: Yaptığınız programları bana da yollayın. Gerçekten de yazılarımın ne derecede işe yaradığını merak ediyorum. Kendi çalışmalarınızda kullanabilmeniz için sık kullanılan ROM rutinlerinin adreslerini Tablo 5'de bir araya getirdik. FAC kolonunda bulunan bir * işareti, FAC'ın içeriğinin değişeceğini, işareti ise aynı kalacağını belirtir. Eğer fonksiyon hem FAC'ı hem de ARG'ı kullanıyorsa rutin çağrılmadan önce A register'ı, yani akümülatör, FAC'ın üssüyle ($61) yüklenmelidir. AND, OR ve NOT gibi mantık işlemlerinde ilk olarak değerler 16 bit tamsayılara çevrilir, daha sonra bitler üzerinden gerekli işlem yapılır ve sonuç tekrar kesirli sisteme döndürülür. BASIC yorumlayıcısının işlemleri yaparken kullandığı bazı sabitler de ROM'da yer alır. Bu sabitlerin değerlerini, anlamlarını ve adreslerini de Tablo 6'da görebilirsiniz. Bu değerler matematiksel işlemleri yaparken sık sık karşınıza çıkacaktır.

Evet, son yazımız da buraya kadar. Aslında işe ilk başladığımda çok daha derinlere inmeyi düşünüyordum, ama daha önce de belirttiğim sebeplerden dolayı bir süre aşırı teknik yazılardan kaçınacak, daha çok yeni başlayanlara yönelik makine diline başlangıç yazılarına yer vereceğiz dergimizde. Bu sayede burada ele alacağımız konulardan daha fazla yararlanabileceksiniz. Eğer Commodore 64'ünüzün tüm ROM'unun makine dili listesini elde etmek istiyorsanız dergimize yazın. Bu konuda size verebileceğimiz çok güzel bir kitap var. İngilizce açıklamalarıyla birlikte tüm BASIC ROM ve KERNAL programları bu kitapta yer alıyor. Yeni bölümlerde buluşmak üzere hepiniz hoşçakalın.

N BASIC Program Makine Dili Rutin 10 0.0" 50 24" 0.4" 100 37" 1.5" 200 6' 6.3" 500 41/ 38.7" 1000 2s 44' 2' 33.4" Tablo-4: Makine dili rutin ile BASIC programın N boyutlu bir diziyi sıralama süreleri.

Adres Sabitin Adresi Hazırlık FAC İşlev $BABC A/Y ARG - sabit $BBEC - FAC « ARG $BB12 FAC « ARG/FAC A/Y FAC « sabit/FAC $BAE2 - FAC - FAC*10 $BAFE - FAC — FAC/10 , $B849 FAC FAC*0.5 $BBA2 FAC sabit ARG « FAC $BBD4 sabit - FAC $B853 FAC « ARG-FAC $B850 FAC « sabit-FAC FAC - ARG*FAC $BA2B FAC « FAC — FAC - sabit*FAC $BF7B FAC —« ARG“FAC $BF78 FAC — ARG“sabit FAC polinom $B043 FAC « polinom2 $AFE6 FAC « ARG OR FAC $AFE9 FAC — ARG AND FAC $AED4 FAC NOT FAC $BC5B FAC ile sabiti karşılaştır $BC1B - FAC'ı yuvarla $BEFB4A - - FAC -FAC Tablo-5: ROM'da bulunan önemli rutinlerin adresleri. Geçen sayıda birlikte tüm fonksiyonları göstermiş oluyoruz. Tabloda gösterilen A, X ve Y harfleri register adlarıdır. FAC ve ARG de daha önce bahsettiğimiz adreslerde ($61.. , $69..) yer alırlar, * ğ Db 4 4 b 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1

DEĞERİ 3.14159265 -32768 1 *434255942 2.88539007 *707106781 1/SOR(2) 1.41421356 SOR(2) -.5 :693147181 LOG(2) 10 99999999.9 999999999 1E9 1.44269504 1/106(2) 2.14987637E-5

$BFE8 00 00 00 1
35 44 TA 11879546
$E092 28 BI 46 3.92767774E-Â
$E2EO 49 OF DA 1.57079633
$E2E5S 49 OF DA 6.28318531
$EZ2EA 00 00 00 00 :25
$E2FO EĞ 1A 2D
$E2FS 28 07 FB F8 42.0077971
$E2FA 99 68 89 Ol — -76.7041703
$E2FF 23 35 DF El 81.6052237
$E304 AS 5D E? 28 — -41.3147021
$E309 49 OP DA A2 6.28318531
$E33F B3 83 BD D3 — -6.84793912E-4
$E344 1E F4 AĞ F5 4.85094216E-3
$E349 83 FC BO 10 -.0161117015
$E34E OC 1F 67 CA
$E353 DE 53 CB  -.054279133
$E358 14 64 70 4C .0724571965
$E35D B7 EA 51 TA  -.0898019185 1.4352314E-4
$E362 63 30 88 TE *110932413 1.34226348E£-3
$E367 92 44 99 TA 1D 84 1C
$E36C 4Cc cc 91 c7 «19999912 7C 63 59 58 «0555051269
$E371 AA AA AR 13 — -.33333316 TE 75 FD EE? .240226385
$E376 00 00 00 00 1 80 31 72 18 10 .693147186

Tablo-6: Bellekte yer alan sabitler, değerleri ve çok önemlilerinin anlamları. Eğer yapacağınız işlemlerde bu sabitler gerekiyorsa, değeri programınıza eklemenize gerek yok. ROM'unuzu kullanıverin.