BASIC ÖĞRENİYORUM (DERS 1)
Herkese merhaba, bu sayımızdan itibaren eski dostumuz C64 ile konuşabileceğimiz bir dil olan BASIC derslerine başlayacağız. (1 dil bir insan, 2 dil insan) bu gıcık espriyi yaptıktan sonra dersimize geçelim. Öncelikle bilinmesi gereken bilgisayarın temel yapısı; bu yapıyı çözdükten sonra BASIC öğrenmek çok kolaylaşacaktır, zira programcı olmanın temeli budur. Bilgisayarın 5 ana ünitesini inceleyelim: 1) Giriş ünitesi (INPUT), 2) Çıkış ünitesi (OUTPUT), 3) Bellek Ünitesi (MEMORY), 4) Aritmetik Mantık Ünitesi (ARITHMETIC LOGIC UNIT A.L.U), 5) Yönetim Ünitesi (CENTRAL PROCESSING UNIT C.P.U)
Bilgisayar elektronik bir makinedir diyoruz. O halde nasıl oluyor da bir dizi aritmetik işlem, alfabetik bilgi akımı mümkün oluyor? Temelde iki çeşit elektrik sinyalinden bahsetmekteyiz. Bunlar düşük voltajlı sinyal ve yüksek voltajlı (genelde 5 volt) sinyalleridir. Elektrik dilinde iki nokta arasında potansiyel enerji farkı varsa voltaj farkı da vardır. Bu prensibe dayanarak “bit”ler dediğimiz 0 ve 1’leri oluşturmak mümkündür. Eğer voltaj farkı sıfır volt ise 0 “bit”ini, voltaj farkı 5 volt ise 1 “bit”ini oluşturmuş oluruz. ”Bit”lerin 8 tanesi bir arada olursa 1 “byte” denir. Bütün harfleri bir dizi 0 ve 1’leri bir araya getirerek yani kodlama sistemini kullanarak oluşturmak mümkündür.
PROGRAMLAMAYA GİRİŞ
Bilgisayarı programlanabilen bir makine olarak düşünmek gerekir. Yapılan işler hız-
lı ve hacim itibariyle kabarıkta olsa, programı basamak,basamak alırsanız her işlemin
çok basit olduğunu görürsünüz. İlk programı küçük bir hesap makinesi ile de rahatça yapı-
labilecek bir işlem üzerinde kuralım. Bilgisayara iki tane rakam verelim ve bu rakamları
toplayarak neticesini ekrana yazmasını isteyelim.
10 INPUT A
20 INPUT B
30 LET TP=A+B
40 PRINT TP
50 END
Yukarıdaki programa bakınca ilk dikkat edilen özellik, programın satırlardan oluşması ve her satırın da bir numara ile başlamasıdır: örneğin 10, 20... gibi. Bu numaralara satır numaraları (Statement Number) denir. Satır numaraları küçükten büyüğe doğru artar. Bu düzenlemeyi bilgisayarın kendisi yapmaktadır. Satır numaraları 1 ile 63999 arasında tam sayı ve pozitif olan sayılardır. Programın akışına göre düzenlenmelidirler. Yani A ve B’nin değerini vermeden, toplamı oluşturan TP değerini hesaplamak mümkün olamayacağından, programdaki 30 no’lu satıra 10 numarası vermekle çalışabilen bir program yapmak mümkün değildir. Dikkat edilecek bir diğer özellikte satır numaralarının onar onar artmış olmasıdır. Bu numaralar birer birer arttırılabilirdi ve program da pekâlâ çalışırdı. Bu değerin onar onar arttırılmasındaki amaç, eğer ileride araya başka satırlar ilave etmek gerekirse programın genel akışını bozmadan bunu gerçekleştirmek içindir. Aksi halde ilave edilen satırdan sonraki satırların numaralarını tekrar düzenlemek gerekecektir. Demek ki programın genelinde bir değişiklik yapmadan 10 no’lu satırla 20 no’lu satır arasına 11, 12, 13, 14, 15, 16, 17, 18, 19 nolu satırları ilave etmek mümkündür.
INPUT, LET, PRINT komutları
10 numaralı satırı biraz daha detaylı inceleyelim. INPUT A: input komutu ile A basit değişkeninden oluşmaktadır. INPUT komutu (girdi) anlamına gelmektedir. Bilgisayar dilinde INPUT kendisinden sonra gelen değişkenin, bu durumda A’nın sayısal değerini klavye yolu ile vermek için kullanılır. Programın tamamını bilgisayarın hafızasına girdikten sonra programı çalıştırmak için RUN komutunu yazıp RETURN tuşuna basmak gerekir. Bu durumda bilgisayar ilk olarak 10 INPUT A satırını
C64 TÜRKİYE #8 3 okuyacaktır. Satırda INPUT komutu olduğundan bizden A değişkenini isteyecektir. Bunu belirtmek için de ekrana bir soru işareti yazar. A değişkeninin değeri 5 olsun, şimdi 5 yazıp RETURN tuşuna basın. Bu işlemi yaparken yazılan 5 rakamını ekranda görmek mümkündür. İleride göreceğimiz gibi bilgisayar A değişkeni için hafızasında ayırdığı yere 5 rakamını yerleştirecektir.
Bilgisayar daha sonra ikinci satır olan 20 INPUT B satırına geçecektir. Burada ki durum da ilk satıra benzediği için ekranda soru işareti görülecektir. Bu demektir ki bilgisayar B değişkeninin değerini istemektedir. B değişkeninin değeri 3 olsun, 3 yazıp RETURN tuşuna basarak bu işlemi de tamamlayalım. Bilgisayar bir sonraki satırda bilgileri değerlendirmeye başlayacaktır. 30 LET TP = A + B satırında LET komutu kendinden sonraki verilen ifadenin geçerli olmasını mümkün kılan bir deyimdir. Burada TP denilen bir değişken daha vardır. Hemen belirteyim, değişkenlerin bir harf ile olması şartı yoktur. A, B değişkenler olduğu gibi TP de bir değişkendir. TP = A + B ifadesi ile bilgisayara deniliyor ki A değişkeninin değeri ne ise onu al, B değişkeninin değeri ne ise onu da al, topla ve bu toplamı TP değişkeni ile ifade edilen hafızaya yerleştir. Bu da LET komutu kullanılarak yapılır. Bazı bilgisayarlarda LET komutunu kullanmaya gerek yoktur. O zaman bu satır 30 TP = A + B şeklindedir. O halde 30 numaralı satırdan sonra bilgisayar TP adında bir değişken oluşturdu. Bu değişkene ait olan hafızada A ve B’nin sayısal toplamı olan 8 vardır. 40 PRINT TP satırındaki PRINT komutu kendisinden sonra gelen değişkenin sayısal değerini ekrana yazmak için kullanılır. Bilgisayar ekrana bağlı değil de printer’a bağlı ise TP değişkeninin sayısal değeri bu defa kağıt üzerine yazılacaktır. Ekran kullandığımıza göre ekrana 8 rakamı yansıyacaktır. Demek ki 50 END satırındaki END komutu programın sonu geldiğini gösterir. Her programın sonunda END komutunu kullanmak gerekir.
PROGRAMIN ÇALIŞTIRILMASI Her satırı yazıp hafızaya yerleştirdikten sonra programı çalıştırmak için RUN komutunu yazmak gerekir. Şimdi RUN yazın, ekranda çıkacak işlem aşağıdaki gibi olacaktır. ? 5 ? 3 8 5 ile 3’ün toplamı 8’dir. Bilgisayar daha sonra hazır anlamına gelen READY mesajını yazarak kontrolü kullanıcıya bırakır.
LIST, Satır Numaraları ve Program Akışı Daha önce de belirttiğim gibi satır numaraları küçükten büyüğe doğru artar. Bu artış onar onar olabileceği gibi birer birer de olabilir. Satır numaraları programın akışına göre düzenlenmelidirler. Numaralama yanlış yapıldığında aşağıdaki örnekte olduğu gibi yanlış netice alınacaktır.
Bilgisayar bu satırları hafızasına aldıktan sonra satır numaralarına göre sıraya koymaktadır. Hafızada ne olduğunu görmek için yani programı listelemek için LIST deyimi kullanılır. Şimdi LIST yazıp RETURN tuşuna basalım: 10 INPUT A 15 LET TP=A+B 30 INPUT B 40 PRINT TP 50 END Bu programa RUN demek mümkün olmayacaktır. Sebebi ise bilgisayar 15 no’lu satıra geldiği zaman B değişkeninin değerini bilmediği için toplama işlemini yapamayacaktır. (HADES’in notu: C64’te eğer sayısal bir değişkene herhangi bir değer verilmeden o değişkenle işlem yapılması durumunda değişkenin değeri sıfır kabul edilerek işlem yapılır.) O halde programdaki satırlara numara verirken, numaralar problemin çözümü için gereken işlem sayısına paralel olarak artmalıdır. Bence en iyisi programı yazarken önce satır numaralarını küçükten büyüğe doğru sıralamalı, sonra yazı kısımlarını işlem sırasına göre doldurmaktır. BASİT DEĞİŞKENLER Evet arkadaşlar bu aylık benden bu kadar, önümüzdeki dersimizde (Aritmetik Operatörler, İfadeler ve Komparatörler) REMARK ve PRINT komutlarını inceleyip bol bol örnekler göreceğiz. Buraya kadar gördüğünüz gibi BASIC dili çok kolay anlaşılır bir dildir, her ne kadar günümüzde pek kullanılmasa da bazen bize gerekebilecek ve en önemlisi 68K işlemcili bilgisayarlarda süper iş görecek sade ve stabil bir dildir. Önümüzdeki sayıda görüşmek üzere, BİR COMMODORE ALIN ONUNLA KALIN ☺
HEXADECIMAL VE ASCII MEMORY DUMP
;=======================================================================================;
; hexadecimal ve ascii memory dump programı
;
; C64 TÜRKİYE dergisi sayı 8 için hazırlanmıştır
;
; 10-05-2005 / ismail "hades" şahin
;
; hades@amigaturk.com
www.c64turkiye.com www.amigaturk.com c64turkiye@amigaturk.com ;
;=======================================================================================;
*=$0801
prg
.word nextline
.word 2005
.byte $9e
.text "2061"
.byte 0
nextline
.word 0
start etiketli yere kadar olan kısımda LIST komutuyla göreceğiniz 2005 SYS2061
satırını oluşturuyoruz.
start
lda
#$0d
;yeşil renk kodu
jsr
$e536
dex
stx
$d020
stx
$d021
stx
$fb
stx
$fc
Yukarıdaki bölümde karakter rengi yeşil olacak şekilde ekranı siliyoruz ve ekran silindikten sonra X registerinin değerini 1 azaltarak "0" yapıyoruz. Bu değeri $D020 ve $D021 adreslerine vererek ekran renklerini siyah yapıyoruz. Ayrıca daha sonra kullanacağımız $FB ve $FC adreslerini sıfırlıyoruz. lda #<text1 ldy #>text1 jsr $ab1e lda #$3a jsr $ffd2 lda #$24 jsr $ffd2
Önce ekrana biraz yazı yazıyoruz sonra ":" ve "$" karakterlerini basıyoruz. adres_gir jsr hex_byte_in sta $fc ;high bayt jsr hex_byte_in sta $fb ;low bayt
Bu bölümde ilk önce adresin HIGH baytını klavyeden girip $FC adresine saklıyoruz.
Sonrada LOW baytını girip $FB adresinde saklıyoruz.
ldy
#$00
ldx
#$06
clc
jsr
$fff0
Yukarıdaki komutlarla kursörün yerini belirliyoruz. Y registerine kursörü koyacağımız yerin sütun değerini, X registerine ise satır değerini vererek Kernal Rom’daki PLOT rutinine sıçrıyoruz.
C64 TÜRKİYE #8 5
lda
#<text2
ldy
#>text2
jsr
$ab1e
lda
#<text3
ldy
#>text3
jsr
$ab1e
Ekrana birşeyler yazdırıyoruz ve asıl bölüme geçiyoruz.
dumper
lda
#$10
sta
line
Ekranda bir seferde kaç satır gösterileceğini ayarlıyoruz.
line_dump
lda
#$20
jsr
$ffd2
lda
$fc
jsr
mem_to_scr
lda
$fb
jsr
mem_to_scr
lda
#$3a
jsr
$ffd2
lda
#$20
jsr
$ffd2
Önce bir adet "boşluk" basıyoruz. Programın başında girdiğimiz adresin önce HIGH
baytını, sonrada LOW baytını hex olarak ekrana yazdırıyoruz. Son olarak ":" ve "boşluk"
karakterlerini basıyoruz
one_line_dump
ldy
#$00
loop1
lda
($fb),y
sta
temp_scr,y
jsr
mem_to_scr
lda
#$20
jsr
$ffd2
iny
cpy
#$08
bne
loop1
Bu bölümde bir satıra hex dump yapıyoruz. Y registerini sıfırlayıp bayt sayacı olarak kullanıyoruz. LDA komutuyla hafızadan o anki baytı alıyoruz ve geçici olarak saklıyoruz. Hafızadan okuduğumuz baytı JSR komutuyla HEX formatlı olarak ekrana yazdırıyoruz. Ekrana bir baytı yazdırdıktan sonra bir adet "boşluk" basıyoruz. Y registerini (bayt sayacı) 1 arttırıp 8 ile karşılaştırıyoruz. 8 olmadıysa hafızadaki bir sonraki bayt için LOOP1 etiketli yere sıçrıyoruz. 8 olduysa program aşağıdan devam ediyor. ascii ldy #$00 ascii_dump lda temp_scr,y cmp #$20 bcc no_ascii cmp #$60 bcs no_ascii .byte $2c no_ascii lda #$2e jsr $ffd2 iny cpy #$08 bne ascii_dump
Burada ise daha önce hafızadan okuyup geçici olarak sakladığımız baytların varsa ascii karşılığını ekrana yazdırıyoruz. İlk olarak Y registerini sayaç olarak kullanmak üzere sıfırlıyoruz. Sakladığımız ilk baytı alıyoruz. Önce "boşluk" karakterinden küçük olup olmadığını kontrol ediyoruz. Eğer küçükse "no_ascii" yazan yere gidiyoruz ve ekrana
C64 TÜRKİYE #8 6 "." karakterini basıyoruz. Eğer okunan bayt "boşluk" karakterinden büyükse bu sefer (Å) karakterinden büyük olup olmadığını kontrol ediyoruz. Eğer büyükse yine "no_ascii" yazan yere gidiyoruz. Eğer küçükse yani okunan bayt $20-$60 arasındaysa ekrana basıyoruz. Fakat burada $2C bayt'ı bilgisayarı kandırmak için kullanıyoruz. $2C değeri "BIT" komutunun kodu olup kullandığı parametre 2 baytlıktır. Bu parametreler ise "no_ascii" yazan yerdeki "LDA #$2E" komutunun baytlarıdır. Dolayısıyla "BIT $A92E" gibi bir komut yazmış oluyoruz. Bu durumda komut sırası .... BCS NO_ASCII - BIT $A92E - JSR $FFD2 şeklinde olmaktadır. Dolayısıyla Aküdeki değer değişmemiş olmakta ve bu değerin ASCII karşılığını yazdırmış oluyoruz. Normalde "no_ascii" yazan yere gelindiğinde Aküye $2E değeri yüklenmektedir ve $2E'nin ascii karşılığı "." karakteridir. Bu nedenle hafızadan okunan baytların ascii karakter karşılığı yoksa "." basılmaktadır. Bu işlemleri 8 defa tekrarlıyoruz ve sonra program aşağıdan devam ediyor. new_line lda #$0d jsr $ffd2
Yukarıdaki iki komutla bir alt satıra geçiyoruz.
mem_setup
lda
$fb
clc
adc
#$08
sta
$fb
bcc
no_inc_fc
inc
$fc
no_inc_fc
dec
line
bne
line_dump
Bu bölümde ilk olarak hafızadan okuyacağımız yeni yerin adresini hesaplıyoruz. $FB adresinde okuma yaptığımız adresin LOW baytı bulunmaktadır. Bu adresteki değeri 8 ile toplayıp geri yazıyoruz. (Her seferinde 8 bayt okuduğumuz için 8 ile topluyoruz). Toplama sonucunda elde biti varsa (yani sonuç 255'ten büyükse -"C" biti "1" ise-) bu sefer $FC adresindeki HIGH baytı bir arttırıyoruz. Eğer elde biti "0" ise yani sonuç 255 veya küçükse "no_inc_fc" yazan yere gidiyoruz. Burada ise daha önce tanımlamış olduğumuz ekranda bir seferde gösterilecek satır sayısını bir azaltıyoruz. “0” olmadıysa “line_dump” yazan yere gidip ekranda 16 satır gösterilinceye kadar işlemleri tekrarlıyoruz. f_keys jsr $ffe4 cmp #$85 ;F1 - Sonraki sayfa beq next_page cmp #$86 ;F3 - Önceki sayfa beq old_pages cmp #$87 ;F5 - Yeni adres beq restart cmp #$88 ;F7 - Çıkış bne f_keys jmp $a474 ;Basic'e geri dön restart jmp start next_page .byte $2c old_pages dec $fc ldy #$00 ldx #$08 clc jsr $fff0 jmp dumper
Burası ekranda 16 satır yani 16*8=128 bayt dump edildikten sonra basılması gereken "F(onksiyon)" tuşlarının kontrol edildiği bölümdür. Önce bir JSR komutuyla tuşları okuyoruz ve "F" tuşları olup olmadığını kontrol ediyoruz. "F1" ile "next_page" yazan yere gidiyoruz. Daha önce bahsettiğimiz şekilde "BIT" komutuyla bilgisayarı kandırıyoruz ve kursörün yerini belirleyip dump etme işine tekrar başlıyoruz. "F3" ile daha önceki sayfayı ekrana getiriyoruz. Bunun için o anki hafıza adresinin HIGH baytının tutulduğu $FC adresinin değerini 1 azalttıktan sonra kursörün yerini belirliyoruz ve başa dönüyoruz. "F5" ile farklı bir adresi dump etmek için programın en başına zıplıyoruz. "F7" ile programdan çıkıyoruz.
Burası altrutinlerin olduğu bölümdür.
hex_byte_in
jsr
hex_key_in
;high nibble
jsr
key_to_mem
asl
asl
asl
asl
sta
$fb
jsr
hex_key_in
;low nibble
jsr
key_to_mem
ora
$fb
sta
$fb
rts
Klavyeden bir baytlık hex sayı girme ve bu sayıyı hafızaya saklama bölümüdür. Önce
klavyeden hex karakter girilen alt rutine gidiyoruz. Geri dönüşte aküde bulunan tuş değe-
rinin sayısal karşılığını almak için bir başka alt rutine gidiyoruz. Buradan geri dönüşte
ise elimizdeki sayıyı 4 kez sola kaydırıp high nibble olarak $FB adresine saklıyoruz.Aynı
alt rutinlere bir kez daha uğruyoruz ve daha önce high nibble olarak sakladığımız değerle
R işlemi yaptıktan sonra aynı adrese yazıyoruz.
O
hex_key_in
jsr
$ffe4
ldx
#$00
control
cmp
key_table,x
bne
next
jsr
$ffd2
rts
next
inx
cpx
#$10
bne
control
jmp
hex_key_in
Bu kısımda klavyeden sadece hex sistem tuşlarına basılıp basılmadığını kontrol edi-
yoruz. Önce klavye taranıyor. Tarama sonunda Aküdeki değeri bir sayaca göre tablodaki
değerle karşılaştırıyoruz. Eğer karşılaştırma sonucunda basılan tuş tabloda varsa karak-
ter ekrana basılıyor ve rutinden çıkılıyor. Yoksa klavye tekrar taranıyor.
key_to_mem
ldx
#$00
loop0
cmp
key_table,x
beq
val_read
inx
cpx
#$10
bne
loop0
val_read
lda
val_table,x
rts
Bu kısımda basılan tuşa göre hafızaya alınacak sayı elde ediliyor. Aküdeki değer
bir tablo ile karşılaştırılıyor. Karşılaştırma sonucu eşitlik varsa, kullanılan sayacın
değeri kullanılarak başka bir tablodan hafızaya yazılacak değer okunuyor ve rutinden
çıkılıyor.
mem_to_scr
pha
lsr
lsr
lsr
lsr
jsr
convert
pla
and
#$0f
convert
tax
lda
key_table,x
jsr
$ffd2
rts
Geldik son alt rutine. Burada yapılan iş hafızadan okunan bir baytı hex olarak ekrana yazdırmak. İlk olarak hafızadan okunan bayt daha sonra tekrar kullanılmak üzere yığına atılıyor. Sonra HIGH nibble değerini ekrana yazdırmak için 4 kez sağa kaydırılıyor. Elde edilen değer sayaç olarak kullanılarak, sayaca göre tablodan okunan değer ekrana yazdırılıyor. Daha sonra yığındaki değer geri alınarak $0F sayısı ile AND işlemi yapılıyor. Böylece LOW nibble elde ediliyor. Sayaç işlemleri bir kez daha yapılıp hafızadaki bir sayı hex olarak ekrana yazdırılmış oluyor.
key_table
.text "0123456789abcdef"
;basılması gereken tuş tablosu
val_table
.byte 0,1,2,3,4,5,6,7,8,9
;tuşlara göre sayısal değerler
.byte 10,11,12,13,14,15
line
.byte 16
;ekrana basılacak satır sayısı
text1
.text " c64 turkiye hex-ascii dump program"
.byte $0d
.text " 10-may-2005 code: hades of ascraeus"
.byte $0d,$0d
.text "f1:next f3:prev. f5:new f7:exit"
.byte 13,13
text2
.text " adres"
.byte 0
text3
.text " hexadecimal memory dump ascii "
.byte $0d
.text " ===== ======================= ========"
.byte $0d,0
temp_scr
.byte 0,0,0,0,0,0,0,0
;geçici saklama bölgesi
.end

