ROM'unuzu Kullanın

epinize merhaba. Hatırlayacağınız gibi, ilk sayımızda bilinmesi mutlaka gerekli olan birkaç ROM adresini verdikten sonra, ROM aritmetiğinin teorisini vermeye başlamış ve geçen sayıya kadar bu konu üzerine eğilmiştik. Geçen sayıda tam sayıları ondalık sayılara çeviren rutinleri de anlattığımıza göre, ROM'da bulunan işlemlerin nasıl kullanıldığını anlatmaya sıra geldi. İlk olarak toplama, çarpma gibi basit işlemlerin adreslerini anlatmayı düşünüyorum. Daha sonra, yerimiz kalırsa, değişkenlere nasıl erişeceğimizi ve karmaşık işlemleri nasıl gerçekleştireceğimizi anlatacağım. Daha sonra değişkenlerin makine dili yardımıyla nasıl kullanılabileceğine bir göz atacağız. Eğer bu hızla devam edebilirsek, iki aya kalmadan tüm fonksiyonları makine dilinden kullanmayı öğrenebilirsiniz. Tüm bu teknik bilgilerin yanı sıra bazı örnek programlar yardımıyla bilgilerinizi pekiştirmeyi de unutmayacağız tabii ki. Artık asıl konuya girebiliriz: Temel Aritmetik İşlemler

BASIC yorumlayıcısının beş adet temel işlemi vardır: Toplama, çıkarma, çarpma, bölme ve üs alma. Bu işlemlerin her birinin iki adet argümana (elemana) ihtiyacı vardır. Temel fonksiyonlardan birini kullanacağınız zaman ilK argümanı FAC'a, ikincisi de ARG'a yerleştireniz gerekir. Fonksiyonu çağırdıktan sonra sonucu FAC'da bulabilirsiniz. Bu temel işlemlerin adresleri şöyledir:

TOPLAMA FAC:-ARG4*FAC $B86A
ÇIKARMA FAC:-ARG-FAC $B853
ÇARPMA FAC:-ARG'FAC $BA2B
BÖLME — FAC:-ARG/FAC
ÜSALMA FAC:-ARG.FAC $BF7R

Bu rutinlerden herhangi birini çağırmadan önce FAC'ın üssünü ($01) A registerine (akümülatöre) yerleştirmeniz gereklidir. Eğer bu üs sıfırsa, ROM FAC'da bulunan sayının da sıfır olduğunu kabul ederek işlem yapacaktır. Bu yüzden tüm işlemlerden önce A'da ne bulunduğunu ayarlamayı unutmamalısısa, veya bölme işlemlerinizde DIVISION BY ZERO ERROR mesajı veriyorsa, A'ya doğru değeri yerleştirmediğinizi anlayabilirsiniz.

İsterseniz monitör programımızı kullanarak iki sayıyı birbiriyle çaryalım:

74132?
7583 E0 00 00 00 00
1384 DO 00 00 00 00

Yukarıdaki değerleri FAC #1 ve FAC 12'ye yerleştirin ve çapma rutinini çalıştırın:

0061 83 E0 00 00 00 00
0069 84 DO 00 00 00 00
., 1000. ASGILDA $61
., 1002 202BBF JSR
., 1005 00 BRK
.G 1000
«1 0061 87 B6 00 00 00 00 00

Sonucu ondalık sayıya çevirirsek:

> 1011011 — 64416484241-97-7*13

Bir de 37'yi hesaplayalım:
CO 00 00 00 00
7-83 E0 00 00 00 00

Bunları gene FAC ve ARG'a yerleştirmeliyiz. Yalnız işlemin ARG . FAC olarak yapılacağını unutmayın. Yani 3'ü $69'dan, 7'yi de itibaren yazmalıyız:

83 E0 00 00 00 00
«1 0069 84 CO 00 00 00 00
., 1000 ASGILDA $61
1002 207BBF JSR $BETB
., 1005 00 BRK
.G 1000
0061
0061 8C 88 BO 00 02 00 00

