Süper Assembler

Program dökümü: SUPER ASS, RENKLI YASAM, Süper Assembler

Makine dili hastaları işte tam aradığınız assembler. Adeta, yok yok!

Bir süredir. Ayhan Kalaylıoğlu'nun makine dili serisini okumaktasınız. Onbirinci sayımızda da, bir monitör programı verildi. Ayhan, o programın açıklayıcı yazısında, programın assemblerinin çok ilkel olduğunu belirtiyordu. Gerçekten de, sembolik olmayan, yani sadece hexadesimal sayılarla ve verilen adres ve değerleri kullanabilen bu program ile uzun uzun programlar yazmak çok zordur. Hatta hayaldir. Bu işlemi rahatça yapabilmek için, iyi bir assembler programı gerekir.

Önce assembler programının ne demek olduğunu genel hatlarıyla görelim. Biliyorsunuz, makinenin anladığı yegâne dil makine dilidir. Ve bu dilde yazılmış programlar, makinenin hafızasında yazıldıkları adresler arasında yerleşirler ve sadece orada çalışırlar. Örneğin $C000'dan başlayan bir programı $9000'a kaydırıp orada çalıştırmak imkânsızdır. Tüm programdaki JMP, JSR, LDA vs. gibi komutların hedefledikleri adresleri değiştirmek gerekir. Monitör programında, bunu sağlayan bir komut var. Ama, makine programcıları bilirler, programınızda vektörler kullanmışsanız ve LDA #ADRES gibi bir komutunuz varsa (bunun ne demek olduğunu birazdan göreceğiz), monitör bunu değiştirmeyecek, böylece de programınız işlerliğini yitirecektir.

Bunun dışında, programınız içinde hesaplama da yapabilirsiniz. Örneğin LDA #2+3 gibi komutlar, assemblerin anladığı dildendir. Hele birazdan göreceğiniz makro kullanımı ve şartlı assemble denilen yöntemler var ki, hiçbir monitör programında bunları bulamazsınız. Yani, her durumda bu uzun programı yazmak işinize yarayacaktır. Yalnız dikkat! Verdiğimiz uzun program, disket kullanıcılarına göre ayarlanmıştır. Eğer kaset kullanıyorsanız, yazımızın sonundaki açıklamaları dikkatle okuyun!

Özetle, assembler kullanarak program yazdığınızda, hiçbir adresi düşünmek zorunda kalmıyor, gerekli değişiklikleri korkunç bir rahatlıkla gerçekleştiriyor ve ileri programlama tekniklerini kullanabiliyorsunuz. Assemblerde yazılmış birçok örnek programı bu sayımızda görebilirsiniz. Bu yazımızla beraber 'ASS.DENEME' ve 'SUPER ASSEMBLER/KASET' dışında, program ekimizdeki diğer bir program olan 'RENKLİ YAŞAM' da bu assembler kullanılarak hazırlanmıştır.

Artık işe başlayalım. Bakalım assemblerimiz neler yapıyormuş...

Önce Super Assembler'ı MDE kullanarak yazın ve kasete veya diskete kaydedin. Kaset kullanıcılarını tekrar uyarıyoruz. Yazımızın sonunu okumadan bir şeye başlamasınlar. Neyse, assembleri kullanmak için, Super Assembler'ı bilgisayara yükleyin ve RUN komutunu verin. Bilgisayar çok kısa bir süre sonra, BREAK IN 0 cevabını verecektir. Artık assembler sistemi emrinize hazır ve nazırdır. Şimdi iş size düşüyor.

Assemblerin temel görevi, sizin yazdığınız sembolik programın makine koduna çevrilmesi olduğuna göre, önce bir sembolik program hazırlamanız gerekir. Buna assembler kodu adı verilir. Assembler kodunun makine koduna çevrilmiş hali ise, obje kodu olarak adlandırılır. Öyleyse, assembler kodunun ve özelliklerinin neler olması gerektiğini bilmemiz lazım.

