ASSEMBLER-6
Retro bilgisayarBNE komutunu ilk defa kullandığımızda örneğin BNE 1200'ün tahmin edildiği gibi 3 Bayt'lık bir komut olmadığını belirtmiş ve hafızada sadece iki bayt işgal ettiğini söylemiştik. Şimdi yeni bir adresleme yöntemi olan relatif adreslemeyi öğrenirken aynı zamanda Branch komutlarının neden 3 yerine 2 bayt kapladıklarını göreceğiz. Örneğin BNE 1200 yazdığımızda kullanmakta olduğumuz monitör programı $1200 mutlak adresine karşılık gelen relatif adresi hesaplamaktadır. Son adresleme yönteminde bilgisayar dallanmanın kaç bayt ileri veya geriye yapılacağına bakmaktadır. Karşımıza iki soru çıkmaktadır: 1. Bilgisayar hangi adrese göre relatif olarak dallanmaktadır? 2. $1200 gibi mutlak bir adres girdiğimizde bilgisayar kaç bayt ileri veya geri dallanacağını nasıl saptamaktadır? Bu soruların cevaplarını aşağıdaki kısa programda bulacağız.
2000 AD0030 LDA $3000
2003 FO 05 BEO $200A
2005 A9 00 LDA # $00
2007 — 8D 00 30 STA $3000
2004 60 RTS
Programımız $3000 baytının içer-
diği değeri akümülatöre yüklemekte, eğer sonuç sıfır ise Basic'e geri dönmektedir (RTS). Eğer $3000 sıfıra eşit değilse bu adres sıfır yapılmaktadır. Bu program ilk bakışta pek anlamlı gözükmese de $3000 bir Flag (bayrak) olarak kullanılırsa oldukça yararlı olur. 6510 makina dilinde bilgisayar hangi satırı işleyeceğini program sayacından (Program Counter) öğrenmektedir. Yukarıdaki programımızda sıra BEQ'ya gelince sayaç otomatik olarak bir adım fazla atarak bir sonraki satırı yani $2005'i göstermektedir. Bu şekilde birinci sorumuzun da cevabını almış oluyoruz. Branch komutlarında dallanmanın gerçekleşeceği uzaklık (genellikle Offset olarak adlandırılır) program sayacına eklenir. İkinci sorunun cevabı için ise yukarıdaki programı bu sefer bayt bayt inceleyelim:
Değer:
838388
Anlamı:
LDA $3000'ın Alçak Baytı $3000'in Yüksek Baytı BEQ Offset LDA $
STA
$3000'in Alçak Baytı $3000'in Yüksek Baytı
Görüldüğü gibi yukarıda bayt sayılarının yanında ayrıca $2005'e olan uzaklıkları yer almaktadır. BEQ komutunda program sayacına toplanacak değerin 05 olduğu belirtilmiştir. Dolayısıyla BEQ komutuna uzaklığı 05 olan satır burada işleme konulacaktır. Kısaca şunu söyleyebiliriz: Eğer ileri yönde bir dallanma yapılacaksa Branch komutundan sonraki satırdan itibaren uygulanması istenilen komuta kadar olan baytlar sayılır ve bu sayı Offset'tir. Yukarıdaki yöntemle ters yönde de dallanma gerçekleşebilir. Daha önceki programlarımızda bunu birçok defa kullandık. Şimdi bu gibi durumlarda Offset'in nasıl hesaplanacağını görelim. Aşağıda makine dili bir programın sadece bir bölümünün Assembler dökümü yer almaktadır.
1000 A2 00 LDX # $00
1002 E8 INX
1003 DO FD BNE $ 002
00 BRK
1005
Bu program daha önce sıfır yapılan X-register'inin değerini 255'i geçene (255'den sonra tekrar 0 gelmektedir) kadar bir arttırmaktan başka iş yapmamaktadır. X-Register'in değeri 0 olmadığı sürece 1002 satırındaki INX komutuna bir dallanma gerçekleşmektedir. Bu register ancak 0 olduğunda BRK ile program durmaktadır. Daha önce belirttiğimiz gibi program sayacı yukarıdaki BNE komutuna sıra geldiğinde $1005'i göstermektedir. Yukarıdaki programı bu sefer bayt bayt inceleyelim:
Bayt: Değer: — Anlamı:
1000 A2 LDX#$
1001 00
1002 3 E8 INX
1003 2 DO BNE
1004 1 FD Offset
1005 00 BRK
Yukarıda yine bayt numaralarının
yanında o an program sayacında belirtilen adrese olan uzaklıklar yazılmıştır. INX komutuna ulaşabilmemiz için sayaçtan 3 çıkartmalıyız. Daha önceki sayılarda belirttiğimiz gibi bilgisayar bir sayıyı çıkartırken o sayının ikinci dereceden karşılığını toplamaktadır. Bu nedenle 03'ün ikinci dereceden karşılığını hesaplamalıyız:
Birinci dereceden karşılık: $1
İkinci dereceden karşılık:
Bu son sayı $FD'ye eşittir ve yukarıdaki örnekteki Offset'e karşı gelmektedir. Ters yöndeki dallanmalar için şu kural geçerlidir: Program sayacının gösterdiği adresten itibaren uygulanması istenen komuta dek olan bayt sayısı belirlenir. Bu sayının ikinci dereceden karşılığı ise Offset'in değeridir. Aşağıdaki şema yukarıda anlatılanları özetlemektedir:
Bayt: — İçeriği: Offset:
1995 F9
1996 FA
1997 FB
1998 FC
1999 FD
000 BNE FE
2001 — Offset FF
2002 — Sayaç Durumu
2003 01
2004 02
2005 03
Bu anlatılanlardan sonra Branch komutlarında var olan sınırlamayı herhalde fark etmişsinizdir. Özellikle ters yönde olan dallanmaların negatif sayılarla oldukça fazla benzerliği vardır: Her ikisinde de ikinci dereceden karşılıklar ile işlem yapılmaktadır. Nitekim bir bayt ile gösterilebilinen en büyük pozitif sayı
4127-$7F ve en küçük negatif sayı 1000 0000 = -128 olduğu için ancak bu sınırlar içinde bir dallanma gerçekleşebilir. Bu nedenle örneğin aşağıdaki gibi bir satır 6510 makine dilinde mümkün değildir: 3000 BNE 1000
Birçok monitör programı böyle bir satır yazıldığında hata mesajı verir. Ex-Mon ise bu durumda 1000 yerine başlangıç adresini yazmaktadır.
Zero Page:
Relatif adresleme yöntemini de gördükten sonra şimdi başka bir adreslemeye geçiyoruz: Zero Page ad- Zero Page ne demektir? Bu terimin
0000 0011 1111 1100 1
1111 1101
(İkilik sistemde)
dilimizdeki karşılığı “Sıfırıncı sayfa”dır. Bilgisayar dilindeki karşılığını iyi anlayabilmek için ise adreslerin C-64 tarafından algılanış şeklini anımsamak gerekir. 16 Bit'lik bir sayı alçak ve yüksek olmak üzere iki bayt haline gelmekteydi. Örneğin $1F04 sayısının alçak baytı $04 ve yüksek baytı $1F'dir. Bu şekilde C-64'ün tüm belleği yani 65535 bayt adreslenebilir. $0000 - $00FF arası ilk 256 adresin yüksek baytları sıfırdır. Böyle 256 baytlık bölgeler sayfa (page) olarak adlandırılır. Yüksek baytları “0” olan bu sayfaya “Sıfırıncı Sayfa” denir. Eğer örneğin akümülatöre bir sıfırıncı sayfa adresi olan $00FA'nın değerini yüklemek istersek şu satırı yazmalıyız:
3000 LDA $00FA
Fakat C-64'ümüzün mikroişlemcisi aşağıdaki satırı da anlayacaktır:
3000 LDA $FA
İşte buna sıfırıncı sayfa adresleme yöntemi adı verilir. LDA komutumuz bu şekilde hafızada 3 yerine sadece 2 bayt kaplar. Şu ana kadar öğrendiğimiz birçok komutta bu adreslemeyi kullanabiliriz:
LDA,LDX,LDY,STA,STX,STY, INC,DEC,ADC ve SBC
Mutlak adreslenen tüm komutlar yukarıda gördüğünüz gibi sıfırıncı sayfayla da adreslenebilir. Resim 1'de komutlar ayrı ayrı ele alınmıştır. Şimdi gelelim hız farklarına: Mutlak ve Sıfırıncı sayfa adresleme yöntemlerini gösteren tabelaları yanyana koyduğumuzda ikisi arasında her komut için bir cycle (çevrim) fark olduğunu görebiliriz. İlk bakışta bu oldukça önemsiz gibi gözükebilir, ancak birkaç yüz defa tekrarlanan döngülerde bu fark büyük önem kazanır. Bu nedenle hız unsurunun ön planda olduğu programlarda muhakkak sıfırıncı sayfada adresleme yapılmalıdır. Yukarıda anlatılan durum C-64'ün işletim sistemini ve Basic yorumlayıcısını geliştiren kimselerce de çok iyi biliniyordu. Bu nedenle hemen hemen tüm kernal (işletim sistemi) ve Basic rutinleri sıfırıncı sayfaya bir
Bayt Etkilediği Komut: | Adresleme: Sayısı | Hex Dec | Süre: | Bayraklar LDA Sıfırıncı Sayfa 2 A5 165 3 NZ LDX Sıfırıncı Sayfa 2 AB 166 3 NZ LDY Sıfırıncı Sayfa 2 A4 164 3 NZ STA Sıfırıncı Sayfa 2 85 133 3 - STX Sıfırıncı Sayfa 2 86 134 3 - STY Sıfırıncı Sayfa 2 84 132 3 - INC | Sıfırıncı Sayfa 2 DE 222 5 | NZ DEC Sıfırıncı Sayfa 2 C6 198 5 NZ ADC Sıfırıncı Sayfa 2 65 101 3 SBC Sıfırıncı Sayfa 2 E5 229 3 CMP | Dolaysız 201 2 NZC Mutlak 3 CD 205 4 N.Z.C Sıfırıncı Sayfa 2 C5 197 3 N.Z.C CPX Dolaysız 2 E0 224 2 N.Z.C Mutlak 3 EC 236 4 Sıfırıncı Sayfa 2 E4 228 3 CPY Dolaysız 2 C0 192 2 NZ.C Mutlak 3 CC 204 4 Sıfırıncı Sayfa 2 C4 196 3 NZ.C, Resim 1:
şeyler not etmektedir. Böylece Assembler programcıları için sıfırıncı sayfayı kullanmak oldukça zor bir hal almıştır ve bazı sıfırıncı sayfa değerlerinin değiştirilmesi felaketlere yol açabilir. Bu nedenle kendiniz C-64'ün bellek haritasını inceleyip hangi adresleri kullanacağınıza karar vermelisiniz. Her Assembler programcısının kendine özgü sıfırıncı sayfa adresleme yöntemleri vardır. Yalnız $02 ve $FB-$FE baytlarında her an gönül rahatlığı ile adresleme yapabilirsiniz. Eğer programcılık bilginize güveniyorsanız Basic yorumlayıcıyı ve C-64'ün işletim sistemini tamamıyla devre dışı bırakma olanağına her zaman sahipsiniz. Böylelikle Sıfırıncı sayfanın tümünü rahatlıkla kullanabilirsiniz, yalnız bu durumda gerekli olacak tüm rutinleri kendi başınıza oluşturmak zorunda kalacağınızı kesinlikle unutmayın. Sonuçta kernal rutinleri kullanılarak yapılabilen en basit işlem bile içinden çıkılamayacak bir hal alacağı için bu yöntem çoğu zaman ihmal edilir. Kursumuzun bundan sonraki bölümünde sık sık sıfırıncı sayfa adresleme yöntemini kullanacağız ve bu sayfayı kullanan kernal ve Basic yorumlayıcı rutinlerini inceleyeceğiz. Sıfırıncı Sayfa'yı kullanan rutinlere en güzel örnek CHRGET rutinidir. Bu program sadece Sıfırıncı sayfayı kullanmaz, tamamıyla burada yeralır. Bu çok gerekli rutinin kullanılışına geçmeden önce karşılaştırma komutlarını ele almalıyız.
Kı Komutları:
X, CPY
Karşılaştırma kelimesinin İngilizce karşılığı “to compare”'dir ve bu kelimeden makine dilindeki CMP, CPY ve CPX komutları türetilmiştir. Burada karşılaştırılacak eleman akümülatör olduğu zaman CMP, X-Register'i olduğu zaman CPX ve de Y-Register'i olduğu zaman CPY kullanılır. Birkaç örnekle konuya daha açıklık kazandırabiliriz:
CMP $FF
Satırı akümülatörün değerini $FF sayısı ile karşılaştırır. Burada dolaysız adresleme kullanılmıştır ve komut bu haliyle 2 bayt'lıktır. Aynı adresleme CPX ve CPY komutları için de kullanılabilir.
CPX $3000
satırı ise X-Registeri'ni $3000 adresinin içeriği ile karşılaştırmaktadır. Burada kullanılan mutlak adresleme diğer karşılaştırma komutları içinde geçerlidir ve bu şekilde 3 bayt kaplarlar,
CPY $A8
satırı ise Y-Registeri'ni bir sıfırıncı sayfa adresi olan $A8'in değeri ile karşılaştırır ve 2 baytlıktır. CPX ve CPY için olan tüm adresleme çeşitleri yukarıda sayılanlardır. CMP için mevcut diğer yöntemlere ise daha sonra değineceğiz, fakat şimdi gelelim karşılaştırma sonuçlarını nereden öğreneceğimize. Sonuçların tekrar akümülatöre veya registerlerden herhangi birisine yazılması mantıksız olacağı için bu iş için yine statü registerindeki üç tanıdık bayrak (flag) kullanılır: N-Bayrağı (Negatif Flag), Z-Bayrağı (Zero Flag) ve Carry Bit. Sonuçların gösterimi şu şekilde olur: 1) Register değeri (X, Y veya akümülatör) karşılaştırılan değerden büyükse Carry Bit = 1, N- ve Z-Bayrağı = 0 olur. 2) Register değeri karşılaştırılan değere eşitse Carry ve Z-Bayrağı = 1, N-Bayrağı = 0 olur. 3) Register değeri karşılaştırılan değerden küçükse N-Bayrağı = 1, Z-Bayrağı ve Carry = 0 olur. Yukarıda anlatılanlar bir şema halinde Resim 2'de gösterilmiştir. Compare komutlarının en yaygın kullanım alanı dallanma operasyonlarıdır ve genellikle kernaldaki CHRGET rutiniyle bir bütün halinde kullanılırlar.
4990 PRINT "A LIVING "
5000 END
CHRGET kısaltması “get a character” veya “bir işaret al” anlamına gelmektedir. Tamamıyla Sıfırıncı Sayfada yer alan bu rutin makine dilinde oldukça sık kullanılır. Şimdi Ex-Mon'da aşağıdaki satırı yazın.
D 0073 008B
Böylelikle CHRGET rutinin tamamını ekranda görebilirsiniz:
0073
0075
E6 TA
DO 02
0077. E6 7B
0079. AD 2502
C9 3A
007E BO OCA
INC $7A
BNE $0079
INC $7A
LDA $0225
CMP # $3A
BCS
Akümülatör Akümülatör Akümülatör BAYRAK X Veriler X X Veriler Y Y N 0 veya 1 0 1 veya 0 Z 0 1 0 C 1 1 0 Resim 2: 0080 C9 20 CMP #$20 0082 F0 EF BEQ $0073 0084 38 SEC 0085 E9 30 SBC #$30 0087 38 SEC 0088 E9 D0 008A 60 RTS
Yukarıdaki dökümde 0079 no'lu satır sizde daha farklı olacaktır. Bu farklılık $7A ve $7B adreslerinden ileri gelmektedir. Bu baytlar bir gösterge gibi kullanılmaktadırlar (Alçak Bayt = $7A ve $7B = Yüksek Bayt) ve büyük bir ihtimalle bu değer sizde $0225'den farklıdır. Yukarıdaki CHRGET rutinini gelecek ay detaylı olarak ele alacağız. Şimdilik hoşçakalın!
TİCARET