ASSEMBLER-8
Retro bilgisayarBu ay ilk olarak makine dilinin en çok kullanılan iki komutunu ele alacağız: JMP ve JSR. Bunların BASIC dilindeki karşılıkları GOTO ve GOSUB'dır ve işlevleri hemen hemen aynıdır. JMP, İngilizce “Jump to address” kelimelerinden türetilmiştir ve “Verilen adrese atla” anlamına gelmektedir. Her zaman olduğu gibi yine bir örnekle bu komutun kullanılışını inceleyelim: JMP $1500 satırı $1500 adresine bir atlamayı gerçekleştirir. Bu işlem şu şekilde gerçekleşir: Program sayacına verilen adresin alçak ve yüksek baytları yüklenir. Bildiğiniz gibi program sayacındaki değer bilgisayara hangi adresteki işlemi yapması gerektiğini bildirir. Şimdi Ex-Mon'u yükleyip aşağıdaki satırları yazalım. 1400 JMP $1500 Atlamanın gerçekleştiği adreste ise programı durduralım: 1500 BRK G 1400 yazıp programımızı işletir işletmez ekrana registerlerin durumunu gösteren satır gelir. Burada program sayacı $1501 değerine sahiptir zira en son $1500 satırını bilgisayar okumuştur.
Şimdi JMP komutuyla kullanılabilen yeni bir adresleme yöntemini tanıyacağız. Bunun için öncelikle aşağıdaki satırları yazalım. 1400 LDA #$00 1402 LDX #$16 1404 STA $1300 1407 STX $1301 140A JMP ($1300) Bu programa ait başka bir satır da şu şekildedir: 1600 BRK Yine G 1400 ile programı başlattığınızda program sayacının 1601 değerine sahip olduğunu göreceksiniz. Yukarıdaki programda $140A adresindeki değişik yazım şeklini herhalde fark etmişsinizdir. Yeni adresleme yöntemimiz dolaylı adresleme olarak adlandırılmaktadır. Bu yönteme dolaylı denmesinin nedeni atlanmak istenen adresin doğrudan doğruya değil de bir vektör üzerinden bilgisayara bildirilmesidir. Bir vektör birbirini takip eden iki bayt'tan oluşmaktadır ve alçak-yüksek bayt şeklinde istenen adresi belirtmektedir. $1600 adresinin alçak baytı $00'dır ve programımızda bu değer ilk önce akümülatöre yüklenir, daha sonra $1300'e yazılır. Yüksek bayt olan $16 değeri ise X-Registeri üzerinden $1301 adresine yazılır. Tüm bu işlemler sonucunda programımızın atlamasını istediğimiz adres $1300 ve $1301'de yer almaktadır. Artık $1300 vektörünü gösteren JMP komutu ile atlamamız gerçekleşebilir. Bu yöntem özellikle kernal (işletim sistemi) rutinlerinde oldukça sık kullanılır. Bu arada yine oldukça önemli bir atlama komutu olan JSR'ye değinmeden geçemeyeceğiz. JSR, “Jump to Subroutine” veya “Alt programa atla” anlamına gelmektedir. Burada aynı BASIC'de olduğu gibi bir alt programa atlanmakta ve daha sonra RTS ile geri dönülmektedir (GOSUB-RETURN ilişkisi). JSR komutu bir adrese atlamadan önce geri döneceği adresi hafızada “stack” diye adlandırılan bir bölgeye kaydetmektedir. Bu bölge $0100-$01FF adresleri arasında yer almaktadır. Bu alana değerler yukarıdan aşağıya doğru yerleştirilmektedir ve bu işlem mikro işlemci tarafından yönlendirilmektedir. Ex-Mon'da M 0100 01FF satırını girerek stack'ın (yığın) o anki durumunu görebilirsiniz. Bu alan makine dili programlar tarafından oldukça sık kullanılır ve değerler devamlı değişir. Ex-Mon'da yer alan register göstergesinde ayrıca “Stack Pointer” adında bir bölüm bulunur (SP ile gösterilir). Bu gösterge stack'daki ilk boş adresi gösterir. Şimdi stack'da $01F0-$01FF bölgesinin aşağıdaki şekilde olduğunu farz edelim. 20 00 20 AA C1 FA C0 46 :01F8 E1 19 A7 79 A6 9C E3 Sizin bilgisayarınızda bu değerler büyük bir ihtimalle farklı olacaktır. Altı çizili olan adres stack pointer'ın gösterdiği adrestir. Şimdi aşağıdaki programı yazıp G 1400 ile başlatalım. 1400 JSR $1500 1500 BRK Ex-Mon'un register göstergesi tekrar ekrana gelince M 01F0 01FF ile stack'a bir kez daha göz atalım: :01F0 20 AA C1 FA C0 02 14 46 :01F8 E1 E9 E7 E7 79 E6 9C E3 Yine stack pointer'ın gösterdiği adres altı çizgili olarak gösterilmiştir ve iki bayt sola kaymış durumdadır. Eğik yazılmış değerler ise $1402 adresinin alçak ve yüksek baytlarıdır. C-64'ün stack diye adlandırılan bu bölgesinin kullanımı çok basit bir prensiple gerçekleşir: En son yazılan değer ilk önce okunur. Değerlerin stack'a nasıl kaydedildiğini daha önce belirtmiştik (Resim 1). Bu arada stack pointer (SP) bize o anki stack durumu hakkında bilgi vermektedir. Örneğin $01F4 olsun. Bu demektir ki, $0100-$01F4 arasındaki adresler doludur ve sadece $01F5-$01FF arası kullanılabilir. 6510 mikroişlemci stack kullanımını kolaylaştıracak 6 adet komuta sahiptir. Bunları teker teker ele almadan ön-
GO WITH THE JON STACK
FF IFC
100
TSX ve bunların tümünün “son giren ilk çıkar” prensibine dayandığını belirtelim. PHA: Bu komut ile akümülatörün değeri stack'a yazılmaktadır (Push Accumulator - Akümülatörü kaydet). Bu işlem sırasında SP bir basamak aşağıya iner ($FF'den geri sayar) ve akümülatörün değeri herhangi bir değişikliğe uğramaz. Dolayısıyla statü registerindeki bayraklar da etkilenmez. PLA: “Pull Accumulator” veya “akümülatörü çek”. Burada tamamen yukarıdaki işlemin tam tersi gerçekleşir: Stack'ın en üstündeki değer akümülatöre yazılır. Bu işlem sonucunda stack'da bir baytlık yer açılır ve SP bir artar. Akümülatöre yüklenen değer sıfır veya negatif bir sayı olabileceği için statü registerindeki N veya Z bayrağı değişikliğe uğrayabilir. PHP: Bu komut “Push Processor status” yani “Statü registerini yaz” anlamına gelmektedir. Statü registeri bu şekilde stack'a yazılarak o anki bayrak konumları saklanabilir. PHA'da olduğu gibi SP bir azalır, statü registeri değişmez. PLP: “Pull Processor status” veya “statü registerini al”. Bu komut yukarıdaki PHP'nin tam tersidir ve stack'ın en üst basamağındaki değeri statü registerine aktarır. Burada çok dikkatli davranılmalıdır, zira yanlış bir değe-
Resim 1: Değerlerin Stack'a yerleşmesi
ONE OR ZERO!
rin statü registerine yazılması sonucu bilgisayarımız kilitlenebilir. SP yine bir azaltılır. TSX: Bu komut “Transfer Stack-Pointer into X” kelimelerinden türetilmiştir ve “Stack göstergesini X'e transfer et” anlamındadır. Burada SP herhangi bir değişikliğe uğramazken, X registeri $00-$FF arası değerlere sahip olabileceği için statü registerindeki N ve Z bayrakları değişebilir. TXS: TSX'in tam ters işlevine sahip olan bu komut X-Registerini stack göstergesine aktarmaktadır. Bu şekilde stack'daki istediğimiz bir değeri akümülatöre yükletebiliriz. Yukarıda yer alan tüm komutlar birer baytlıktır. Stack bölgesi devamlı bilgisayar açıldıktan sonra çalıştırılmış Assembler programların izlerini taşıyacağı için bazı durumlarda gereksiz baytların silinmesi gerekebilir. Aşağıdaki program SP'nin gösterdiği değerin altındaki 32 bayt'a sıfır değerini yazmaktadır. 8000 LDA #$00 8002 TSX Stack göstergesi X registerinde saklanmaktadır. 8003 LDY #$20 8005 PHA Stack'a sıfır değerini gönderiyoruz. 8006 DEY 8007 BNE $8005 8009 TXS 32 defa sıfır değeri yazıldıktan sonra X-registerinde sakladığımız eski stack göstergesini gönderiyoruz. 800A BRK Stack ile çalışırken işleri fazla karıştırmamak için PHA-PLA, JSR-RTS gibi komut çiftlerinin sayısına dikkat etmelisiniz. Özellikle stack'ın tam olarak bilgisayar tarafından nasıl yorumlandığını bilmeden TSX-TXS komutlarını kullanmamanızı tavsiye ederiz. Dolaylı adresleme: Stack bölgesini ve stack komutlarını tanıdıktan sonra yazımızın başında kısaca değindiğimiz dolaylı adreslemeye tekrar dönmek istiyoruz. Şimdi bu yöntemi geçen sayıda öğrendiğimiz indeksli adresleme ile birleştirip dolaylı-indeksli adreslemeyi göreceğiz. Aşağıdaki satıra bir göz atalım: LDA ($FA), Y Buradaki parantez işaretleri bize JMP komutunu hatırlatmaktadır ve hemen hemen aynı amaçla kullanılmıştır. $FA ve $FB adresleri vektördür ve buralarda asıl işlenecek adres yer almaktadır. Bu adreslerin şu değerleri aldığını farz edelim: $FA = 01 $FB = 48
$FB = 80 ve Y-registerinde de 5 olsun. Sonuçta vektörümüz $8001'i göstermektedir. Yukarıdaki şekliyle LDA komutunu bilgisayar yorumlarken $8001 değerine Y-registerinin değerini de ilave eder ve $8006 adresini akümülatöre yükler. Bu son öğrendiğimiz adresleme yöntemindeki tek sınırlama vektörün (parantez içindeki sayı) sıfırıncı sayfada olması gerektiğidir. Şu ana kadar öğrendiğimiz komutlardan ADC, CMP, LDA, SBC ve STA bu yöntemle adreslenebilirler. (Resim 2) Dolaylı-indeksli adresleme konusunu kapamadan önce yine bir örnek programı inceleyeceğiz. Bu program tüm ekran değerlerini ($0100'dan başlayan) $E000 adresine yazacaktır. Öncelikle sıfırıncı sayfada iki vektör belirleyelim: $FA/$FB ekran adreslerini ve $FC/$FD transfer edilecek adresleri ($E000 ve sonrası) göstersin. 1000 LDA #$00 1002 STA $FA 1004 STA $FC Bunlar iki vektörün alçak baytları idiler. Şimdi de yüksek baytlar: 1006 LDA #$04 1008 STA $FB 100A LDA #$E0 100C STA $FD Bu şekilde vektörler belirtilmiş oldu. Şimdi her biri 256 bayt olan 4 blok transfer edilmelidir. Blok sayısını X-registerine yazalım: 100E LDX #$04 100F ... Daha sonra Y-Registerine de sayacı (indeksi) yükleyelim: 1010 LDY #$00 Şimdi gerçek taşıma döngüsü başlayabilir: 1012 LDA (FA), Y 1014 STA (FC), Y 1016 DEY 1017 BNE $1012 Y-registeri ilk başta 0 değerine sahip olduğu için DEY komutuyla geri sayacaktır ve bu şekilde ilk blok taşınacaktır. İkinci blok için vektörlerin yüksek baytlarını arttıralım: 1019 INC $FB 101B INC $FD
Bye —
LDA dolaylı X 2 AL 161 6
2 Bi 177
STA dolaylı X 2 Bı 129 6 -
İz dolayıy 2 sı —
dolayıx 2 61 87 6 NVZC
nn ma ls NVZC
— — 2" Et 226 6
dolayıy 2 Fİ NVZC
CUP dolayıx — 2 — 188 6 NZC
6 NZC
PHA — e me
— ie ia
PHP a 1 08 e. —
G0
TSX a 1 BA 186 2 NZ
TXS — 1 SA 154 2 -
Resim 2: Dolaylı olarak adreslenen komutlar
Bu işlemin dört defa tekrarlanması için her seferinde blok sayısını bir azaltmalıyız: 101D DEX 101E BNE $1012 Dolaylı-indeksli adresleme yönteminin daha birçok yararlı kullanım alanı mevcuttur. Yalnız bu yöntem mutlak-indeksli adreslemeye göre biraz daha yavaştır. İndeksli-dolaylı adresleme: Bu son adresleme aşağıdaki şekilde kullanılır. STA (FA, X) Burada vektörün değeri parantez işaretleri arasında belirtilmiştir. Yalnız burada vektör doğrudan doğruya $FA/$FB adres çifti değildir. İndeksli-dolaylı adreslemede vektör verilen değere X-registeri ilave edilerek bulunur. Eğer X-registeri $02 değerine sahip ise yukarıdaki örnekte vektör $FA + $02 = $FC ve $FB + $02 = $FD çifti olur. Sıfırıncı sayfadaki FA-FF adresleri şu değerlere sahip olsun: 00FA 00 04 FA/FB 00FC 00 00FD E0 FC/FD = E000 00FE 10 00FF 80 FE/FF = 8010 Bu şekilde bir vektör tablosu yaratırsak uygun X-registerini kullanarak örneğin akümülatör değerinin tablodaki değerlerden birine yazılmasını sağlayabiliriz. Bu adresleme yöntemi aslında oldukça faydalı olabilir, ancak sadece sıfırıncı sayfa ile kullanıldığı ve sıfırıncı sayfa da oldukça dar kapsamlı olduğu için, kullanım alanları sınırlıdır.
İndeksli-dolaylı adresleme şu komutlarla kullanılabilir: ADC, CMP, LDA ve STA Kursumuzun şu ana kadar olan bölümünün genelinde hemen hemen tüm makine dilleri için gerekli olan temel bilgileri edindik. Gelecek sayıdan itibaren C-64'ün işletim sistemindeki rutinlerden yararlanarak daha büyük program projelerine başlayacağız. Bu aylık