Assembler kodu, BASIC programı gibi satırlardan oluşur. Şartlı assemble kullanmadığınız sürece (tamam, sıra ona da gelecek...), satır numaralarının önemi yoktur. Sadece hangi satırın hangi satırdan önce geldiğini belirler. Her bir satır değişik içeriklere sahip olabilir. Bunlar, makine dili komutu, assembler komutu, sembol (label) veya açıklama (BASIC'teki REM gibi)

bölümleridir. Bir satırda bunların bir veya birkaçı olabilir.

Makine dili komutu ile LDA, ADC, JMP gibi, 6510'un anladığı komutları ve bu komutların değişik adresleme şekillerini kasdediyoruz.

Assembler komutları ise, Super Assembler'ın assembler kodunuzu objeye koduna çevirirken gerçekleştireceği birtakım işlemlerin kullanıcı tarafından belirlenmesini sağlarlar. Örneğin, formatlı bir assembler kodu listesi üretebilir, label tablosu isteyebilir, programınızın hafıza içindeki yerini belirleyebilir, değişkenler kullanabilir, birden fazla assembler kodunu birbirine ekleyebilir ve daha birçok işi kolaylıkla gerçekleştirebilirsiniz.

Label'lar ise, programın herhangi bir satırına bir isim vermeye yararlar. Daha sonra bunlar, JMP, JSR, BNE, BEQ gibi atlama komutlarında hedef adres olarak kullanılırlar. Bunların gerçek adres değerlerini assembler hesaplar. Böylece hem siz zahmet etmezsiniz, hem hata olasılığı sıfıra iner, hem de label'ın assembler kodundaki yerini değiştirip RUN ettiğinizde oluşan obje kodu, bu değişiklikle çalışır durumda kalır.

Açıklamaları ise, aslında çok ilkel ve karmaşık bir dil olan makine dilinde yazdığınız programın satırları hakkında yorumlarınızı ve açıklayıcı notlarınızı içerir. Tıpkı BASIC'teki REM komutu gibidirler. Obje kodu üretilirken dikkate alınmazlar. Sadece dökümantasyon açısından önemleri vardır. Size bu özelliği sık sık kullanmanızı tavsiye ederim. İnanın, bir programı yazdıktan birkaç ay sonra, siz bile kendi programınızı anlamayabilirsiniz. Açıklamalar koyarak hem kendinize, hem de programınızı okuyacak olanlara yardımcı olursunuz.

Şimdi, böyle bir satırda geçerli olan kuralları görelim:

1) Her satırın ilk karakteri '-' (eksi) işareti olmalıdır.

2) Her satırda en fazla bir komut olabilir. Bu ya bir assembler komutudur ya da bir makine dili komutu.

3) Bir satırda en fazla bir label olabilir.

4) Eğer label varsa, label ile eksi işareti arasında boşluk olmamalıdır.

5) Eğer satırdaki ilk komut, bir makine dili komutu ise, eksi'den sonra en az bir boşluk olmalıdır.

6) Eğer label varsa, label ile arkasından gelen assembler veya makine dili komutu arasında en az bir boşluk olmalıdır.

7) Bir satırda sadece label olamaz.

8) Bir satırda assembler veya makine dili komutu kullanılmışsa, (başında label olup olmaması farketmez) ve bir açıklama eklenmek isteniyorsa, açıklama noktalı virgülle başlamalıdır.

9) Eğer bir satırda sadece açıklama olacaksa, eksi'den hemen sonra noktalı virgül gelmelidir.

10) Assembler komutları nokta ve iki harften oluşur.

11) Makine dili komutları üç karakterli isimlerinden ve adresleme bölümünden oluşur.

12) Assembler komutları, eksi'den hemen sonra da başlayabilirler, orada boşluk da olabilir.

Tüm bunlar çok karmaşık gelebilir. Ancak aşağıda genel biçimler verilmiştir. Çok kolay olduğunu göreceksiniz.

NNNNN -; açıklama

NNNNN -.AK assembler komutu parametreleri,

NNNNN - .AK assembler komutu parametreleri

NNNNN - .AK assembler komutu parametreleri ; açıklama

NNNNN -.AK assembler komutu parametreleri ; açıklama

NNNNN -LABEL MDK adresleme

NNNNN -LABEL MDK adresleme ; açıklama

Burada, .AK ile assembler komutu, MDK ile makine dili komutu, NNNNN ile satır numarası temsil edilmiştir. Dergimizde bulacağınız örnek programlar da size genel görünüş konusunda yeterli bilgi verecektir.

Makine dili komutlarını zaten Ayhan'ın yazısında görmektesiniz. Açıklamamız gereken, assembler komutlarının neler olduklarını ve ne işe yaradıklarıdır. Ama önce, assembler kodu içinde yapabileceğiniz hesaplamalar ve kullanacağınız değişkenler ile ilgili bazı önemli bilgileri verelim.

Assembler kodunuzda, bir sayı yazabileceğiniz her yerde matematiksel terimler olabilir. Örneğin:

