asic'in Gariplikleri
Az kullanılan komutların bazılarını kurcalayalım.
Birileri, şimdiye kadar hazırlanan bütün yazılımların yüzde 90'ının, hazırlandığı dilin sadece yüzde 10'undan yararlanılarak hazırlandığını iddia ediyor. Eminim ki bu rakam abartılmış, ancak doğruluk payı da var. Her dilin kendine özgü ve temelini oluşturan birkaç komutu vardır ve bunlar da program için önemlidirler. Mesela BASIC'te en çok kullanılan komutlar LET,
IF-THEN ve herhalde GOTO'dur. Bunlardan başka her dilin “az bilinen” komutları da vardır ve bu komutlar bir süre sonra unutulup giderler. Bu ay sizlere bu komutları yeniden hatırlatmaya çalışacağım. Eğer yakın zamanlarda Programcının El Kitabı'nı karıştırmadıysanız herhalde bu komutlar size yabancı gelecektir. Belki bu komutlar günlük programlama için gerekli değiller ancak dara düştüğünüzde size yardımcı olacaklardır. Eminim ki pek çoğunuz biz bu komutları zaten biliyoruz diyeceksiniz. Harika! Ne kadar çok komut bilirseniz o kadar iyi programlar yapabilirsiniz. Bu yazının da amacı sizin RAM'ınızı genişletmek. Eğer bu dili yeni öğreniyorsanız bu komutları bir yerlerde saklayın, ilerde ihtiyacınız olabilir.
Seyrek Ama Önemli
Komutlar listesine bakarken pek çok BASIC 2.0 (C-64) komutunun BASIC 7.0'da (C-128) olduğunu fark ettim. Bu gerçekten ilginç çünkü BASIC 2.0 gerçekten de “dokunsan yıkılacak” bir versiyon.
İşte POS fonksiyonundan başlayalım. POS size cursor'unuzun o anda ekranda bulunduğu kolonu verir. Eğer cursor ilk satırın 10. sütunundaysa POS(0) size C-64 ve C-128'de 9 değerini verir. Ama cursor'unuz bir sonraki ekranda aşağıdaki satırdaysa POS(0) C-128'de hâlâ 9 değerini verirken C-64'te 49 değerini verir. Peki neden farklı? Commodore 64 aslında mantıksal olarak 80 karakter alır. Ama bir satır 40 karakterden oluştuğu için bir mantıksal satır iki fiziksel satırı kapsar. Peki POS fonksiyonuna ne zaman ihtiyacınız olur? Eğer değişkenleri, grafik karakterlerini bir satıra yazmanız gerekiyorsa veya bir program bir mesaj yazmak için gerekli yer olup olmadığını da bu sayede algılayabilir. Mesela bir A$ değişkenini o satırda yeterli yer varsa o satıra, yoksa aşağıdaki satıra yazdıralım (40-kolon ekran).
201F LEN(A$) — 40-P THEN PRİNT
30 PRİNT A$
10. satır P değişkenine bundan sonra yazılacak mesajın ilk karakterinin kolonunu verir. Eğer P değişkeni 39'dan büyükse (yani bir alt satırdaysa) bu değişkenden 40 çıkarılarak normal hale gelmesi sağlanır. Bir sonraki satırda A$ değişkeninin uzunluğu kalan boşlukla karşılaştırır. Eğer A$ değişkeni o boşluktan daha uzunsa araya bir PRINT komutu girer ve cursor bu sayede bir sonraki satırın başına gider. A$ değişkeni boşluklara sığıyorsa doğrudan 30. satıra gidiliyor. 30. satırda ise A$ değişkeni cursor nerde ise oraya yazdırılıyor. POS fonksiyonunun parantezleri arasına ne yazdığınız aslında pek fark etmez. Yani POS bize cursor'un yatay pozisyonunu verir. Aslında cursor'un yatay pozisyonunu bilmek bize pek çok yarar sağlar. Hangi komut size cursor'un yatay pozisyonunu verir? Aslında böyle bir komut yok. Belleğin 214 (C-64'te) veya 235. (C-128'de) adreslerine bakmalısınız (PEEK ile). Bizim tanıdığımız BASIC çok eskiden beri kullanılıyordu. O zaman bilgisayarlar video monitörleri kullanmıyorlardı. Bu yüzden cursor sadece sağa sola doğru hareket ettirilebiliyordu. Cursor'u yukarı aşağı oynatmak mümkün değildi çünkü bilgiler bir kağıt üzerine dökülüyordu. Aslını söylemek gerekirse o zamanlar cursor bile yoktu. POS komutunun tek amacı printer kafasının yatay pozisyonunu öğrenmekti. Listemizde sıradaki komut programa cursor'un satırın neresinde olduğunu söylüyordu. SPC ise cursor'u aynı satırda belirtilen uzaklığa götürür. SPC komutu kolayca TAB komutu ile kullanılabilir. Aralarındaki farkı aşağıdaki programla daha rahat anlayabiliriz.
10 PRİNT A$; SPC(15);BS
20 PRİNT A$; TAB(15),B$
10. satır A$'ı ve B$'ı aralarında 15 karakter boşluk bırakarak yazar ve uzunluklarına dikkat etmez, 20. satır A$ değişkenini yazdıktan sonra B$'ı basmadan önce cursor'u 16. pozisyona götürür ve sonra B$’ı yazar (Neden 15 değil de 16? 16 çünkü en soldaki kolon 0 numarasını alır). Eğer A$ değişkeninin uzunluğu 15'ten büyükse B$ değişkeni onun üzerine basılır. Bu yüzden TAB komutunu kullanmak tehlikelidir. SPC ve TAB komutları o kadar kullanışlı değillerdir. Daha kullanışlı bir komut olan CHAR ise sadece BASIC 7.0'da mevcuttur. Bu komutta cursor'un gitmesini istediğiniz yerin hem yatay hem de dikey olarak koordinatlarını vermeniz yeterlidir.
BOŞ HAFIZA
FRE kullanışlı fakat gereksiz bir komuttur. Hiç programlarınızda boş kalan hafızayı öğrenme ihtiyacını duydunuz mu? Bu sık olarak karşınıza çıkan bir sorun olmamasına rağmen bazen ihtiyacınız olabilir. FRE(0) komutu size C-64'ünüzün ne kadar kullanılabilir RAM'ı olduğunu verir. İşin ilginç tarafı ise sonucun -32768 ile 32767 arasında olmasıdır. Eğer 40.000 bytes boş belleğiniz varsa, PRINT size -25536 gibi bir sonuç verecektir. Herhangi bir eksi sonuca 65536 eklemelisiniz.
PRİNT - 65536 * (ERE(0) 0)
Yukarıdaki komutla bilgisayarınızda ne kadar boş hafıza olduğunu hemen bulabilirsiniz. () ile birlikte yazacağınız sayının C-64'te bir önemi yoktur, ancak C-128'de 0 yazarsanız programlar için kalan hafızayı, 1 yazarsanız değişkenler için kalan hafızanın boyutunu öğrenebilirsiniz. FRE ile bir program ne kadar uzun dizeler yaratması gerektiğini kestirebilir. Her dizenin 5 bayt harcadığı biliniyorsa program doğrudan maximum dize sayısını hesaplayabilir.
10 D-FRE(1)/5-10
20 PRİNT D
30 DIM A(D)
40 PRİNT FRE(İ)
10 tane bayt eksilttik çünkü bunlar sizin belirlediğiniz dize ile ilgili bilgileri içereceklerdir. Eğer C-128'inizde bir “Out of Memory Error” ile karşılaşmak istiyorsanız 10. satırdaki 10'u 2 ile değiştirin. Dikkat bundan sonra bilgisayarınızı açıp kapatmanız gerekebilir. Aynı programı ufak bir değişiklikle C-64'ünüz için de uygun hale getirebilirsiniz.
10D-(FRE(1) - 65536 *
10'u küçültün ve sonucu görün, Bir süre sonra karşınıza “Out of Memory Error” çıkacaktır.
Tanjant
En son ATN fonksiyonunu ne zaman kullandınız? Peki ATN fonksiyonunun ne olduğunu bilmiyor musunuz? Biliyorsanız bilgisayarınızda neden ASN veya ACS olmadığını hiç düşündünüz mü? ATN fonksiyonu trigonometriyle ilgilidir. ATN ile ters tanjantı alabilirsiniz (ArcTangent). Mesela 45 derecelik bir açının tanjantı.
tan(45) = 1.0
BASIC genellikle derece cinsi açılarla değil “radyan” cinsi açılarla çalışır. Ama korkmanıza gerek yok radyan ve derece arasında basit bir bağlantı vardır.
1 derece = pi/180 radyan veya 1 radyan = 180/pi derece
Bu bağlantının sebebi ise tam bir dairenin 360 derece veya 2*pi radyan olmasıdır. Bunu başka bir şekilde de söyleyebiliriz.
1 derece > 0.01745 radyan veya 1 radyan = 57.30 derece
45 derecelik bir açının tanjantını şu şekilde bulabiliriz.
PRİNT
Şimdi bilgisayarınız size 1.0 sonucunu verecektir.
ATN fonksiyonu TAN fonksiyonunun tam tersidir. ATN(0.1) size (radyan cinsinden) 45 derece verecektir,
PRINT 57.30*ANT(1)
Yukarıdaki satırı yazarsanız bilgisayar parantez içindeki açının tanjantını derece cinsinden ekrana yazar. Peki de Sinüs ve Cosinüs'ün niye ters fonksiyonu yok. Bunun ana nedenleri şunlar: 1) Trigonometrik fonksiyonlarda bunlara fazla gerek yoktur 2) Eğer gerek olsa bile ATN ile diğerlerini hesaplayabilirsiniz. Şimdi size ters sinüs ve ters kosinüs'ün fonksiyonlarını veriyorum.
DEF FNACS(X)—ATN(SOR(1-X*X)/(x4 (1-
Diğer fonksiyonlardan farklı olarak bu fonksiyon size negatif ve değerleri doğru olarak verir. Herneyse ATN hakkında yeterince konuştuk,
Ekleme
En son ne zaman iki sequential dosyayı birleştirdiniz. Doğrusu bunu ben de hatırlayamıyorum. BASIC 7.0'da bunun için CONCAT diye hazır bir komut var ama C-64 kullanıcıları COPY komutuyla bir kombinasyon yazmak zorundalar. Aslında bu komutlar sadece sequential dosyalarla çalışabilir. C-64'ün komut kombinasyonu C-128'in CONCAT komutundan daha kullanışlıdır. İki komutun formatı şöyledir,
10 CONCAT
veya
20 “COP
BASIC 2.0 ile (BASIC 7.0'ın kapsamındaki) yeni dosya ismi diğer dosya isimlerinden farklı olabilir. 20. satırda maximum 4 tane dosyayı birleştirebiliyorsunuz. Birleştirilecek dosyalar virgüllerle ayrılmalıdırlar. BASIC 7.0'da daha az kullanılan bir komut ise APPEND'dir. Bu komut size arkasına daha fazla bilgi eklenebilecek bir sequential dosya açmanızı sağlar. BASIC 2.0 ise bu işi “A” seçenekli bir dosya açarak yapar (satır 20).
10
veya
20 OPEN
Artık PRINT #1 komutuyla SEQ dosyanıza bilgi ekleyebilirsiniz.
Input'u Kesmek
C-128 sahipleri INPUT'u kesememelerini hiç sevmezler. INPUT kesebilmek için ilk önce RUN/STOP'a sonra da HELP tuşuna veya nümerik klavyedeki ENTER tuşuna basmaları gerekir. Bu tuşlar INPUT ile bekletilirken araya CHR$(13) koyarlar, Bu sayede INPUT komutu kesilmiş olur.
C64 kullanıcılarının işi biraz daha zor, INPUT komutunda soru işareti ekranda belirdiğinde: 1) CONTROL tuşuna basılı tutun. 2) M tuşuna basın, 3) Hemen CONTROL ve M tuşlarını bırakın, 4) Bundan hemen sonra Run/Stop tuşuna basın. CONTROL-M tuşu INPUT'a CHR$(13) koymanın bir yoludur. Bu sayede INPUT kesilir. Aşağıdaki programla alıştırma yapabilirsiniz.
10 INPUT X
20 GOTO 10
Negatif Bir Bit
NOT inceleyeceğimiz bir sonraki komut. NOT mantıksal operasyonlar için kullanılır yani bit işlemlerinde, Mesela mantıksal değer atamanın standart yolu şudur.
10 FALSE-0
10 TRUE-NOT FALSE
Mantıksal değişkenler sadece iki değer alabilirler true(doğru) veya false(yanlış). Bu değişkenler program akışını değiştirmek için kullanılabilir. Diyelim ki programınızda bir altrutin var ve bu rutin herhangi bir zaman çağrılabilir. Ama siz bu rutinin çağıran yerden bağımsız olarak sadece bir kere işleme konulmasını istiyorsunuz.
30 FALSE
Alt rutininiz şu şekilde olabilir.
10 TF DUN- TRUE THEN RETURN
10**#*Rutininizi buraya köyün****
180 DUN- TRUE
190 RETURN
Programınız GOSUB 100 ile altrutini çağırıyor. 100. satır DUN mantıksal değişkenine bakarak bu rutinin daha önce çağrılıp çağrılmadığını kontrol ediyor. Eğer DUN FALSE ise rutin çalıştırılır ve DUN TRUE yapılır. Böylece bu rutin bir daha çağrıldığında 100. satırdaki kontrole takılacaktır. 100. satırı şöylece kısaltabilirsiniz:
100 İF DUN THEN RETURN
Sonuç değişmez. Eğer rutin ilk çağrıldığında bir bölümünün diğer çağrılışlarında ise başka bir bölümünün çalışması isteniyorsa 100. satır şu şekilde değiştirilebilir.
100 DUN THEN ...(sadece ilk se-
ferde)...:GOTO 180
NOT ayrıca sayısal değişkenlerde de kullanılabilir.
10 Az0
20B-NOTA
30 PRİNT B
sonuç olarak -1 alırsınız. NOT komutu gördüğü her 0 biti 1 yapar ve tam tersi. Eğer 0 ise 16 tane 0 bir var demektir. NOT ettiğinizde bu 16 bit şu hale gelir: 1111 1111 Bu da onluk düzende karşılık gelir. Buna “ikinin tamlayanı” sistemi denir. İkilik düzende 16 tane 1, 65535'e eşittir. Ancak bilgisayar normal ikilik düzeni kullanmaz, eski sayıların ifadesi için daha farklı bir yöntem izlenir. İkinin tamlayanı sistemi şöyle çalışır: 1. En soldaki hariç 15 biti al ve hepsini ters çevir (1'ler 0, 0'lar 1 yap). 2. Bu sonuca 1 ekle. 3. Sonuçtaki sayıya negatif de. En soldaki bite işaret biti diyebiliriz. İşaret bitinin 1 olması sayının negatif olduğunu ve işlemlerin yukarıdaki gibi işletilmesi gerektiğini gösterir. İşaret biti 0 ise sayı pozitiftir. Örneğin 1111 ... sayısını onluk düzene çevirelim. Yukarıdaki adımları takip edelim. Sayının her bitini ters çevirelim, elde edeceğimiz sayı 000 0000 0000 0000, Toplam 15 basamak aldığımıza dikkat edin.
2. Bu sayıya 1 eklenince elimizde 000 0000 0000 0001 sayısı olur. 3. Böylece 1111 1111 1111 1111 sayısının ikinin tamlayanı gösterimde onluk olarak “eksi bir” sayısına denk geldiğini görürüz. Sonuç olarak NOT 0'ın da nasıl ettiğini görüyoruz. 0000 sayısının onluk düzende kaç olduğunu hesaplamaya çalışın. En soldaki 1 sayısı onluk olarak bu sayının negatif olduğunu gösterecektir. Daha sonra anlatılan adımlar izlenerek -16 sayısı bulunur (16 sayısının bitlerini ters çevirip sonuca 1 eklemek 16 sayısını verir). Eğer sisteme PRINT NOT -16 komutunu verirseniz cevap olarak 15 sayısını alırsınız.
Ama Ne Bit açıklaması bize WAIT komutu için iyi bir ortam hazırladı. WAIT komutu genellikle normal programcılıkta sanılır ama bu doğru değildir. Her neyse, ilk önce bu komutun ne yaptığına bir bakalım. WAIT'in formatı şöyledir: WAIT HAF,A,X. Bilgisayar bellekte HAF (hafıza) adresindeki değeri A ve X değerleriyle karşılaştırır. Şimdi ise basit bir örnekle başlayalım. WAIT 211,1 yazın. C-128'de SHIFT tuşları ayrı ayrı bitlerde saklanırlar (C-64'teki hafıza adresi ise 653'tür. Yani yazacağınız şey 653,1'dir). Aşağıdaki program siz SHIFT tuşlarına basana kadar bekleyecektir.
05 HAF-211:1F FRE(0) THEN
HAF-653
10 WAİT HAF,I
20 PRİNT “Şimdi 20,
5. satır hangi bilgisayar kullanılıyorsa ona göre hafıza adresini ayarlar (FRE komutundan hatırlıyorsanız. FRE(0) ile FRE(1) arasında bir fark vardı. Oysa C-64'te bu bir şey değiştirmiyordu. İşte 5. satırda FRE(0) ile FRE(1) ayrı değere sahipse hafıza adresi C-64'e göre ayarlanıyor. FRE(0) ile FRE(1)'in değeri farklıysa HAF değişkeninin değeri de değişmiyor). Şimdi size bazı tuşların onluk ve ikilik düzenlerdeki değerlerini veriyoruz.
Onluk — İkilik düzen — Her iki SHIFT tuşu 1 00001 COMMODORE tuşu 2 00010 CONTROL tuşu 4 00100 ALT tuşu 8 01000 CAPS LOCK 16 10000
Son iki tuş sadece C-128'de vardır. HAF adresinde 00000 değeri varsa bu tuşlardan hiçbirine basılmamıştır demektir. Eğer değer olursa tuşların hepsine birden basılıyor demektir. WAIT komutu AND ile kullanıldığında hangi HAF bitlerinin işlemi bilgilendirdiğini belirtir. Eğer SHIFT ve CONTROL tuşlarına basılıp basılmadığını kontrol etmek istiyorsanız WAIT HAF,5 yazmanız gerekir. Onluk düzendeki 5 sayısı ikilik düzende 1 ve 4. bitleri kapsar. Yani onluk düzende 1 ve 4. Bunlara 2, 4 veya 5. bitler dahil değildirler. Sadece SHIFT ve COMMODORE tuşları algılanır. İkisinden birine veya ikisine birden basılırsa program akışına devam eder. WAIT HAF,A,X komutu, diğerlerinden biraz daha karışıktır. Mesela WAIT HAF,5,1 yazdığınızda bilgisayar SHIFT tuşu bırakılıncaya veya CONTROL tuşuna basılıncaya kadar bekleyecektir. Şimdi 10. satırı şekildeki gibi değiştirin:
TO MEM,5,1
Şimdi RUN yazın ve hemen SHIFT tuşuna basın. Program siz SHIFT tuşunu bırakana veya CONTROL tuşuna basana kadar bekleyecektir. (FOR-NEXT döngüsü siz SHIFT'e basana kadar geçecek olan zaman için konmuştur). Programınız başka tuşların basılmasını da bekleyebilir, Daha önce verdiğimiz tabloya bakarak 10. satırı değiştirin. Sprite veya grafik için olan bazı özel komutları listeye katmadım çünkü bazıları gerçekten de çok seyrek olarak kullanılıyorlar. Eğer size hâlâ garip gelen bazı komutlar varsa bana bunlardan bahsetmeyin. Onları kendi hallerine bırakın...
ketmeyenler. Bu ay da bir Commodore dergisi alıp tamamen özel bilgisayarımıza ayrılmış olduğunu görmek ne büyük zevk, değil mi? Atölyemizde iki ayrı program gösterdik şimdiye kadar, Ne yazık ki ayrı ayrı kullanılmaları gerekiyor. Ama acele etmeyin, onları birleştirmeyi de öğreneceğiz. Geçen ay bir joystick kontrollü ok programı yapmıştık hatırlarsanız. Bu okun nasıl olup da BASIC programlarını etkilemeden ekranda dolaştığını detaylı olarak anlatmıştım geçen ay. Bu ay da bu ok programının bir uygulamasını vermeye söz vermiştim. Ne yalan söyleyeyim, kullanmaya kullanmaya BASIC'in ne kadar problem çıkardığını unutmuşum. Basit bir hesap makinesi (evet, bu ayın kö-
Ss elam Commodore 64'ünü hâlâ terleten dört işlemi yapabilecek bir hesap makinesi) yapmak için bile tam iki günümü harcamam gerekti. Eminim programda hâlâ hatalar bulunuyor. Bu yüzden sizden istediğim programı iyice incelemeniz ve hataları bulmanız. İsterseniz programı geliştirebilirsiniz de. Eğer programı bana diskette (veya kasette) gönderirseniz, disketinizin (veya kasedinizin) sağ salim size ulaşacağını garanti ederim (pul da gönderirseniz çok makbule geçer...). İsterseniz programdaki hataları ayıklamak yerine baştan bir hesap makinesi de yazabilirsiniz, En çok hatayı bulanların ve en iyi hesap makinesini yollayanların burada teşhir edileceğini(!) de eklemeliyim. Kim bilir, birer paket cips bile kazanabilirler... Hesap makinesine girişmeden önce ok programımızı çalıştırdıktan sonra hangi adreslerde ne gibi bilgiler bulabileceğinizi söylemeliyim sanırım: 49579: Ateşe basıldığında 0'dan farklı bir değer alır. Eğer tuş, vb. yaptıysanız ve sık sık oku kontrol etme imkanınız varsa bu adresin değerine bakarak ateş tuşuna basıldığı anı yakalayabilirsiniz, 49580-49581: Bu iki adreste, ekranda dolaşan okun tam olarak hangi X koordinatında (nokta olarak) bulunduğunu öğrenebilirsiniz. Bu X koordinatı 0 ile 319 arasında bir değer alır. Şu formülle X koordinatı hesaplayabilirsiniz: PEEK(49581)*256 + PEEK(49580) 49582: Bu adreste de okun Y koordinatını görürsünüz. 0 ile 199 arası bir değer alır. 49583: Okun ekranda hangi X karesinde bulunduğunu öğrenebilirsiniz. BASIC programlar genelde karakter ekranında çalıştığı için bu adres deminki X koordinatından daha sık kullanılır sanırım. 0 ile 39 arasında bir değer alabilir. 49584: Okun hangi Y karesinde bulunduğunu bu adresten öğrenebilirsiniz. 0 ile 24 arası bir değer alabilir. 49585-49586: Son ateş tuşuna basıldığında okun hangi X koordinatında bulunduğunu tutan adreslerdir. 0 ile 319 arası değer alırlar, Şu formülle tuttukları değeri bulabilir-
si PEEK(49586)*256 + PEEK(49585) 49587: Ateşe son basıldığında okun bulunduğu Y koordinatını tutar. 0 ile 199 arası değerler alabilir. 49588: Ateşe son basıldığı anda okun bulunduğu X karesini tutar. 0 ile 39 arası değerler alabilir. 49589: Ateş tuşuna son basıldığında okun bulunduğu Y karesini aklında tutar. 0 ile 24 arası değerler alabilir. İsterseniz bunları bir de tablo haline getirelim:
EXE BASİC Kullarıtabikeri
Oh! Programın bu kadar çok bilgi verdiğini bilmiyordum doğrusu. Bazılarınız karakter pozisyonunu da benim vermemin saçma olduğunu, bu pozisyonun kolayca X koordinatını 8'e bölerek hesaplanabileceğini söyleyecektir eminim. Ama, her şeyi hazır bulmak daha kolay değil mi? Neyse, gelelim hesap makinemize... İlk olarak bir hesap makinesinin çalışma prensibini oluşturmalıyız. Eminim bu konuda daha önce hiç kafa patlatmamışsınızdır. Ama kalemi elinize alıp kağıdın başına geçtiğinizde, bir hesap makinesi yaratmanın hayatta yapılabilecek en kolay iş olmadığını farkediyorsunuz. Hesap makineleri sonsuz miktarda toplama yapabildiğine göre (şu işlemi yapabilme ve bir işlem yapmak için en az iki argüman gerektiğine göre) bizden iki değer (argüman) alması gerek. Bu değerlerin alınmasının bittiğini bir işlem veya eşittir belirtir. Şimdi nasıl bir algoritma kurarak sonsuz işlemi iki adet sayı alarak gerçekleştirebileceğimizi düşünelim. Benim aklıma şöyle bir yöntem geldi: İlk olarak A sayısı alınır, daha sonra B sayısı alınır. A'ya A (işlemA) B değeri atanır. (Buradaki işlem A, A sayısının alınmasının bittiğini gösteren işlemdir. Birazdan gelecek işlemB de B sayısının alınmasının bittiğini gösteren işlem olacaktır haliyle.) Eğer işlemB “=” değilse işlemA'yı işlem B'ye eşitleriz. A zaten son işlemin sonucunu tutuyor olur. Böylece sadece yeni bir B sayısı (ve işlemi) alarak yeni bir işlem yapabiliriz. Ta ki bir “=” ile işlemler dizisi son bulana kadar... Eğer işlemB olarak eşittir girildiyse sonuç ekrana yazılır ve yeniden A sayısı (ve işlemi) alınmaya dönülür. Tabii ki burada karşılaşılacak problemleri (ve çözümlerini) programın açıklamasını yaparken yazmayı düşünüyorum. Genel olarak A ve B sayılarını almak için aynı kuralları kullanacağımıza göre, tek bir alt-program yazarak her iki sayının da alınmasını sağlayabiliriz. Bu alt rutini çağırırken seçeneğimiz bir değişkene 1 verirsek A sayısı, 2 verirsek B sayısı alınır. Bu değişkende bulunan değer sayesinde alt programımız da A'nın mı B'nin mi olduğunu farkedebilir. Bu sayede “-” gibi işlemlerde alınmakta olan argümana göre farklı işler yapabilir. Bir de her hesap makinesinde bulunan AC ve CE tuşları ve programımıza eklememiz gereken, Öncelikle bu tuşların tam olarak ne yaptıklarını öğrenmeliyiz: AC'ye basıldığında nerede olursak olalım, tüm değişkenler ve işlemler sıfırlanır, A sayısının alınmasına dönülür. CE'ye basıldığında ise yalnızca alınmakta olan sayı sıfırlanır, bir önceki sayı ve işleme dokunulmaz. Tabii ki hesap makinesi programı her zaman çalışacağı için programı sonsuz döngüye sokmalıyız,
Şekil-i: mükimsı programının akiş Şeması,
İşte şimdiye kadar çıkarttığımız algoritmanın akış şeması:
Programı tasarlarken sadece klavyeden sayı aldırma rutinlerini yazmak, program çalışır hale geldikten sonra okla sayı alma rutinlerini eklemek daha akılcı. Bu sayede ilk olarak ana programdaki hataları ayıklayabiliriz. Program tamamen çalışabilir hale gelince de ok yardımıyla sayı okuma programını yazarız. Böylece tek seferde daha az hata kaynağı olabilecek programla uğraşırız. Artık yazdığımız programı inceleme vakti geldi sanırım. Bu yüzden en iyisi döküm ekini açın ve programı oradan takip edin. Programın ilk satırında MOUSE.EXE programını yüklüyoruz. Biliyorsunuz BASIC program içinde bir program çalıştırınca iki satıra sıçranır. Bu yüzden A değişkeniyle sonsuz yükleme çevrimine girmekten kurtuluyoruz. 110. satıra kadar olan bölgede ekranı çiziyoruz, oku çalıştırıyoruz ve gerekli değişkenleri ayarlıyoruz. Programın ana değişkenleri AR$, yani argümanlar, IS$, yani işlemler ve EK, yani eksi. Sayılarla olan problemi yüzünden argümanları sayı yerine karakter olarak tutup, zamanı gelince VAL(AR$(X)) ile değerini hesaplattırmayı uygun bulduk. Eksi işareti hesap makinesinin en soluna yazılacağı için, bir de eksi değişkeni tutup, bu değişkenin durumuna göre eksi işareti koymak da kolayımıza geldi. Gelelim 110. satıra: Aslında GOTO yerine GOSUB kullanıp RETURN'le geri dönseydik daha temiz bir çalışma olurdu, ama AC tuşunun her şeyi sıfırlayıp en başa dönmesi çok zor oluyordu ve program çok karışık görünüyordu. Bu sebeple ile alt programa sıçrıyoruz ve geri döneceğimiz zaman da X'in değerine göre 120. ya da 130. satıra sıçrıyoruz (RETURN'ün yapması gereken işlemi takip ediyoruz açıkçası), X değişkeni 1000. satıra sıçrarsak A sayısı ve IS$(1) alınır. X'e 2 verdiğimizdeyse B sayısı alınır.
120. satırda B sayısını aldıktan sonra 2000. satırdaki alt programa sıçrayıp yapılan işlemin sonucunu A'ya alıyoruz. 9000. satırda işlemin sonucunu ekrana yazıyoruz. Tüm bu işler bitince B sayısının işleminin ne olduğunu kontrol ediyoruz. Eğer “=” ise tekrar A sayısını alma rutinine sıçrıyoruz (110. satır). Değilse işlemA'yı işlem B'ye eşitliyoruz ve yeni bir B sayısı almak için 120. satıra gidiyoruz. 999. satırdaki END hiçbir zaman kullanılmıyor, ama alt programcıklardan hemen önce bir END koymak, programı geliştirme aşamasında iyi bir yardımcı olur. Bu sayede programın işlemesi bitince bir alt programlar işlemeye başlamaz. Artık alt programları inceleme vaktidir, İlk olarak en karışık olanından, yani sayı alma alt programından başlayalım: Bu alt program, kaç tane sayı girildiğini anlamak için RAKAM (bilgisayar için RA) adlı bir değişken kullanıyoruz. En başta bu sayıyı ve argümanı sınırlıyoruz ve bir tuş veya ok girdisi bekliyoruz. Bunu yapmak için ilk olarak klavyeden bir girdi var mı diye bakıyoruz (GET Z$) daha sonra ateşe basılmadıysa Z$'ın değeriyle oynamayan bir alt programa (ok okuma) gidiyoruz. Eğer Z$ boşsa bu işlemleri tekrarlıyoruz. 1030. satırda sadece 9 rakam alınmasını sağlıyoruz. Yani 9. rakamdan sonra nokta ya da sayı giremiyorsunuz. Yalnızca: 1050: AC KONTROLÜ. 1060: İŞLEM. 1070: EŞİTTİR. 1080: SAYININ NEGATİFİ. 1090: CE KONTROLÜ. Yapılıyor. 1100. satırda bir rakam girilmesi durumunda yapılacak işler duruyor. Eğer henüz sayı girilmediyse ve sıfıra basıldıysa bu sıfırı dikkate almıyoruz. Her ihtimale karşı, henüz rakam girilmediyse AR$(X)'i bir daha sıfırlıyoruz (negatifini alma rutinine gelince neden bunu eklediğimizi anlayacaksınız). Daha sonra RAKAM'ı bir artırıp, girilen rakamı argümanımıza ekliyoruz. Son olarak da ekrana yazma rutini olan 1900'e atlıyoruz, 1200. satırda AC durumunda ne yapılacağını görebilirsiniz; İlk olarak 9800'e sıçranıp tüm değişkenler sıfırlanıyor ve X'e 1 veriliyor, daha sonra da 1900'e gidilerek son durum ekrana yansıtılıyor. 1300. satırda bir işlem girildiğinde yapılacak işleri bulabilirsiniz: Eğer AR$'a daha sayı girilmediyse AR$(X)'e EKRAN$ (bilgisayar için EK$)'da bulunan değeri, yani ekrandaki değeri atıyoruz. Bu sayede sonra sonuca bir sayı daha ekleme şansınız olur, Yani “2 + 2” sonucu olan 4'ü gördükten sonra yeniden “+ 2” yazarsanız 2 değil 6 sonucunu alırsınız. Daha sonra IS$(X)'i girilen işleme eşitleyip, X'in değerine göre 120. ya da 130. satıra gidilir (sayı alınmıştır artır...). 1400. satır eşittir girilmesi durumunda neler yapılacağını gösterir. Eğer X = 1 ise, yani A alınıyorsa eşittir yalnızca sayıyı ekranda gösterir ve yeni sayı alınması için başa döner. Eğer X'e 2 varsa, eşittir bir işlem gibi davranmalıdır. Yani IS$(2) = “=” olur ve 130. satıra uçulur.
1500. satırda en çok problemi yaratan program var: negatifini alma. İlk olarak, RAKAM = 0 ise, yani sayı girilmediyse ekrandaki sayıyı alıyoruz. Eğer bu sayı da sıfırsa beklemeye dönüyoruz. Değilse EK(X)'i eksi EK(X) yapıyoruz. Sayı almanın başındaki sıralama bu rutinin başındaki EKRAN$'ın alınmasından dolayı ortaya çıkıyor. Eğer bu sıralamayı yapmazsak sonradan basılan sayılar bu sayıya eklenmeye başlıyor. Son olarak, 1600. satırda da sadece şu anda alınmakta olan değerlerin hepsi sıfırlanıp ekrana yazılıyor. 1900. satırdaysa ekran (tabii ki hesap makinesinin ekranı) temizleniyor, ekrana yazılıyor, EKRAN$'a da bu değer atanıyor. EK(X)'e göre eksi işareti de basıldıktan sonra tuş beklemeye geri dönülüyor. Programın en zor kısmını bitirmiş olduk böylece, Artık diğer kısımlarla devam ederiz. İkinci alt programımız 2000. satırda başlıyor. Burada ilk olarak A1'e AR$(1)'in, A2'ye de AR$(2)'nin eksi veya artılısı yerleştiriliyor. Daha sonra IS$(1)'in değerine göre +, -, * veya / işlemlerinden biri yapılıyor. Bölme işlemini yapmadan önce A2'nin değerine bakıyoruz. Eğer bu değer 0 ise 9030'a gidip ekrana “OE” yazdırıyoruz ve AC anlamındaki “A”'ya basılmasını bekliyoruz. A'ya basılınca da her şeyi sıfırlayıp başa dönüyoruz. Eğer her şey yolundaysa sonucun mutlak değerini (ABS(A1)) diziye çevirip (STR$(sayı)) AR$(1)'e koyuyoruz.
EK(1)'i hesaplamak ise daha kolay. A1'in işaretini (SGN(A1)) Yalnız SGN(0) fonksiyonu 0 sayısını verdiği için sonuç sıfırsa EK(1)'e 1 vermeliyiz. AR$(2)'yi de gereksiz yere sıraladıktan sonra geri dönüyoruz.
3000. satırdan başlayan üçüncü alt program dergimizde yayınlanmış olan EKRAN Yapıcı programın bir çıktısı ve sadece ekrana bir hesap makinesi çizmekle yükümlü, Bu arada belirtmeden geçmeyeyim, ekran düzeni tamamen EMRE'ye ait (sanırım memnun ol artık).
7000. satırda bulunan kısacık rutin ise bu programı yazmamızın asıl sebebi olan ok kullanarak ekrandan bir şeyler okutma programı. Buraya ilk sıçranıldığında hemen ateş tuşu kontrolü yapılıyor. Eğer ateşe basılmıyorsa zaten yapılacak bir şey olmadığından hemen geri dönüyoruz. Ateşe basılıysa da, bu sefer ateş tuşu bırakılana kadar bekliyoruz (7020. satır). Bunun sebebi, ateşe basıldığında bir tuşu iki kere okumayı engellemek. Bu gibi ufak rutinler programları daha kolay kullanılır hale getirirler. Daha sonra ekrandaki tuş matrisine göre, ok hangi satırdayken ateşe basıldığını kontrol ediyoruz. Eğer 5, 7, 9 veya 11. satırdaysa “Tuşlardan biri olabilir.” diyerek satır alt rutinlerine sıçrıyoruz. Satır tutmuyorsa Z$'a dokunmadan geri dönüyoruz. Eğer 5. satırda ateşe basıldıysa kolonlara bakıyoruz (7100'deki alt program): 14. kolonsa Z$'a bir “7” 16. ise “8” 18. ise “9” koyuyoruz. İki karelik tuşları kontrol etmek için OR işlemiyle: “20. VEYA 21. kolonlarsa Z$'ı “C” yap.” diyoruz. Aynı şekilde AC'yi VEYA 24. kolonlardaysa Z$'a “A” yaz.” şeklinde ayarlıyoruz (7130. ve 7140. satırlar). Eğer bu kolonlardan hiçbiri değilse Z$'a dokunmadan geri dönüyoruz. Ok 7. satırdaysa hemen 7200'e sıçrıyoruz ve kolona göre değerler veriyoruz:
KOLON Z$ 14 7 16 8 18 9 20 * 2 44
Bunların dışında bir kolondaysak, ciddiye almıyoruz. 9. satırdaysa da aynı şekilde 7300'e gidip ilk üç kolon değerine göre Z$'a “4”, “7”, “2” veya “3” veriyoruz. “4” tuşumuz beş karelik olduğuna göre burada OR kullanarak beş değeri birden kontrol etmek saçma olur. Bu yüzden AND kullanarak
“kolon büyük-eşit 20 ise VE küçük-eşit 25 ise Z$'a “4” ver.” dememiz daha yerinde olur. 11. satırsa sıçradığımız 7400. satırda ise değişik bir şey yok. Sadece Z$'a “0”, “N” veya “-” veriliyor. Burada dikkat etmeniz gereken şey, okun şu anda olduğu pozisyonu değil de son ateşe basıldığı koordinatı kontrol etmek olmalı. Okun şu anda bulunduğu koordinatlar yalnızca çizim programı gibi garip şeyler yapıyorsanız işinize yarayacaktır. Okla ekrandan bilgi almak için kullanılacak genel yaklaşım buradaki gibi olmalıdır. Ekranı satırlara ya da kolonlara bölün (Eğer satırlar düzenliyse satırları, kolonlar düzenliyse kolonları kontrol edin ilk olarak). Daha sonra her satır (ya da kolon) için belirlediğiniz yere sıçrayarak kolon (ya da satır) kontrolünü yapın. Programda geriye kalan yerlerde pek de ahım şahım şeyler yok. Daha çok hammallık kısımları bu satırlara atılmış. Mesela 9000. satırda EKRAN$ ekrana yazılacak değeri alıyor. Eğer ekrana yazılacak olan değer ekrandan büyükse hiç düşünmeden 9030. satıra atlayarak yapıştırıyoruz, ekranı temizleyip sayıyı buraya yazıyoruz ve geri dönüyoruz. 9800. satırdaki alt program tüm argümanları, işaretleri ve RAKAM'ı sıfırlıyor. Daha sonra X'e de 1 verip geri dönüyor. Yani bu işte, 9900. satırdaki program ise kursoru 3. satır 14. kolona alıyor ve geri dönüyor. Bu sayede hesap makinesinin ekranına yazmak için GOSUB 9900 deyip, sonra PRINT kullanmanız yeterli. Evet, bu aylık açıklayacağım program bu kadar. Yapılabilecek en iyi hesap makinesi programı olmadığının farkındayım, ama programın asıl amacı okun kullanımını açıklamak olduğuna göre bu kadarla idare edin. Yazının başında da söylediğim gibi her türlü programınızı bekliyorum. “Disketim ya da kasedim diye de üzülmeyin, posta pulunu yolladığınız zaman içinde başka bir şeyler bulunarak (vaktim olduğu zaman) size döneceğinden emin olabilirsiniz. Bu aylık da bu kadar. Atölye'de incelenmesini istediğiniz konular olursa bana iletmekten çekinmeyin. İlk fırsatta özel konulara değinmek benim de hoşuma gidecektir. Gelecek aya kadar hepiniz hoşçakalın.