ASSEMBLER-5

Kursumuzun şu ana kadar olan bölümünde ele aldığımız makine dilinin temelini oluşturan ikilik ve onaltılık sayı sistemlerindeki aritmetik işlemler oldukça başımızı ağrıtmıştı. Bu işlemlerle bir müddet daha uğraştıktan sonra programlarımızda C-64'ün işletim sistemindeki (kernal) rutinleri kullanıp örneğin en basitinden makine dili ile ekranın herhangi bir bölümüne istediğimizi yazabileceğiz. Fakat şimdi tekrar kaldığımız yere dönelim ve makine dilinde çıkartma işleminin nasıl yapıldığını görelim. “Subtract with Carry” (Carry ile birlikte çıkart) veya kısaca SBC komutu makine dilinde çıkartma işlemlerinde kullanılır. Aynı ADC'de olduğu gibi burada da akümülatörün değeri ele alınır ve sonuç tekrar akümülatöre kaydedilir. Fakat SBC'de farklı ve daha karışık olan tek unsur Carry'nin kullanılışıdır. Biz burada Carry'nin kullanılışına detaylı olarak değinmeyeceğiz; karşılaşacağımız sorunlarda ise SEC (Set carry) komutunu kullanacağız. SEC ile Carry'nin değeri 1 yapılmaktadır.

Önemli Not: Herhangi bir toplama işleminden önce muhakkak CLC ile Carry'yi temizleyin. Aynı şekilde yine herhangi bir çıkartma işleminden önce SEC ile Carry'nin “1” değerini almasını sağlayın.

Şimdi iki örnekte yukarıda gördüklerimizi inceleyelim. Öncelikle bir 8-Bit çıkartma: $1300'deki SAYI1'den $1400'deki SAYI2'yi çıkartalım ve sonuç $1500'e yazılsın.

1200 CLD
1201 SEC
1202 LDA $1300
1205 SBC $1400
1208 STA $1500

Yukarıda da görüldüğü gibi SBC mutlak veya dolaysız olarak (Örneğin SBC #$40) adreslenebilir. Dolaysız olarak adreslendiğinde komut iki bayt, mutlak olarak adreslendiğinde ise 3 bayt işgal etmektedir. SEC ise daha önce tanıştığımız CLC gibi tek baytlık bir komuttur. İkinci örneğimiz ise bir 16-Bit çıkartmadan oluşmakta. Programa geçmeden önce belleğin dört baytı aşağıdaki şekilde düzenlenmelidir:

1300 SAYII Alçak Bayt
1301 SAYII Yüksek Bayt
1400 SAYI2 Alçak Bayt
1401 SAYI2 Yüksek Bayt

Sonucu yine $1500 ve $1501'e yazalım.

1200 CLD
1201 SEC
1202 LDA $1300

ANIL GÜL

1205 SBC $1400
1208 STA $1500

Program bu haliyle iki sayının alçak baytlarını birbirinden çıkartmakta ve $1500'e kaydetmektedir.

120B LDA $1301
120E SBC $1401
1211 STA $1501

Bu şekilde iki sayının yüksek baytlarını da birbirinden çıkardıktan sonra görevimiz tamamlanmış oluyor. SBC komutu ADC ile aynı bayrakları (Statü registeri) etkilemektedir.

Bir program projesi:

Şimdi öğrendiklerimizle ilk geniş kapsamlı programımızı geliştirebiliriz. Bu program bize iki açıdan yararlı olacaktır: 1) Şu ana dek tanıdığımız komutları birbirleriyle kombine etme imkânına sahip olacağız. 2) BASIC ve Assembler programlarını birbirine bağlamada oldukça sık kullanılan bir yöntemi göreceğiz. Özellikle bu ikinci konu birçok kişi tarafından yeteri derecede bilinmemektedir. Assembler rutinlerini BASIC programların içinde kullanmanın birçok yöntemi vardır ve bu yöntemlerin hepsine sırası geldiğinde teker teker değineceğiz.

Program: Aritmetik dizinin toplamı,

Ne X-Reg

İs m

Carry'nin silinmesi

16-Bit-Toplama

Toplam * son eleman

Yeni

Carry'nin silinmesi

16 Bit - Toplama

Son eleman * D farkı

Yeni son Eleman

X-Register - 1

A: Programımızın akış diyagramı.