Bu tip işlemlerde, toplama, çıkarma, bölme, çarpma, üs alma gibi beş değişik basit işlemin yanısıra, mantıksal operatörler de mektedir. Bunlar AND, OR, NOT, eşittir, büyüktür ve küçüktür operatörleridir. Yazılışları, iki işaret arasına konmuş baş harflerinden veya sembollerden oluşur:

AND = !A!

OR = !O!

NOT = !N!

büyüktür = !>!

küçüktür = !<!

eşittir = !=!

Bu işlemler parantezlerle kontrol edilebilir:

!N! (değişken1 !=! 5) !A! (değişken2 !<! 20))

Yukarıdaki işlemin sonucu, eğer değişken1'in içinde 5 ve değişken2'nin içinde 20'den küçük bir değer varsa 0 olacaktır. Şimdi bu -1 nereden çıktı diyeceksiniz? Bu işlemin sonucu doğru ise, bunun sayısal değeri -1, yanlış ise 0 olacaktır. Yukarıdaki terim, Basic'te yazılmış aşağıdaki terime eşittir, isterseniz bir deneyin:

NOT (D1 =5) AND (D2 <(20))

Bu işlemlerin dışında, küçük byte ve büyük byte dediğimiz iki işlem daha vardır. Eğer elimizde 0-65535 arasında, yani 16 bit'lik bir sayı varsa, küçük byte bu sayının alt 8 bit'ini, büyük byte da onun üst 8 bit'ini verir. Bunlara KB ve BB dersek, BB*256+KB işleminin sonucu bizim 16 bit'lik sayımızı verecektir. Eğer olayı onaltılık sistemde incelersek, örneğin $5EF8 (24312) sayısının küçük byte'ı $F8 (248), büyük byte'ı da $5E (84) olur.

NNNNN sayısının küçük byte'ını bulmak için <(NNNNN) operatörünü, büyük byte'ını bulmak için >(NNNNN) operatörünü kullanmanız gerekiyor. NNNNN yerine 0-65535 arasında bir sayı, bir label veya bu aralıkta sonuç veren matematiksel bir terim konabilir. Örnek programımızın 200-210 numaralı satırlarında bunun örneğini görebilirsiniz.

Tüm programınız içinde, ondalık ve ya onaltılık sistemde sayılar kullanabilirsiniz. Onaltılık sayıların başına $ (dolar) işaretini koymanız gerekiyor. Programınızın dışında, satır numarası kullanmadan vereceğiniz direkt komutlarda da bu sayı sistemini kullanabilirsiniz. Örneğin, PRINT $C000 komutu ile 49152 cevabını alabilirsiniz.

Sırası gelmişken, diğer Basic komutlarını nasıl kullanacağınızı da belirtelim. LET ve FOR komutlarının dışındaki komutları sadece direkt modda kullanabilirsiniz. Program yazmak yok. Ayrıca PRINT komutundan başka, assembler kodundaki hesaplamalarda kullandığınız terimleri de direkt modda kullanabilmeniz için sola bakan ok tuşunu kullanmanız gerekir. Örneğin, obje kodu ürettikten sonra programda kullandığınız bir label'ın veya değişkenin değerini öğrenmek istediniz. Bu durumda PRINT label-adı komutu yerine, PRINT'in yerine sola bakan

ok işaretini koyacaksınız.

Eğer ikilik sistemin kullanılamaması sizi rahatsız ediyorsa, bunu toplama ve üs alma işlemleri ile kolayca gerçekleştirebilirsiniz. Örneğin, LDA #%00101 satır geçersizdir. Ancak bunun yerine, LDA #2↑0+2↑2 yazabilirsiniz.

Sıra geldi değişken kullanımına. Label'ların dışında, iki tür değişken kullanılabilir. Genel ve yerel değişkenler. Birazdan göreceğimiz gibi, bir tür alt-program sayabileceğimiz makro kullanımı sırasında, o makronun içinde kullanacağımız tüm değişkenler ve label'lar o makro içinde yerel (local) sayılacaklardır. Bunun en önemli sonucu, programın ana kısmında ve makroların içinde aynı isimli değişkenleri veya label'leri kullanırsanız bile, hiçbirinin birbirine karışmamasıdır. Bir değişkenin değeri bir makroda 5, bir diğerinde 2, ana programda da 8 olabilir. Eğer o değişkenin tüm program içinde geçerli bir değere sahip olmasını istiyorsanız, onu genel (global) değişken olarak tanımlamanız gerekir. Bunun nasıl yapıldığını da birazdan göreceğiz. Değişken isimlerinin istediğiniz uzunlukta olabileceğini, tüm karakterlerinin önemli olduğunu, ilk karakterlerinin bir harf olması gerektiğini, geri kalanlarının da harf veya sayı olabileceğini belirterek bu konuyu da kapatalım.

