Merhabalar, atari yazı dizisinin 3. yazısıyla yeniden beraberiz.Geçen yazıda registerlardan bahsetmiştik ve temel 6502 kodlarını görmüştük. Bu yazıda ise görmediğimiz registerları, flagleri ve adresleme modlarını görelim.
Öncesinde TIA registerlarından ve memory için kullandığımız X,Y ve A registerlarından bahsetmiştim. Şimdi, diğer registerlarla devam edelim:
Program Counter: Programın çalıştıracağı bir sonraki komutu işaret eder. Program counter, program çalışırken otomatik olarak değişir. Programcıya bağlı olmasa da; program counter değeri bir subroutine' e, bir banch’ten başka bir banch’e geçişle ya da bir routine’den dönüş yapılarak değiştirilebilir. Counter değeri 16 bitliktir.
Stack Pointer: Mikroişlemci, stack kullanmamıza da imkan sağlıyor. Hafızanın, $0100 ve $01FF arası, yani decimal olarak 256 bytelık bir kısmı stack için ayrılmıştır. Stack pointer ise stackte kullanabileceğimiz, boş olan bir sonraki hafıza konumunu gösterir. Stackte push yapıldığında stack pointer bir azalırken, pop/pull yapıldığında ise bir artar.
Processor Status: Processor Status, genellemek gerekirse, yapılan aritmetik işlemlerin sonucu olarak ortaya çıkan yan etkileri gösterir. 8 bitlik olan bu registerın 7 bitini kullanırız ve bu 7 bitin her biri farklı bir anlama gelir ve bu bitler flag olarak adlandırılır.
Carry Flag : Adından da anlaşılacağı üzere carry flag, toplama veya shift(kaydırma) işlemleri sonucu ortaya çıkan “elde var 1” meselesinin register üzerinde gösterilmesidir. Programcı, isteği üzerine bu flag’ i 0’a veya 1’e eşitleyebilir. SEC (Set Carry Flag) ve CLC (Clear Carry Flag) komutları bu işler için kullanılır. Bu komutlar argüman almaz.
Zero Flag: Son operasyonun sonucu 0 olduğunda 1’e eşitler.
Interrupt Disable: Amacı ‘set’ edildiğinde herhangi bir girdinin (input) mikroişlemcinin yaptığı işlemleri durdurmamasıdır. SEI komutu bu flag i aktif etmek için kullanılırken, CLI ise temizlemek için kullanılır.
Decimal Mode: Decimal yani onluk mod aritmetik işlemlerin onluk tabanda yapılmasını sağlar. SED (Set Decimal Flag) ve CLD (Clear Decimal Flag) komutları ile sırasıyla aktive ve deaktive edilir. Break Command: BRK (Break) komutu kulanıldığında aktif edilen flag’tir. Break komutu içinde bulunduğu fonksiyonun bitirilmesini sağlar.
Overflow Flag: Toplama işlemi sonucu ortaya çıkan sayı mevcut bitlerle gösterilemeyecek bir sayıysa overflow oluşur. Örneğin, 5 bitle gösterilen iki sayıyı toplamaya çalışalım: 19 + 25 = 44 Fakat 5 bitle gösterebilecek “overflow flag”imizin en büyük değeri 31’dir. 44’ü 5 bitle gösteremeyiz; yani overflow oluşur. Mikroişlemci, çözüm olarak oluşan sayının son 5 bitini sonuç olarak alır ve sonrasında “overflow flag”ini 1’e eşitler.
Negative Flag: Yapılan aritmetik işlemin sonucu negatif ise “negative flag” aktif edilir.
Flagler ve registerlarla işimiz bittiğine göre, adres modlarıyla devam edelim: 6502 işlemcisinin “address bus”ı 16 bittir. Yani diyelim ki 65536 bytelık bir memory ye sahibiz. Byteları hex olarak ifade ediyorduk. Bu da demek oluyor ki kullanacağımız adresler $0000-$FFFF arasındadır. Memory nin belirli bir bölgesinden bilgi okurken ya da aynı şekilde belirli bir bölgesine data kaydederken bir adres vermek zorundayız. Farklı komutlarda (mnemonic) kullandığımız bu adresler farklı söz dizimleri şeklinde ifade edilebilir:
Absolute Addressing:
Adresin direkt verildiği durumdur. 2 bytelık yani 4 basamaklı bir hex parametre olarak verilir. Örnek olarak: STA $b103.
Kullanmamız gereken memory lokasyonunu her zaman tam olarak bilemeyiz ve bunun bir değere bağlı olması gerekebilir. Bu durumlar için de “Absolute Addressing”i kullanırken X veya Y registerlarını da kullanabiliriz. Şöyle ki:
LDA #$24
LDX #$53
STA $0200,X ; A’nın değerini 200+03’de yani 0203’de sakla.
Zero Page Addressing: Zero page addressing, “absolute addressing”e benzemek ile birlikte temel farkı parametre olarak verdiğimiz addressing tek byte olmasıdır. Bunun sebebi ise, “zero page addresing”de memory nin $00 - $ff arasındaki boşluğuna erişebiliyor olmamızdır. Tahminimce, “zero page” kavramı da her 100 byte ın bir ‘page’ olarak adlandırılmasından geliyor ki bir bilgisayar mühendisi de doğası gereği indekslemeyi 0’ dan başlatır. Argüman olarak tek byte aldığı için daha hızlı çalışır ve assemble edildiğinde daha az yer kaplar. “Absolute Addressing”i registerlar ile kullanabildiğimiz gibi “Zero Page Addressing”i de kullanırken X veya Y registerlarını kullanabiliriz. Şöyle ki: LDA #$24 LDY #$03 STA $A4,Y ; A’nın değerini A4+03’de yani A7’de sakla.
Immediate Addressing: Immediate Addressing ise memory den değer okumak yerine direkt bir sayı vermekte kullanılır. Örneğin;LDA $02 yazarsak A’ya memory nin 02’deki değeri neyse onu verecekken LDA #$78 yazarsak A’ya direkt olarak 78 değeri verilecektir. Yani, ikinci yazdığımız bir “Immediate Addressing”dir.
Implicit Addressing: Aslında bir addressing olmama durumudur. Increment (INX,INY) veya decrement (DEX,DEY) komutları gibi komutlar parametre olarak bir memory adresi almak zorunda değillerdir. Yaptıkları tek şey verilen register ı bir arttırmak veya bir azaltmaktır.
Indirect Addresing: Indirect Addressing ise kullanımı ve kavraması biraz sıkıntılı olmasına rağmen en çok işe yarayan addressing modudur. Indirect address parametre olarak bir absolute address alır, sonrasında o adrese gidip kullanacağı adresin son byte ını bulur ve sonrasında memory nin bir sonraki byte ından ilk byte ı alır. Tamam karışık geldi biraz. Hemen bir örnek yapalım.
LDA #$01
STA $f0
LDA #$02
STA $f1
JMP ($00f0)
Eveet sevgili atariseverler, ilk yazımla başlayan atari yolculuğumuz bu yazımla son buluyor. Sizlere bu yazı dizisinin atari konusunda donanımsal ve yazılımsal olarak genel bir bakış açısı kazandırdığını düşünüyorum. Umarım bu yazı dizisi sizleri atarinin heyecan verici dünyasına dahil etmiştir. Görüşmek üzere.
Kaynaklar: