Bu sayfadaki yazılar
Sayfanın metni
Sayfa 18
SİC programında makine dili pro: şu cümlelerle işleme koyabilirsiniz:
10 CH-65 : 20 INT (N/256) 30 LSB — N-256/MSB 40 SYS 4892, CH, LSB, MSB
20 ve 30 numaralı satırlar, maksimumu 65535 olan N değerini her biri 0 ile 255 (dahil) arasında değişen tek byte'lık bir niceliğe dönüştürür. CH değişkeni de N kere yazılacak karakterin ASCII kodunu depolar. SYS komutu bilgisayarın 4892'ye atlayıp, oradaki makine dili programını işleme koymasını sağlar. SYS komutunun ardından gelen ilk parametre, makine dili rutininin başlama adresini (4892'yi) temsil etmektedir. Onu izleyen üç parametre ise, makine dili rutini işleme konmadan önce işlemcinin A sicil, X sicil ve Y sicilinde depolanması gerekli değerlerdir. Bütün bu konulara yabancı olduğunuzu varsayarak, önce başlama adreslerinden ve sicillerden biraz söz edelim. BASIC'te, bir programın dizisel akışını değiştirmek için GOTO veya GOSUB komutlarını kullanırız. Hangi komutu kastettiğimizi ise satır numarasıyla belirtiriz. Yani, bilgisayar GOTO 100 cümlesini işleme koyduğunda, bir sonraki komutu almak için 100. satıra atlar. 100. satırın bilgisayar hafızasında nerede olduğunu bilmeyiz; zaten buna gerek de yoktur. Hafızada 100. satırın yerini bulmak BASIC'in görevleri arasındadır. Nitekim, BASIC'e “yüksek düzeyli dil” denmesinin nedeni de, programcıyı hafızada neyin nerede depolandığını takip etmek gibi basit şeylerden kurtarmasıdır. SYS komutu, düşük düzeyde bir dile inmemize olanak verir. BASIC SYS 4892'yi görünce bir sonraki komut için mikroişlemciyi hafızada 4892 adresine atlatır. İşlemci orada PRINT veya GOTO gibi BASIC cümleleri değil, BASIC çeviricisi programına başvurmadan, kendi başına işleme koyabileceği komutlar bulunacaktır. Birazdan, bu konuda örnekler göreceğiz. SYS komutunun bilgisayar 4892'ye sapmadan önce A, X ve Y sicillerine bazı değerler koyduğunu görmüştük. Siciller, tıpkı el kalkülatörlerindeki hafıza işlevi gibi, mikroişlemci içinde okuma-yazma depolarıdır. C-64'te, BASIC programının SYS komutunu işleme koymadan önce A, X ve Y sicillerinin değerlerini hafızada 780, 781 ve 782 konumlarına POKE etmesi gerekir (Bk. C-64 Programcısının Rehberi, s. 318). C-128'de, kayıt değerleri SYS komutuna dahildir.
MAKİNE DİLİ
Makine diline girmeden önce, size bir akıl verelim: C-64 veya C-128 Programcısının Rehberi'nde (kısaca, PRG'de) 5. bölümü bir okuyun. Bu bölüm assembly dilini ve bilgisayarın iç işleyişlerini gayet güzel özetlemektedir. PRG'ler kitap olarak pek net ve tertipli sayılmasalar da, bir sürü temel ve yararlı bilgi içerirler, bir PRG'nız yoksa, gerçek bir kurcalayıcı sayılmazsınız. Kısacası...
Makine dilinin herhalde en zor tarafları (gerek ikili, gerekse onaltılı sayı sistemi ile) adresleme tarzlarıdır. Assembler programı makine dili programlarını yazmanın içerdiği matematiksel yükü biraz hafifletir, ama tamamen ortadan kaldırmaz. Adresleme tarzlarına gelince, yalnız ve yalnız bol zaman ve pratikle tam olarak öğrenebilirsiniz onları. İsimlerini boş verin. Önemli olan işlevleridir. LDA ($3A,X)'e “endeksli dolaylı adresleme” dendiğini bilmek işinize yaramaz, ama bu komut sonucunda A sicilinin tam olarak nereden yüklendiğini bilmek her şeyi değiştirir. Eğer C-64 kullanıyorsanız, C-128'deki HEX komutunun bir benzerini oluşturmak için 1030. satırı GOSUB 2050 yapmanız gerekli. Ayrıca 64'te 2000'de başlayan satırların eklenmesi gerektiğini de unutmayın. 64'te işe başlamak için: 1. Sicim Yükleyici'yi yukarıda anlatıldığı gibi yükleyip uyarlayın. 2. RUN yazarak Sicim Yükleyici'yi işleme koyun. 3. Makine dili monitör programınızı yükleyip geçin. SİCİM utility'si C-64'te, şimdi bulunduğu adres olan 4892'de genellikle aksayabilir. Çünkü, BASIC programları bazen araya karışmaktadır. Bu tartışmada yalnızca programın hafıza içindeki durumuna bakacak, işleme koymaya çalışmayacağız. Programı C-64'te de kullanılabilecek biçimde harekete geçirme çarelerine ise daha ileride bir göz atarız. C-128'de, Sicim Yükle! yazıp sonra da girerek (eğer değişiklik yapmadıysanız, F8'e basmanız gerekli), SİCİM utility'sini incelemeye başlayabilirsiniz. Nereden başlayacağız? Rutinin hafızaya 4892'den ($131C) itibaren yüklendiğini biliyoruz. Bu konumdan disassemble işlemine başlayalım. Önce D 131C (ya da monitörünüzde geçerli olan disassemble komutunu) yazın. SİCİM rutinin ilk komutları
JMP $1324 EOR ($48,X) 91 EOR $E021, Y
O meçhul 299 komutu ilk bakışta aklınızı karıştırabilir. Bu program gerçekten işleme konabilir midir? Bu rutinin ne işe yarayacağı konusunda ilk ipucunu JMP komutundan alıyoruz. Bu komutla, işlemci koşulsuz olarak adres $1324'e atlamaktadır. Böylece EOR (dışlayıcı-OR) komutlarıyla meçhul komut açıklığa kavuşuyor. O bitler muhtemelen gerçekten komut değil de, yalnızca veri değerleridir. Bilgisayar onları işleme koymaz. Doğruca üzerlerinden atlar. Bu varsayımı doğrulamadan önce disassembly işlemine devam edelim. JMP komutu $1324'e gitmiş olduğu için, bu sefer parçalamaya oradan başlıyoruz. Şimdi karşımızdaki gerçek bir programa benziyor. Bunu nasıl anlayabiliriz? Tecrübeli olmak işe yarar tabii, ama her şeyden önce, burada meçhul bit yok. Ayrıca, adres $FFD2'ye yönelik bir takım JSR talimatları görülüyor. Bu adreste, programın içkin bir parçası olan Kernal rutinlerinden biri bulunuyor. Kernal rutinleri her an kullanıma hazır makine dili rutinlerinden oluşur ve makine dili programlarında sıkça geçer. Şimdi, önce 97. sayfadaki Ekran (Dump?) 1'e bir göz atın. Bu tabloda, adres $133B'de bir RTS komutu görüyoruz. RTS komutu, bir altrutinin sonundaki BASIC RETURN cümlesine eşdeğerdir. Bunun SİCİM programının en son komutu olması da mümkündür.
Klavyeyle gezinmek için ← ve → tuşları.
Sayfa 19
Programın gerçekten sonuna gelip gelmediğinizi anlamak için, BEQ ve BNE (eşitse sap ve eşit değilse sap) komutlarına bakın. Sapma komutları, koşullu atlama komutlarıdır. İşlemcinin statü sicilindeki flag'ların set ya da reset edilmiş olmasına bağlı olarak program sapar. Sapma komutlarından hiçbirisi RTS komutunun bulunduğu adresin ilerisindeki adreslere gitmemektedir. Demek ki, RTS gerçekten de programın sonudur. Ayrıca, Sicim Yükleyici'nin hafızaya 32 bit sokmuş olduğunu ve $133B'deki RTS'nin 32 bit olduğunu hatırlarsanız, programın sonuna vardığınızı anlamanız güç olmaz! Programı parçalamak mesele değildir. Ama parçalardan bir anlam çıkarmak zor olabilir. Burada da tecrübe işe yarar. Fakat şu küçük rutini yorumlamak o kadar zor olmasa gerek. $1324'ten başlayarak ilk iki komutu alın:
CPX # $00 BEO $132E
İlk komut X-sicilini sıfırla karşılaştırmaktadır. Eğer X-sicili sıfıra eşitse işlemcinin Sıfır flag'ı set, değilse reset olacaktır. Sıfır flag'ı set olursa, BEQ (sıfıra eşitse sap) komutu $132E'ye atlar.
BASIC çağrı programımızın ve Y sicillerine değerler yerleştirdiğini görmüştük. Eğer X sicili sıfırdan büyük bir değerle başlıyorsa, program $1328'de şu komutları yerine getirecektir:
XxX
JSR $FFD2 DEX
BNE $1328
Bu, BASIC'teki FOR-NEXT döngülerine denk düşmektedir. $FFD2'deki altrutin çağrılır, X sicili eksiltilir ve eğer sıfır değilse BNE (sıfıra eşit değilse sap) komutu programın tekrar $FFD2'ye dönmesini sağlar. Böylece, $FFD2 X kere, yani X sicilindeki ilk değer kadar çağrılır. X sıfıra eşitlendikten sonra, adres $132E'deki şu komutlar yerine getirilir:
CPY $00 BEO $133B
Eğer Y-sicili sıfırsa, rutin adres $133B'deki RTS'ye, yani programın sonuna atlar. Y sıfır değilse, $1332'den başlayan şu komutlar yerine getirilecektir:
JSR $FFD2 DEX BNE $1332 DEY BNE $1332
Bunlar içiçe FOR-NEXT döngülerine tekabül etmektedir.
FOR Y-? TO ? STEP -1 FOR X-255 TO O STEP -1 GOSUB $FFD2 NEXT X NEXT Y
X-sicili maksimum değerinden (255) sıfıra indirilir, sonra da Y-sicili eksiltilir. X gene 255'ten dönerek sıfıra iner ve Y eksilmiş olur. Bu, Y sıfıra ininceye kadar sürer. Sonra, $1339'daki son BNE komutu atlanır ve son RTS komutuna varılır ki, bu da BASIC'e dönmektedir.
KERNAL RUTİNLERİ altrutin CHROUT ya da BSOUT diye adlandırılan bir Kernal rutinidir. Bu rutinin tanımını PRG'nizde bulacaksınız. Bu programda, CHROUT (akümülatör diye de adlandırılan) A sicilindeki hareketlerin değerini alıp ilk uygun konumda ekrana vermektedir. Yani CHROUT sizi cursor konumunu gelişmelere paralel olarak değiştirme ve karakteri ekranda hangi adrese vereceğinizi saptama sıkıntısından kurtarmaktadır. Hatırlayacağınız gibi, BASIC çağrı programımız print edilecek karakterin değerini A-siciline yüklemişti. Ayrıca, print edilecek sayıyı X ve Y sicillerine yüklediğini görmüştük. SİCİM utility'si önce $FFD2'yi X kere çağırmış, sonra da içiçe X-Y döngüsünü Y kere tekrarladı. İçiçe X-Y döngüsünün her geçişinde $FFD2 256 kez çağırılarak X 255'ten 0'a indi. Böylece, SİCİM utility'si belirlenmiş olan karakteri tam istediğimiz gibi (X * 256 Y) kez print etmektedir. Kernal rutinlerini öğrenmek başka programları parçalamakta da size yardımcı olabilir. Bu rutinler makine dilinin en yorucu işlemlerine kolay bir çözüm getirdikleri için yaygın olarak kullanılmaktadır. PRG'lerde Kernal rutinleri her yönüyle tanıtılmış ve örnekler verilmiştir. Sıra $131F ile $1323 arasında gördüğümüz veri karakterlerine geldi. Bunları yorumlamak için, M 131F 1323 yazın. Ekran Dump 1'de de gördüğünüz gibi, bunlar bu yazının alınmış olduğu derginin ismine tekabül ediyor. (Eğer C-64 monitörünüz ASCII display vermiyorsa, veri bitlerinizi kendiniz çevirmek zorundasınız) Bu veri bitleri SİCİM utility'sinde kullanılmamıştır, ama çoğu makine dili utility'si bu şekilde düzenlenir. Programın başında bir veri depolama alanı bırakıp, bir JMP komutuyla bu verileri atlamak sık rastlanan bir uygulamadır.