Nihayet geldik assembler komutlarına:

.BA adres

Obje kodu hafızada, bu komutun olduğu satırdan sonraki satırlar için, verilen adresten sonraya yerleştirilir. Adres, desimal veya hexadesimal olabilir. Bir programda birden fazla BA olabilir. Bu durumda, assembler kodunuzun değişik bölümleri değişik adreslerde assemble edilir. Kaset kullanıcıları için verdiğimiz programa bakın.

GL değişken=değer

Adı verilen değişken, desimal veya hexadesimal olarak belirtilen veya matematiksel terim olarak verilen değere sahip olur. Aynı zamanda, değişken genel (global) tanımlanmış olursunuz. Değerin 0-65535 ($0000-$FFFF) arasında olması gerekir.

.EQ değişken=değer

GL gibidir, ancak değişken yereldir (local).

.BY byte1, byte2, byte3......

Verilen byte değerleri hafızaya sıralı yerleştirilir. Her bir byte $00-$FF (0-255) arası değerde olmalıdır. Örneğin:

.WO adres1, adres2

Bildiğiniz veya öğreneceğiniz gibi, 6510 prozesörü bir adresi lo/hi denen formatta saklar. Diyelim ki adresiniz $7A8E. Eğer bu adres hafıza içinde arka arkaya gelen iki byte'a yerleştirilecekse, önce $8E, sonra da $7A yerleşir. Yani önce küçük byte, sonra da büyük byte. .WO komutu, arkasından gelen 0-65535 arası değerlerdeki sayıları sırasıyla bu formata göre hafızaya yerleştirir. Örneğin:

.TX "yazı"

Yazıyı oluşturan harflerin ASCII kodlarını hafızaya yerleştirir.

.OB "dosya-adı,P,W"

Eğer oluşan obje kodunun bir program halinde diskete gönderilmesini istiyorsanız, programınızın en başında bu satır bulunmalı. Kaset kullanıcıları bu komutu kullanamaz.

.EN

Eğer .OB kullanmışsanız, programın en son satırında .EN vererek dosyayı kapatmalısınız. Eğer obje kodu üretilirken bir hata olmuş ve obje kodu üretimi durmuş ve dolayısıyla da dosya açık kalmışsa, CLOSE 14 ile elden de kapatabilirsiniz.

.LI dosya-no,araç-no,ikincil-adres

Obje kodu üretilirken, bu komuttan sonra gelen tüm satırlar, verilen parametrelere göre formatlı bir şekilde gönderilir. Örneğin:

.SY dosya-no,araç-no,ikincil-adres

Obje kodu üretildikten sonra, kullanılan sembollerin alfabetik sırayla, verilen parametrelere göre basımını sağlar. Örneğin:

.ST

Assembler, obje kodu üretirken bu komutu görürse üretimi durdurur.

.DP k0,k1,k2,k3

.LI komutu sonucunda basılacak dökümün formatını ayarlar.

k0 : Assembler ve makine dili komutlarının başlayacağı kolon

k1 : Noktalı virgülün ve açıklamaların başlayacağı kolon

k2 : Kağıdın veya ekranın solunda bırakılacak boş kolon sayısı

k3 : SY komutu verilmişse, sembollerin basımının başlayacağı kolon

Genel amaçlı assembler komutları bu kadar, 10 tane daha var. Onları da birazdan göreceğiz.

Zincirleme Assemble

SUPER ASSEMBLER ile birden fazla assembler kodunu arka arkaya otomatik olarak objeye çevirebilirsiniz. Bu iş için iki assembler kodumuz var:

.AP "dosya-adı"

O anda kullanılan assembler kodunun objeye çevrilmesi bitince, verilen isimli dosya doldurulur ve onun objeye çevrilmesiyle devam edilir.

.CO değişken1,değişken2...

Listede yer alan tüm değişken ve/veya label'lar ve .CO komutundan önce gelen tüm satırlar korunur. .AP ile doldurulan program, bu satırlardan sonrasına yerleşir. Böylece programın başında tanımlayacağınız makro ve değişkenler ikinci programda da geçmiş olacaktır. Bu arada dikkat etmeniz gereken şey, .CO komutundan önceki satırlarda .BA komutu ile ana programın parçalarının olmaması gerektiğidir. En ideal durumda sadece makro tanımlamalarının olması gerekir.

Şartlı Assemble

IF..THEN..ELSE veya GOTO komutlarının benzerlerini kullanarak yazılan programlar, şartlı assemble'ye örnektirler. Bu komutlara göre, assembler kodunun bir bölümü veya bir başka bölümü objeye çevrilir. Veya belli bir bölüm birkaç kez arka arkaya objeye çevrilir. Diyelim ki bir komutun obje kodunda 50 kere arka arkaya gelmesi gerekiyor. Bunun için 50 satır yazmak yerine, bir sayaç

ile döngü içinde, aşağıdaki komutları kullanarak aynı komutun 50 kere objeye çevrilmesini sağlayabilirsiniz.

ON şart,satır no

Eğer belirtilen şart doğru ise obje kodu üretimi devam edecektir. Eğer yanlışsa, üretim verilen satır numarasından devam edecektir. Örneğin:

Hem s'in değeri 0 hem de g'nin değeri 5 olduğu için, obje kodu üretimi 40'tan devam edecek ve 50 satırda duracaktır. s'in içinde de 3 olacaktır. Eğer 20'nci satırda s=10 yaparsak, obje kodu 30'uncu satırda 60 numaralı satıra atlayacak ve s=2 olacaktır.

.GO satır-no

Herhangi bir şarta bağlı olmaksızın, obje kodu üretimi, verilen satırdan devam eder.

.IF .EL .EI

IF...THEN...ELSE...ENDIF yapısını oluştururlar. Bir örnekle görelim:

s ve f değerine göre, verilen şart yanlış olduğu için .EL ile .EI arasındaki bölüm objeye çevrilir ve PEEK(2) ile elde edeceğimiz sonuç 2 olur.

Tabii ki, .EL komutunu kullanma zorunluluğu yok. Sadece .IF ve .EI kullanılabilir. Bu durumda arada kalan satırlar, sadece şart doğru ise objeye çevrilir.

Makro Tanımlama

Sıra geldi makrolara... Bunları bir alt program gibi görebiliriz. Makine dili programcılığında çok kullanılan kalıplar vardır. Veya bir programın içinde aynı tür bir algoritmaya bir iki sayı farkıyla tekrarlanıp duruyordur. İşte bu tür bir program parçası sadece bir kez makro halinde tanımlanır ve bir isim verilir. İçinde geçen bazı değişkenlerin parametrik olması da sağlanır. Artık ana programda sadece makronun adı ve o sırada kullanılması gereken değişkenler yazılır ve SUPER ASSEMBLER bunları kullanarak gereken program parçasını kendiliğinden yaratır.

Bir makronun genel görünümü şu şekildedir:

Ana program içinde çağırırken de şu şekil kullanılır:

Şimdi bunları ayrıntısıyla görelim:

.MA isim (parametre1,parametre2....)