Birçoğumuz SYS komutunu oldukça sık kullanırız. Örneğin “POKE 214,Satır No.” ve “POKE 211,Sütun No.” komutlarının ardından yazacağımız “SYS 58640” ile kursorun pozisyonunu belirleyebiliriz. Aslında burada yaptığımız iş bilgisayarın belleğinde bulunan makine dili bir programı işletmekten başka bir şey değildir. Burada 58640 programın başlangıç adresidir ve SYS'yi Basic'teki GOTO komutunun bir benzeri olarak düşünebiliriz. Dolayısıyla SYS komutunu kullanarak Assembler programları çalıştırmak pek zor değildir. Esas sorun Assembler programın kullanacağı parametrelerin kullanılmasında yatmaktadır. Bu sorunun en basit ve en yavaş çözümü değerlerin Alçak ve Yüksek Baytlar şeklinde belli adreslere POKE edilmesi ve daha sonra makine dilinde yazılmış programca okunmasıdır. Şimdi örneğimizde bu yöntemi kullanacağız.

Örnek programımızda birçoğumuzun yakından tanıdığı bir aritmetik diziyi ele alacağız. Eğer “A” ilk eleman, “D” fark ve “N” ise eleman sayısını belirtirse bu tür bir dizinin toplamı şu şekilde olur: S= A + (A + D) + (A + 2*D)

İlk on doğal sayının toplamı yukarıdaki diziye bir örnektir:

Szl14243444546474849-410

Burada 1 ve N=10'dur. Yukarıdaki örnekte S toplamının 55 olduğunu kolaylıkla hesaplayabiliriz, fakat eleman sayısı çoğaldığında iş oldukça yorucu bir hale gelir. Her ne kadar bu işi yapabilen bir formül (Gauss Formülü) mevcut ise de biz burada herhangi bir formül kullanmayacağız. Programımız kısaca 1'den N'e kadar olan tamsayıları toplayıp sonucu bize bildirecek. Bu sonuç 16-Bit bir sayı olduğu için 32767'den büyük olamaz. Dolayısıyla N için sadece 1 ile 255 arası değerler sözkonusudur (Neden 255 olduğunu program tamamlanınca deneyerek görebilirsiniz). N sadece 1 bayta ihtiyaç duyduğu için bunu $1300'e kaydedebiliriz. A ve D'nin değerleri 1'dir, fakat bunlar da ileride programda değişiklik yapılabilmesi için 16-Bit'lik sayılar olarak hafızaya kaydedilir. “A” değişkeni alçak ve yüksek bayt şeklinde $1310/1311'de, “D” değişkeni ise aynı şekilde $1320/1321'de saklanır. Sonuç ise $1400/1401'de yer alacaktır. Makine dili programımızın ise başlangıç adresi de $1200'dür.