Türkçesi: 1.000 1000 1011 0000 0000 0000 0000 0010 1000 1000 1011. 0000 0000 0000 0000 0010 —20484128484241-41.9*10.-6 Ne garip değil mi? 2187 kısmı doğru, ama sonuna garip garip sayılar gelmiş. Normalde sadece 9 rakam basılacağı için PRINT 3.7 yazınca ekranda 2187 görünür. Ama

PRINT 3.7-2187

yazdığınızda sıfır yerine 1.90734863E-06 görürsünüz. İyi de bu garip artık kısım nereden geliyor? Bu sorunu cevabını öğrenmek için üs alma rutinini incelediğimizde üs alma işleminin şu şekilde yapıldığını görürüz:

EXP(B*LOG(A)) EXP ve LOG işlemleri yalnızca belli bir dereceye kadar kesinlik gösterebildiği için -- sebebini daha sonra göreceğiz- işlemin sonucunun sonunda garip rakamlar kalması pek de sürpriz sayılmaz. Üs alma işleminin gerçekleştirilmesi için iki ayrı işlem yapılması gerektiği için bu işlem diğerleri arasında en yavaş işleyenidir. Ortalama olarak 50 milisaniyeden (saniyenin binde biri) biraz daha fazla zaman harcar. Bu yüzden basit üs alma işlemlerini elinizden geldiği kadar çarpma işlemleriyle yaparsanız hem daha hızlı, hem de daha kesin sonuçlar elde edersiniz. Mesela 3.2 işlemini 3*3 olarak yaptığınız zaman en az yirmi kaz hızlı çalışacaktır. İşlemlerin hızlarını daha sonra bir tablo halinde yayınlayacağız. Şu ana kadar öğrendiklerimizin pratikte kullanılabilmesi için BASIC yorumlayıcısının değişkenleri nasıl kullandığını öğrenmemiz gerekecek. Zero-page'da (sıfırıncı sayfa:$00-$FF arası belleğe verilen ad) birkaç adres değişkenler hakkında bilgi tutar. Bu adreslerde BASIC programın yeri, normal değişkenler, indeksli değişkenler ve string'- lerin (A$ gibi değişkenler) bellekteki yeri gibi değerli bilgiler saklanır. Değişkenlerin yerini gösteren adresler aşağıdaki tabloda göskarakterlerinin sonu $37/S38 BASICRAM'in sonu

Tablo-l: Sıfırıncı sayfa değişkenleri ve gösterdikleri adreslerin yerleşimi.

Bilgisayarınızı ilk açtığınız zaman BASIC programının yerleştiği adres $0801 2049 olarak belirlenmiştir. Bu alanın sonu $A000 adresidir.

I0A-I

satırını girdiğiniz zaman bilgisayarınızda aşağıdaki işlemler yapılır: -$0801 bölgesi sırasıyla şu değerleri alır: -bir sonraki satırın adresi -satır numarası (Düşük değerlikli, Yüksek değerlikli) -tokenler haline getirilmiş program satırı -satır sonunu belirten $00 baytı Bir monitör programıyla bu adresi incelediğimizde şunu görürüz:

«1 0800 00 09 08 0A 00 41 B2 31
«1 0808 00 00 00

Ve program bilgilerini saklayan adreslerde şu bilgilerle karşılaşırız:

«1 002B 01 08 OB 08 OB 08 OB 08
«1 0033 00 A0 00 00 00 A0