Tanımlanacak makronun adı ve kullanacağı parametrelerin isimleri verilmektedir. Bu isimler global tanımlanmış değişkenlerle aynı olamaz. Bu satırdan sonra gelen (.RT'den önceki satırlarda) kullanılan değişkenler, aksi şekilde tanımlanmadığı sürece yereldir.

Bir makronun içinde şartlı assemble yapabilir, bir başka makroyu çağırabilir, hatta işinize yarayacaksa kendisini de çağırabilirsiniz.

.RT

Makro tanımlamasının bittiğini belirtir. Bu satırda bir label olamaz!

... isim (parametre1,parametre2....)

Verilen isimdeki makro tanımında yeralan tüm parametreler, verilen parametrelerle değiştirilir ve ortaya çıkan assembler kodu ... (üç tane yanyana konmuş nokta) komutunun olduğu satırdaymışçasına objeye çevrilir. ... komutunu yeni bir makine dili komutu gibi düşünebilirsiniz. Gerçekten de, aslında bir assembler komutu değildir ve üç harfli makine dili komutları gibi işlem görür. .MA komutundan sonra sadece parametre isimlerini kullanabiliyorduk. Ancak ... komutunda, parametre yerlerine sayı, değişken, label adı veya matematiksel terim konabilir.

Örnek Program

Gördüğümüz assembler komutlarının çoğunu kullanan örnek programımıza biraz göz atalım:

5 : Tüm programın listesi, 1 numaralı kanaldan ekrana gönderilecek.

6 : Obje kodu, "OBJ.DENEME" adı altında diskette yaratılacak.

7 : En sonda label tablosu, 2 numaralı kanaldan ekrana gönderilecek.

10 : Programın başlangıç adresi $C000(49152). Yani SYS 49152 ile çalışacak.

20 : Boşluk tuşunun ASCII kodu global bir değişkene yükleniyor.

70 : ROM'da yer alan ve akümülatör ile Y-yazmacının gösterdiği adresten başlayan yazıyı o an açık olan yazım aracına gönderen rutinin başlangıç adresi bir değişkene yükleniyor.

80 : ROM'da yer alan ve akümülatörde bulunan ASCII kodunu o an açık olan yazım aracına gönderen rutinin başlangıç adresi bir değişkene yükleniyor.

90 : BAS isimli bir makro tanımlamaya başlıyoruz. İlk parametre basılacak yazının başlangıç adresi, ikincisi ise kaç kere basılacağı. Makromuz, belirtilen yazıyı istendiği kadar basacak ve bu arada da her satırda bir kolon daha içeriden başlayacak.

100 : Basılan satırları sayaç sıfırlanıyor.

110 : Basılan boşlukları sayaç sıfırlanıyor.

120 : Boşluk kodu akümülatöre yükleniyor.

130 : Eğer yeteri kadar boşluk basılmışsa...

140 : 200'üncü satırdan devam et.

150 : Basılmamışsa...

160 : Boşluk bas ve...

170 : Boşluk sayacını bir arttır...

180 : Ve IF komutunu burada bitir.

190 : Kod üretimine 130'uncu satırdan tekrar başla.

200 : Akümülatöre yazının başlangıç adresinin küçük byte'ını yükle.

210 : Y-yazmacına yazının başlangıç adresinin büyük byte'ını yükle.

220 : Ve baskıya gönder.

230 : Satır sayacını bir arttır.

240 : Eğer yeteri kadar basılmamışsa, 110'a geri dön.

250 : Makro tanımı bitti.

260 : YAZI1 label'inin gösterdiği yazıyı üç kere bas.

270 : YAZI2 label'inin gösterdiği yazıyı dört kere bas.

280 : Geri dön.

290 : Verilen yazının ASCII kodlarını RTS'nin kodundan sonraya yerleştir.

300 : Kaldığın yere 13 ve 0 byte'larını koy (RETURN'ün kodu ve yazının bittiğini belirten kod).

310-320: Aynı işlemleri bu yazı için de yap.

330 : Obje dosyasını kapa.

340 : Obje üretimini durdur.

Bu programın ürettiği obje koduna monitör ile bir göz attığımızda ve SYS 49152 ile elde ettiğimiz sonuca bakınca, işlemlerin doğru yapıldığını görüyoruz (ve hiç şaşırmıyoruz, değil mi?..).

SUPER ASSEMBLER'ın çalışmasıyla ilgili bir iki küçük not daha. Programın içinde bir byte değerinin yer alması gereken bir yere tek bir harfi "X" şeklinde koyabilirsiniz. Örneğin, LDA #"A" ile, "A" harfinin ASCII kodu akümülatöre yüklenmiş olur. Obje kodu üretimi bitince, geçen süre dakika:saniye:1/10saniye formatında belirtilecektir. Ayrıca, programın ilk ve son byte'larının yerleştiği adresler de gösterilecektir.

Bu kadar iyi bir assemblerin yazımının da rahat olması gerekir, değil mi? İşte bu nedenle, bir sürü de editör komutu hazır edilmiştir, siz kullanın diye. Sıra geldi onlara.

Tüm editör komutları, / (bölü) işareti ile başlar. Her biri tek bir harf ve gerekli sayıda parametre içerir. Her satırda sadece bir tek editör komutu kullanılabilir. İki nokta üstüste ile birbirlerinden ayrılmazlar. Basic editörünün özellikleri aynen korunmuş, yeni komutlar eklenmiştir. Hepsi de, tabii ki, direkt modda kullanılır, programların içinde hataya yol açarlar.

/A sayı1,sayı2

Otomatik satır numarası üretir. Örneğin /A 100,10 komutundan sonra bilgisayar, 100 numaralı satırdan başlayıp, 10'ar artırarak satır numaralarını yaratacaktır. Hatta, yazılmasını unutulabilen eksi işareti de kendiliğinden yazılacaktır. Eğer satır üretiminin durmasını isterseniz, o satıra herhangi bir şey yazmadan RETURN tuşuna basınız. Bir uyarımız olacak... Diyelim ki 150'nci satırı yazarken 130'uncu satırda bir hata gördünüz. Sakın cursor'u o satıra çıkarıp düzeltme yapmayın. Önce yazdığınız satırı bitirin, sonra ortaya çıkan 170'den sonra hemen RETURN'a basıp satır üretimini durdurun, ondan sonra düzeltme yapın.

/O

NEW ile sildiğiniz programı yeniden geri getirir. Tabii ki, NEW komutundan sonra hiçbir satır yazmamış olmanız şartıyla.

/D satır1-satır2

Satır1 ile satır2 arasında kalan satırlar (kendileri dahil) silinir. Satır numaraları, LIST komutunda olduğu gibi değişik şekiller de verilebilir. Örnekler:

/D 1000

/D 1000-2000

/D -2000

/D 1000-

/E satır1-satır2

Belirtilen bölge, formatlanmış bir şekilde ekrana getirilir. Artık istediğiniz değişikliği yapabilirsiniz. Sakın LIST yapıp programınızı düzeltmeye kalkışmayın, programınız size güme gider. Örnekler:

/E

/E 1000

/E 1000-2000

/E -2000

/E 1000-

/Tn,kolon

.DP komutu gibi, formatlı dökümde kullanılan kolonları belirler. 'n' yerine 0-3 arası bir sayı gelecektir.

/X

Bilgisayar, açılış durumuna döner.

/P no,satır1,satır2

Programınızı, 30 değişik sayfaya bölebilirsiniz. Bu, daha sonraki işlemlerinizde işinize yarayacaktır. 'no' yerine 1-30 arası bir sayı koyabilirsiniz. Örneğin /P1,100,200 komutu ile, 100-200 arası satırları birinci sayfa olarak nitelediğinizi belirtiyorsunuz.

/no

Belirtilen numaralı sayfayı oluşturan satırlar formatlı olarak listelenir.

/N no, satır no,artış

Belirtilen sayfanın satır numaraları, verilen satırdan başlamak ve artış aralıklarına göre artmak üzere yeniden ayarlanır.

/F no,"text"

Belirtilen sayfada, verilen "text"i içeren her satır formatlı olarak basılır. "text" içinde bilinmeyen karakterler varsa bunların yerine soru işareti konulabilir. Örneğin, /F1,"T??T" komutu ile, birinci sayfadaki TEXT, TILT, TARTI gibi arasında iki herhangi harf olan iki T'ye sahip her satır listelenir.

/R no,"text1",text2"

Belirtilen sayfadaki tüm "text2"ler "text1" ile değiştirilir. "text2"nin içinde soru işaretleri olabilir. "text1" boş ise, "text2"ler silinir.

/U adres

Normalde programı kodunuz, 8152 ($1FD8) adresinden başlar. Ancak bu adresi daha yukarı çıkarabilirsiniz. Böylece arada kalan boş alanı makine dili programları için kullanabilirsiniz.

/B

Hafızanın o anki durumunu gösterir. Sırasıyla program başlangıcının alabileceği en küçük adres değeri (8152), o anki gerçek program başlangıç adresi, o anki program bitiş adresi ve geri kalan boş byte sayısı bildirilir.

/L"isim"

LOAD ile aynı işi yapar.

/S"isim"

SAVE ile aynı işi yapar.

/V"isim"

VERIFY ile aynı işi yapar.

/M"isim"

MERGE ile aynı işi yapar. Adı verilen dosyayı, hafızadaki programa ekler.

/G no

Kayıt aracının numarasını değiştirir. Normalde 8'dir.

/I

Disketinizin içeriğini (directory) görmenizi sağlar.

/K

Disk drive'ın hata mesajını okuyup ekrana yazar.

/@ komut

Disk drive'a komut gönderir. Örneğin bir dosyayı silmek için:

/@s: dosya adı

Komutlar için 1541'in el kitabına bakın.

/CH renk

Ekran rengini ayarlar.

/CR renk

Çerçeve rengini ayarlar.

/I

Obje kodu üretildikten sonra, kullanılan label'lerin listesini verir.

/II

/I gibidir, ancak listeyi alfabetik sırada verir.

Bir kez daha uyaralım... Her satırın eksi işareti ile başlaması gerekiyor. Eğer bir satır /D ile değil de, Basic'te-

ki gibi satır numarasını yazıp RETURN'a basarak silmek istiyorsanız, satır numarasının yanına eksiyi de yazmanız şart. Assembler o satırı silecek ve bir sonraki satırı otomatik olarak gösterecektir. Sizin de hemen göreceğiniz gibi assembler, siz bir satır yazıp RETURN'a basar basmaz yazdığınız satırı formatlayıp ekrana yeniden basacaktır. Böylece programınızı yazarken kontrol etmeniz çok kolaylaşacaktır.

Bir de, assemblerimizin hata mesajlarını görelim:

CAN'T NUMBER TERM : Bir terim hesaplanamıyor. Assembler komutlarından biri yanlış yazılmış olabilir.