Bayt | — Kod Etkilediği | A*resleme İsayısı|he — dec | bayraklar ADC dolaysız. |2 69 10512 mutlak 3 6D CLC |yok- 1 18 24 (2 O-c SBC |2 absolut 3 ED 237|4 SEC |yok 1 38 56 |2 |LC BEO |relatif 2 FO 2 Değişiklik yok BCC |İrelatif 2 90 2 Değişiklik yok 2 BO 2 Değişiklik yok BM |relatif 2 30 2 iklik yok. BPL |relatif 2 10 2 iklik yok. 2 60 2 Değişiklik yok BVS |relatif 2 70 2 Değişiklik yok *1 dallandırmak 42 sınırın artması halinde

A2: Son öğrendiğimiz 11 komut.

Öncelikle Basic çağrı programıyla biraz ilgileneceğiz. Yalnız hemen şunu belirtelim: POKE, PEEK ve SYS komutlarında kullanacağımız değerler yukarıda belirtilen adreslerin desimal karşılıklarıdır.

10 REM **** ARİTMETİK BİR DİZİNİN TOPLA-
MI ***
20 POKE 5120,0 : POKE 5121,0 : REM SONUÇ AD-
RESLERİNİN SIFIRLANMASI
30 PRİNT CHRS$(147) CHR$(17) CHRS(17)
40 INPUT “ELEMAN SAYISI N-”;N
S0 IF OR N>255 THEN PRİNT
#N< -255”: GOTO 40
60 POKE 4864,N :REM N'NİN KAYDEDİLMESİ
70 POKE 4880,1:POKE 4881,0: POKE 4896,1: PO-
KE 4897,0: REM A VE D'NİN KAYDEDİLMESİ
80 SYS 4608: REM MAKİNE DİLİ PROGRAMININ
ÇAĞRILMASI
90 M-PEEK(5121):L « PEEK(5120): REM SONU-
CUN OKUNMASI
100 E— 256*M 4 L:PRİNT CHR$(17) CHR$(17)
110 PRİNT “ ILK “N” TAMSAYININ TOPLAMI:
120 END
Şimdi artık makine dili programımıza geçebiliriz. Bu-
nun için lütfen Resim 1'deki akış diyagramına bakın.
Programımızın hazırlık safhasında eleman sayısını X
registerine yükleyeceğiz ve toplama işlemi gerçekleşece-
ği için Carry Bit'ini temizleyeceğiz. Monitör programı-
nızı yükleyip A1200 yazdığınızda başlangıç adresimiz olan
$1200 ekranda gözükecektir. Artık programı yazmaya
başlayabiliriz (Her satırdan sonra RETURN'e basmayı
unutmayın).
1200 LDX $1300
1203 CLC
Şimdi gelecek olan altı satırda ise bir sonraki eleman
© ana kadar olan toplama eklenecektir. Başlangıçta
$1400/1401 boştur ve $1310/1311'de ise başlangıç ole-
manı olan A— | yer almaktadır. Aşağıdaki döngü işle-
meye başladığında ise $1400/1401'de o ana kadar olan
toplam ve $1310/1311'de ise son eleman bulunacaktır.
1204 LDA $1400
1207 ADC $1310
120A STA $1400
Bu satırlarda alçak baytlar toplanıp $1400'e kaydedil-
miştir.
120D LDA $1401
1210 ADC $1311
1213 STA $1401
Böylelikle yüksek baytlarda toplanmış oldu. Bundan
sonra dizinin o anki son elemanını bir önceki elemanı D
ile toplayarak elde etmeliyiz. Bu işlemin Basic'deki kar-
As A4 D'dir. Yine bir 16-Bit toplama yapacağı-
mız için CLC komutunu kullanmalıyız.
1216 CLC
1217 LDA $1310
I21A ADC $1320
121D STA $1310
Bunlar alçak baytlar idi. Şimdi de yüksek baytlar:
1220 LDA $1311
1223 ADC $1321
1226 STA $1311
X- Registerini | eksilttikten sonra O olup olmadığını
kontrol ederek N tane elemanın toplanıp toplanmadığı-
nı anlayabiliriz.
1229 DEX
122A BNE $1203
Eğer tüm elemanlar toplanmamış ise döngünün başı-
na dönülecektir. Döngü N defa tekrarlandıktan sonra Ba-
sic'e dönüş şu şekilde sağlanır:
122C RTS
Yazdığımız bu makine dili programını diskete şu şe-
kilde kaydedebilirsiniz: S “Program Adı'',1200,122D,08
Genelde tüm monitör programları bu kalıbı kullanır,
fakat bazıları virgül işaretine gerek duymaz. Bu nedenle
farklı bir monitör programı kullanıyorsanız biraz dene-
me yapmanız gerekecektir. Kaset kullanıcıları ise Yuka-
**08”' yerine yazmalıdırlar. Yalnız birçok mo-
nitör programı disket ile çalışmak üzere hazırlanmıştır

ve teybi bir kayıt cihazı olarak kabul etmezler. Bu gibi durumlarda kaset kullanıcıları için başka bir monitör programını denemekten başka çare kalmamaktadır. Makine dili programı kaydettikten sonra tekrar yüklerken monitör programına ihtiyacımız olmayacak. Sadece LOAD””,8,1 (veya kaset için ,1,1) yazdıktan sonra Basic başlangıcını normale döndürmek için NEW yazıp RETURN'e basmalısınız. Böylelikle biraz önce yazdığımız Basic programı da yükleyebiliriz. Assembler programını oluştururken A ve D'yi değişken olarak tutmuştuk. Bu nedenle isterseniz Basic programın satırındaki alçak ve yüksek baytları değiştirerek farklı diziler elde edebilirsiniz (1+2+3+4+5+6... gibi). Burada dikkat etmeniz gereken tek unsur ise S toplamının 32767'nin üstünde olmamasıdır. Yalnız hemen şunu belirtelim: Şu ana kadar makine dilinin gerekli temel özelliklerini öğrendik. Bu bilgiler doğrultusunda toplamın 32767'den daha büyük değerler almasını sağlayabilirsiniz. İşte size bir ipucu: Neden yukarıda iki bayt halinde yazdığımız sayılar üç veya daha fazla bayt ile gösterilmesin? Veya yukarıda belirttiğimiz maksimum sınır değeri aşılırsa makine dilinin hangi özelliği ortaya çıkar? (Statü registerinin V-Bayrağı ile ilgili bölüme bir göz atmanızı tavsiye ederiz.)

Branch komutları:

6510 mikroişlemcisi 8 farklı dallanma komutuna sahiptir. Biz bunlardan sadece BNE'yi tanıyoruz. Bu Branch (Branch — dallanma) komutlarının tümü statü registerinin bayraklarını kontrol etmektedir. BNE ve BEQ komutları Z-Bayrağına bakmaktadırlar. Eğer Z-Bayrağında sıfır değeri varsa BNE istenen adrese dallanmaktadır. BEQ (Branch if equal Zero — eğer sıfıra eşitse dallan) ise aynı işi Z-Bayrağı sıfıra eşit ise yapmaktadır. BCC ve BCS ise statü registerindeki C-Bayrağı yani Carry Bit'i ile ilgilenmektedirler. BCC'nin karşılığı “Branch if Carry Clear”, yani “eğer Carry boş ise dallan”dır. Carry Bit'inin “1” değerini aldığı durumlarda ise BCS (Branch if Carry set) komutu devreye girmektedir ve dallanmayı sağlamaktadır. Yukarıda sıraladıklarımız makine dilindeki en anlamlı ve en çok kullanılan dallanma komutlarıdır. Şunu rahatlıkla söyleyebiliriz ki, programcılar tarafından kullanılan dallanmaların %90'ı bu şekilde sağlanmaktadır. R.Mansfield Amerika'da oldukça satılan “Machine Language for Beginners” adlı kitabında okuyucuları programlarında BPL ve BMI komutlarını kesinlikle kullanmamalarını öğütlüyordu.

Aslında bu komutları kullanmamak için bir sebep yoktur. Birçok sorun BPL, BMI, BVS ve BVC ile kolaylıkla çözümlenmektedirler. Sayıların bilgisayar tarafından nasıl yorumlandığını bildikten ve bu dallanma komutlarının fonksiyonlarını kavradıktan sonra bunları rahatlıkla kullanabiliriz. BMI ve BPL (“Branch on Minus” — “Eğer negatif ise dallan” ve “Branch on Plus” — “Eğer pozitif ise dallan”) statü registerindeki N-Bayrağına göre hareket etmektedirler. Bu bayrak hakkında daha önce bazı bilgiler vermiştik. Şimdi kısaca tekrar ele alalım isterseniz. Eğer bir operasyonda 7. Bit'i 1 olan bir sayı ortaya çıkarsa bu bayrak da değerini almaktadır. Dolayısıyla bu Bit 8-Bit'lik bir sayının işaretidir. Eğer bu Bit “1” değerini alırsa BMI, aksi takdirde BPL ile bir dallanma gerçekleşir. BVS ve BVC komutları da statü registerindeki V-Bayrağı ile ilgilenmektedirler. Eğer bu bayrak “1” değerini alırsa BVS (Branch on Overflow Set) komutu kullanıldığında bir dallanma gerçekleşecektir. BVC ile ise V-Bayrağının 0 olduğu durumlarda dallanma sağlanır. Bu şekilde istersek hesap işlemlerinde kullanılan sayıların 16, 24 veya 32 Bit'lik olmaları sağlanabilir ve böylelikle her seferinde ortaya çıkabilecek en büyük ve en küçük değerleri bulmak için uğraşmayız. Yukarıda tanıdığımız tüm Branch komutları aynı BNE gibi 2 baytlık komutlardır ve özel bir adresleme yöntemi kullanmaktadırlar: Relatif Adresleme. Resim 2'de son öğrendiğimiz 11 komut hakkında bazı yararlı bilgiler yer almaktadır.

Tabii ki 9?

MACERA PESINDE T