Bu değerleri yorumlamaya çalışalım. $2B/$2C adresleri $0801 adresini gösteriyor. Burası BASIC programının başlangiç adresi. $0801 adresine bir göz atarsak burada gelecek satırın adresini, yani $0809'u bulabiliriz (tabii ki $09 $08, yani düşükyüksek değerlikli bayt formatında). Daha sonraki baytta ($0803,$0804) satır numarasını düşük-yüksek değerlikli bayt formatında bulabiliriz. Yani $OA $00 — $000A — 10. Daha sonra da programın tokenler haline getirilmiş kodunu bulabiliriz. $41 ““A” harfinin ASCII karşılığıdır. $B2 BASIC yorumcusu için *—” anlamındadır. $31'de karşılığıdır. Bunlardan sonra gelen $00 baytı da satırın bittiğini gösterir. Bir sonraki program satırı da aynı sistematikle saklanır. Ama sadece bir satır girmiş olduğumuz için bir sonraki satırın adresi yerine $0000 buluruz. BASIC yorumcusunun kabulüne göre bu değer BASIC programın bittiğini gösterir. Bunu takip eden adres, yani $080B — $2D/$2E *'de saklanır ve hem programın sorunu, hem de normal değişkenlerin başlangıcını belirtir. Herhangi bir değişkenimiz olmadığı için, Array'lerin (dizilerin) başlangıcı da bu adrestedir. Eğer programı RUN ile çalıştırırsak A değişkeni için yer ayrılır: 0800 00 09 08 0A 00 41 B2 31 0808 00 00 00 41 00 81 00 00 «1 0810 00 00

002B 01 08 OB 08 12 08 12 08
«1 0033 00 A0 00 00 00 A0

Bakın. Şimdi değişkenlerin başı olan $2D/$2E $080B'yi gösterirken, dizilerin başı olan $2F/$30 $0812'yi gösteriyor. Kısaca, $080B-$0812 arasındaki 7 bayt bizim A değişkenine ayrıldı. Bu bölgeyi incelersek:

080B 41 00 81 00 00 00 00

Değişkenlerin saklandığı alan genelde 7

bayt uzunluğundadır. Bildiğiniz gibi değişken adları maksimum iki karakter olabilir. O zaman değişken girişinin ilk iki baytı değişkenin adına ayrılmış olmalıdır. $080B'de bulunan $41 - “A” bu varsayımımızı doğruluyor. Daha sonra gelen beş bayt, kolay kullanım açısından ondalık sayı formatında A değişkeninin değerini içerir. 82 00 00 00 00 sayısı ondalık düzende 1'e eşittir zaten. Bir de tam sayı değişkenleri kullanıldığı zaman ne olacağına bakalım isterseniz. Programın ilk satırını

I0A

şeklinde değiştirdiğimiz zaman bunu yapmış oluruz. Programı çalıştıralım ve BASIC ve sıfırıncı sayfanın durumuna bakalım:

«: 002B 01 08 0C 08 13 08 13 08
«1 0033 00 A0 00 00 00 A0
«1 0800 00 0A 08 0A 00 41 25 B2
«1 0808 31 00 00 00 Ci 80 00 01
0810 00 00 00

Sıfırıncı sayfa elemanlarının ne demek istediğini kolayca anlıyor olmanız lazım artık. Ama ben kopya çekmek isteyenler için tekrarlayayım: “BASIC programı $0801'de başlıyor ve $080C'de bitiyor. Bu adreste değişkenler başlıyor ve $080C-$0813 arasını istila etmişler. $0813'te başlaması gereken diziler ise henüz ortalıkta yoklar.”. Ne kadar kolay, değil mi? Dikkat ettiyseniz BASIC programı artık bir bayt daha uzun. Çünkü “We” karakterini araya ekledik. Şimdi A% değişkenin yerini bulmaya çalışın. Ben sizi bekliyorum... Buldunuz mu? Hayır mı? O zaman birlikte inceleyelim: Demin de söylediğim gibi değişkenler $080C'de başlıyor. O adreste ne var? $C1? Sakın bu baytın $41'le bir benzerliği olmasın? Aaa, sadece $41'in son biti 1 yapılmış o kadar ($80+$41). Bir sonraki bayt da bunu doğruluyor zaten. Demek ki son bit buradaki değişken bir tam sayı olacakmış. Bir de değişkenin değerini okumayı öğrendik mi tam sayılarla işimiz bitmiş demektir.

