Belki de en önemli işlerden biri, interrupt kurulumu yapmak. Interrupt denilen şey, "kesme isteği" olarak çevrilmiş Türkçeye, kesme denilen şey ise, işlemcinin o sırada yaptığı işi bırakıp başka bir adrese zıplamasını sağlayan bir zamanlayıcı. Zx spectrumda saniyede 50 intterupt oluşur.
z80 işlemcide 3 adet kesme modu mevcut. Bunlar IM0 IM1 ve IM2.
Kesme modu 0 iken, kesmeleri bir aygıt kontrol ediyor demektir. Yani genişleme yuvasından takılan bir aygıt olabilir. Bu modda bus'tan bir byte okur ve ona göre hareket eder, bu komut genellikle RSTx komutu olur.
Mod 1 iken işlemci kesme modunu kendi kontrol ediyor demektir ki bu genel olarak servis modu olarak adlandırılır. Zx Spectrumda servis rutini 0x0038 'de tutulmakta, bu adresin özelliği bir byte'lık RST38 komutu ile ulaşılabilinmesi. Basitçe saniyede 50 kere kesme uygulanır, ve bu kesme sırasında RST38 çağrılır. 38h servis rutininde yapılan iki şey var, frames isimli sistem değişkeni bir arttırılır ve klavye okunur.
Mod 2 ise vector jump denilen bir zıplama şekli. Düşük byte databus'tan okunur, yüksek byte ise I yazmacında tutulan değerdir. Yani vektör= I*256+databus . Problem şu ki, zx spectrumda bustan gelecek verinin ne olacağını tutturmak çok zor (floating bus problemi, ula da aynı veri yolunu kullandığı için oradaki değeri ula değiştirebiliyor). Bu durumda IM2 vektörünün nereyi işaret ettiği konusunda 256 farklılık olabiliyor. Bu işi genellikle o rutine bir tablo yerleştirerek çözüyoruz.
Örneğin I yazmacını 254 olarak ayarlayalım. Bu durumda IM2 vektörü 65024'den başlayacak, ve 256 byte'lık bir sapma olabilecek yani 65280'e kadar. (tablomuzu 257 byte olarak hazırlıyoruz)
Buradaki püf noktasını vermek istiyorum, ki bu bilgi bitpazarlarının yeri kadar gizli kalmış bir sırdır, ayarladığımız bu adres zıplanacak olan adres değil, zıplanacak olan adresi gösteren adrestir. Yani Örneğin databus 255 olsun (ki genellikle interrupt oluştuğunda %99 databus 255'tir) ve I ise 254 olsun, IM2 65280'i işaret edecek ve oraya biz ne koyarsak oraya zıplayacak. Örneğin 65280 ve 65281'de FDh FDh (65021) varsa bu durumda IM2 doğrudan 65021'e zıplar.
Ben kendi kullandığım kodu veriyorum:
org 65021
JP 40000 ;interrupt rutininizi 40000'e koyun.
org 32768
di ;interrupt ayarı yapmadan önce kesmeleri kapatalım
ld hl,65024 ;tabloyu oluşturacagız, 65024<->65280 arasında
ld de,65025
ld (hl),253
ld b,e
ld c,e
ldir ;tablo hazır, aralığı 253'lerle doldurduk.
ld a,254 ; kesme rutinini tablomuzu gösterecek sekilde ayarlayalim
ld i,a ; I yazmacı 254'ü gösterdiginde bus'taki degere göre vektör 65024<->65280 arasında kalacakır.
im 2 ; interrupt mode 2 aktif
ei ; interruptlar? açalım
Şimdi buradaki ilk kısımda 257 byte'lık bir FDh tablosu oluşturuluyor, ve interrupt modu o tabloyu işaret ediyor, böylece databusdaki değişmeler sonuca etki edemiyor. Bu kod bir kere çalıştığında artık kesmeler bizim istediğimiz adrese yönlenecek, o adreste de JP 40000 olduğu için her 1/50 saniyede bir 40000 adresine gidilecek demektir.
Interrupt rutini çalıştığında otomatik olarak di çalıştırılır. Yani interrupt rutininden dönmeden önce ei ve ret kullanmayı unutmayın.
Alternatif olarak, eğer 48k için kodlama yapıyorsanız ve FD tablosu için 257 byte harcamak niyetinde değilseniz romdaki FF tablosunu kullanabilirsiniz. 48k Rom'unda 14446'dan başlayıp 15615'e kadar giden devasa bir FF tablosu vardır. Buradaki veriyi kullanarak ve I'yı 59 haline getirerek IM2 zıplama adresini tablo kullanmadan 65535'e dönüştürürsünüz. 65535'e ise 18h (=JR n) yerleştirdiğinizde ve 65535'den sonraki adres 0 olduğu için, romdaki ilk byte olan 243 alınacak ve dolayısıyla -12 geri zıplanacak (JR 243 =-12 göreli zıplar) ve 65524'e düşmüş olacaksınız. Buraya da nihayet kodunuzu yerleştirebilirsiniz. Fakat bu kod 128k'da çalışmayabilir, çünkü o tablo 128k'da 128k editör kodu ile doldurulmuş. +3/+2A'da ise FF yerine 00'lardan oluşuyor. Yani dediğim gibi 48k ile limitli bir opsiyon, fakat ekleyeyim, üst modellerde 48k rom'a dönmek mümkün, programı 48k modunda yükledikleri sürece 128k ve +3'de de çalışacaktır.
Kolay gelsin.