END OF LINE EXPECTED : Satır sonu beklenirken bir başka koda rastlanmış.

UNKNOWN PSEUDO : Assembler komutu anlaşılamıyor.

ILLEGAL REGISTER : Makine dili komutunda index yazmacı yanlış.

WRONG ADRES : Makine dili komutu yanlış adresleme modu ile kullanılmış.

ILLEGAL LABEL : Tanımlanmamış label kullanılıyor.

BRANCH TOO FAR : BNE, BEQ, BCC gibi atlama komutlarıyla hedeflenen adres 127 byte'den uzak.

LABEL DECLARED TWICE : Aynı adlı label ikinci kez tanımlanmış.

TOO MANY LABELS : Hafıza artık hem programı hem de değişkenleri alamıyor. Çok değişken kullanılmış.

NO MACRO TO CLOSE : .MA olmadan .RT verilmiş.

PARAMETER : Makro çağırılırken gönderilen parametreler, tanımlamadaki parametre sayısıyla aynı değildir.

RETURN : .MA olmadan .RT verilmiş.

Hafıza kullanımı da şu şekilde:

$0000 : Zeropage

$033C: Genel amaçlar için kullanılıyor.

$0400 : Video RAM

$0800-$1FD7 : Assembler kodu için ayrılmış bölge

$A000-$BFFF : BASIC ROM'u ve altındaki RAM'da tanımladığınız değişkenler.

$C000-$CFFF : Kullanılmıyor, yani boş Siz kullanabilirsiniz...

$D000-$FFFF : İşletim sistemi.

İşte sonuna geldik. Bir iki uyarı da kaset kullanıcılarına. Maalesef, C-64'ün kasete kayıt sırasında kullandığı kodlama, diskete kayıttakiyle aynı olmadığı için, .OB ile oluşan kodu kasete kaydetmeniz imkânsız. /G1 ile araç numarasını kasete çevirip tüm işlerinizi halledebilirsiniz, ancak .OB işe yaramaz. Bu nedenle, size küçük bir program daha sunuyoruz. Bu, assemblerde yazılmış ve Süper Assembler'ı kasete ayarlayan bir program. Dergimizde yayınladığımız uzun Süper assembler programını MDE ile yazıp SAVE ettikten sonra yükleyip RUN ile çalıştırın ve "Süper Assembler/Kaset" programını aynen yazın. RUN ile çalıştırıldıktan bir süre sonra obje üretimi duracak ve bilgisayar, PRESS RECORD&PLAY ON TAPE yazacaktır. RUN/STOP tuşu ile çıkın ve SYS 49152 ile Süper Assembler'ın bu yeni halini kasete SAVE edin. Adı Süper ASS/Kaset olacaktır. Artık bu assemblerı kullanabilirsiniz. Herhangi bir assembler kodunu objeye çevirdikten sonra, bu yeni Süper Assembler kendiliğinden PRESS RECORD&PLAY ON TAPE diyerek, kasette kayda başlamanızı bekleyecektir. Eğer kayıt yapılmayacaksa RUN/STOP ile durdurun. Yapılacaksa da, kaseti çalıştırın. Programınız LISTE$ adıyla kasete geçecektir. Ancak bu işlemin doğru yapılabilmesi için programınızın $C000-$CFFF arasında olması gerekir. Bir başka olasılık da /U komutu ile kendinize $1FD8'den sonra boş yer yaratıp, objeyi oraya yaratırmanız.

Bir diğer olanak da, elinde monitör programı olan arkadaşlar için geçerli. Objeyi yarattıktan sonra /X ile Basic'e geri dönün. Korkmayın, bu arada makine dili programınıza bir şey olmaz. Şimdi monitör programınızı, makine programınızla üstüste gelmeyecek şekilde yükleyin ve monitörün SAVE komutunu kullanın. Nasılsa obje üretimi sonunda ilk ve son byte adresler veriliyor. Ancak son byte adresine bir eklemeniz gerektiğini unutmayın.

İşte bu kadar... İyi programlar...

Bu yazıdaki programlar

Dergideki dökümlerden çıkarıldı; satırlar derginin kontrol toplamlarıyla doğrulandı ve programlar VICE emülatöründe denendi. Tarayıcıdaki C64'te çalıştırabilir, indirip bir emülatöre sürükleyip bırakabilir ya da gerçek bir C64'te LOAD "AD",8,1 ile yükleyebilirsiniz. "Sorun bulundu" yazanlarda bazı satırlar okunamadı ya da tutmadı; düzeltilmiş bir sürümünüz varsa contact@coze.org adresine gönderin.