$C1 $80'den sonraki beş bayta 00 01 00 00 00 değerleri yerleşmiş. A'nın değeri 1 olduğuna göre ya ilk iki bayt $00 $01 —$0001 — 1 anlamına geliyor, ya da çok garip bir format kullanılmış. Bir iki sayıyla değerlikli olarak A%'nın değerini sakladığını görürüz. Demek ki tam sayılar 16 bitten fazla değer alamazlarmış. Sondaki üç bayta bir iş yakıştıramadığımıza göre herhangi bir işleri yoktur. Madem üç bayt boşa kullanılıyor, tam sayı değişkenleri kullanmak programın az bellek harcamasını sağlamaz. Hızda da herhangi bir artış yoktur. Hatta kesirli sayılara çevrileceği için daha da yavaşlatır. Öyleyse tam sayı formatını kullanmamak hayrımıza olacaktır. Bir değişken türü daha var kontrol etmemiz gereken: string değişkenleri. Şu satırı girin ve çalıştırın:

10 A$- “STRING”
Monitörü gene kullanırsak:
«1 002B 01 08 13 08 TA 08 1A 08
«1 0033 00 A0 00 00 00 A0
«10800 00 11 08 CA 00 41 24 B2
«1 0808 22 53 54 52 49 4E 47 22
«1 0810 00 00 00 41 80 06 09 08
0818 00 00

Sıfırıncı sayfada string alanını gösteren baytlara baktığımızda her şeyin aynı kaldığını görürüz. Bu durumda değişkenin bulunduğu yeri incelemek oldukça işimize yarayabilir.

41 80 06 09 08 00 00

İlk iki baytın değişken adını gösterdiğinden eminiz artık. Ama string türünü göstermek için $41 $00 değişkeni $41 $80 olarak yazılmış. Yani, sadece ikinci baytın son biti 1'se değişken bir string'dir. Sonraki üç baytı yorumlarsak, ilk baytın karakter dizisinin uzunluğu, diğer ikisinin de adresi olduğunu tahmin edebiliriz. Burada yazıldığına göre, A$ değişkeninin içeriği altı karakter uzunluğunda ve $0809 adresinde yer alıyor. Ne kadar ilginç değil mi? BASIC programının içindeki yeri gösteriyor A$. Bu sayede oldukça bir yer kazancı sağlayabiliriz. İyi de karakterlerden birini değiştirmeye kalkarsak ne olacak? BASIC kullanırken edindiğimiz deneyimlere göre bir string'in içeriğini değiştirmek, BASIC programının yapısını değiştirmez. Yani bilgisayarımızın böyle bir değişiklik karşısında nasıl davranacağını test etmeliyiz. Haydi bakalım programınıza şu satırı ekleyin:

20 A$-LEFTS(A$,3)

Programı çalıştırın ve emektar monitörünüzü kullanın.

«1 002B 01 08 22 08 29 08 29 08
«1 0033 FD 9F 00 A0 00 A0
00 11 08 CA 00 41 24 B2
«1 0808 22 53 54 52 49 4E 47 22 *
«1 0810 00 20 08 14 00 41 24 B2
0818 C8 28 41 24 2C 33 29 00
<1 0820 00 00 41 80 30 FD 9F 00
«1 0828 00
Değişkenler $0822'den başlıyor.
0822 41 80 30 FD 9F 00 00

Deminki söylediklerimi göz önüne aldığımızda değişkenin içeriğinin 3 karakter uzunluğunda olduğunu ve $9FFD adresinde yer aldığını rahatça görebiliriz. Demek ki değişkenin içeriğinde bir değişiklik yapmaya kalkarsak, BASIC program üzerinde işlem yapılmıyor ve $A000'dan geriye sayarak bu içerik için yer açıyor. $9FFD'ye baktığımızda A$'ın son hali olan “STR” harfleriyle karşılaşırız. Bu arada string yerinin göstericisi olan $33/$34'ün de $9FFD'ye kaydığına dikkatinizi çekerim. Demin bahsettiğim token haline getirme işinin neden yapıldığını anlamak için programın içindeki LEFT$'ı bulmaya çalışın. Bulamayanlar için yerini söyleyeyim: $0818. Ne güzel, değil mi? Beş karakterlik yer ayrılacağına tüm komut LEFT$ anlamına gelen tek bir bayta sığdırılmış ($C8). Hemen hemen tüm değişken türleri hakkında bilginiz oldu artık. Geriye sadece bu değişkenlerin gruplar halinde kullanılmasını sağlayan diziler (array) kaldı. Dizileri incelemek için, NEW komutunu verdikten sonra aşağıdaki programı girin ve RUN deyin,

10 DIM A(500)

Sıfırıncı sayfa değişkenleri şu şekilde düzenlenecektir:

«1 002B 01 08 10 08 10 08 E0 11
-:0033 00 A0 00 00 00 A0

Dizi (array) olmayan hiçbir değişken tanımlamadığımız için, değişkenlerin başlangıç ve bitiş adresleri aynı adresi, yani $0810'u gösteriyor. Bu adres aynı zamanda dizilerin de başlangıç adresi olarak kullanılıyor. Diziler için ayrılmış olan alan $11E0 adresine kadar sürdüğüne göre, A dizisi için: $11B0-$0810 = $09A0 = 2512 bayt ayrılmış. $0810 adresinden incelemeye başlarsak şu baytlarla karşılaşırız:

«10810 41 00 DO 09 01 01 F5 00
«10818 00 00 00 00 00 00 00 00
«1 0820 0000 00 00 00 00 00 00

İlk iki baytın değişken adı olduğunu tahmin etmeniz pek de güç olmamıştır artık. İki MSB'de (Most Significant Bit - En Yüksek Değerlikli Bit, yani 7. bit) 0 olduğuna göre değişkenimizin kesirli sayı tuttuğunu anlarız. Sonraki iki bayt, demin hesapladığımız dizi uzunluğunu Düşük-Yüksek değerlikli bayt formunda saklıyor. Daha sonraki baytı tahmin etmeniz hemen hemen imkansız. Ancak bir iki denemeden sonra bu sayının dizinin boyut sayısını tuttuğunu anlayabilirsiniz. Buradaki örnekte A dizisinin tek boyutlu olduğunu rahatça görebilirsiniz. Bu bayttan sonra gelen $01 $F5 = $01F5 = 501, dizi elemanlarının sayısını tutar. Dikkat ettiyseniz, bizim A'yı 500 elemanlı olarak tanımlamamıza rağmen, burada 501 eleman görünüyor. Bunun sebebi, A dizisinin (çoğu zaman unutulan) 0. elemanının da sayılmasıdır. DIM A(2) kullansaydınız, A(0), A(1) ve A(2) A dizisinin üç elemanını oluşturacaktı. Buraya kadar olan bölge, dizinin genel bilgisini içeriyordu. Bu bayttan sonraki baytlarda ise, sıfırıncı elemandan başlamak üzere, dizi elemanlarının değerleri yer alır. Eğer monitörden çıkıp, direkt modda (satır numarası vermeden) şunları yazarsanız bunu daha iyi gözlemleyebilirsiniz:

A(0)-10:A(I)- 11

Şimdi monitöre tekrar girin ve 0810 0820 arasına bir daha bakın:

41 00 DO 09 01 Ol F5 84
«1 0818 20 00 00 00 84 30 00 00
0820 00 00 00 00 00 00 00 00

Bu sayıların ondalık düzende yazılışları şunlardır:

$84 20 00 00 00 -
-

Bir de çok boyutlu dizileri inceleyelim. Bunun için ilk olarak NEW komutunu verin ve direkt modda şu satırı girin:

DIM B(1,2,3)

Monitöre girin ve ilk olarak sıfırıncı sayfa değişkenlerini, daha sonra da 0800 bölgesini tarayın:

«1 002B 01 08 03 08 03 08 86 08
«1 003300 A0 00 00 00 A0
«1 0803 42 00 83 00 03 00 04 00
. «4 080B 03 00 02 00 00 00 00 00
«1 0813 00 00 00 00 00 00 00 00

İlk bakışta B değişkeni hemen dikkatimizi çekiyor zaten. İsimden sonra gelen bayt, dizinin $0083 = 131 bayt uzunluğunda olduğunu söylüyor. Bundan sonra da dizi boyutlarının büyüklükleri saklanıyordu. Bu örnekte $0004, $0003 ve $0002 sayıları rahatlıkla görülebiliyor. Nedendir bilinmez, bu sayılar sizin verdiğinizin tersine sıralanmışlar. “Buraya kadar tamam da, bu dizinin elemanları nasıl sıralanmışlar?” diyenlerinizin cevabını da hemen vereyim:

30 00 00 00
B(0,0,2)
B(0,0,0)
B(1,0,0) B(1,0,2)
B(0,1,0) B(0,1,2)
Bi1,1,0)
B(0,2,0) B(0,2,2)
Bi1,2,2)
B(0,0,1) B(0,0,3)
B(1,0,3)
B(0,1,3)
Bi1,1,1) Bi1,1,3)
B(0,2,1) B(0,2,3)
Bi1,2,1) B(1,2,3)
Yukarıdaki listeden dizi elemanlarının na-
sıl sıralandığını kolayca çıkarabilirsiniz. Aşa-
ğıda DIM A(X,Y,2) ile açılan bir dizinin ele-
manlarının bellekte hangi sırayla saklandı-
ğını gösteren listeyi çıkaracak BASIC prog-
ramını görebilirsiniz.
10 FOR K-0 TO X
20 FOR L-0TO Y
30 FOR M-0 TOZ
40 PRINT K*,”L*,”M
50 NEXT M,L,K
Normal değişkenlerin aksine, dizilerde ele-

manın tam sayı veya string olmasına göre farklı sayıda kullanır. String dizilerinde de, normal stringlerde olduğu gibi, bir eleman girilene kadar bellekte yer ayrılmaz. Daha sonra $A000'dan aşağı inilir. Yukarıda anlattıklarımın ışığında bir dizinin BASIC alanınızda kaç bayt götüreceğini şu şekilde formüle edebiliriz.

Bellek 4 T*Çarpım(Eleman * 1)

Yukarıdaki formülde bulunan N, dizinin boyutunu, T'de dizinin tipini belli ediyor. Eğer diziniz tam sayı tutuyorsa 2, kesirli sayı tutuyorsa 5, string tutuyorsa 3 koymalısınız T yerine. Sonda bulunan Çarpım(Eleman + 1), tüm boyutların eleman sayılarına 1 ekleyerek, bu sayıları birbirleriyle çarpmanız gerektiğini söylüyor. En başta bulunan 5, iki baytlık isim, iki baytlık dizi uzunluğu ve bir baytlık dizi boyutu için gereken alanı hesaplanan değere ekliyor. Dizinin her boyutu için iki baytlık eleman sayısı tutulduğu için boyut sayısını 2 ile çarpıp toplam belleğe ekliyoruz. En iyisi demin verdiğimiz örnekler için gerekli bellek alanını bir de bu formülle hesaplayalım: 1. DIM A(500) N:1 T:5 - Bellek = 5 + 5 * (501) = 2510 bayt. Tam beklediğimiz gibi. 2. DIM B(1,2,3) N:3 T:5 - Bellek = 5 + 2*3 + 5 * (2*3*4) = 131 bayt. 3. DIM N:3, T:2 = 8 bayt. 4. DIM A$(100,100) N:2, T:3 = 5 + 2*2 + 3 * (101*101) = 30614 bayt. Bu kadar çok yer kapladığı için çoğu zaman bu büyüklükte bir dizi açamazsınız. Sadece dizi tablosu belleğin yaklaşık 30K'sını yiyor ve 10201 elemanın datalarının saklanması için (ve BASIC programını saklamak için) sadece 8K boş bellek kalıyor. Bu aylık bu kadar. Artık ROM'un BASIC'i nasıl yorumladığını, sayıları nasıl kullandığını oldukça iyi biliyorsunuz. Gelecek sayıya kadar anlamadığınız yerleri kapatmaya çalışın, çünkü bir iki tane örnek program yayınlamak istiyorum. Bu arada tüm çabalarınıza rağmen içinden çıkamadığınız yerler olursa bana yazmaktan çekinmeyin. Gelecek ay görüşmek üzere,