Bu sayfadaki yazılar
Sayfanın metni
Sayfa 55
mı yazmak için birkaç gün uğraşacaktık. Monitör programları adı verdiğimiz C Monitör, Amiga Monitör, Süper Monitör gibi programlar yardımı ile bir ölçüde assembler çalışabiliyoruz. Komutları normal olarak harfler ile giriyoruz. Fakat monitör programları ile çalışırken daha önce de örneğini verdiğimiz (n 50000) gibi programın adresleme işleri ile de uğraşmak zorundayız. Makina dili programımızın arasına bir satır eklemek istersek, monitör programlarında bu iş imkansız denebilecek kadar zordur, işte assembler derleyicilerin yararı burada ortaya çıkıyor. Bizi bir sürü sayı ile uğraşmaktan kurtarıp, dikkatimizi programın listesini hazırlamaktan çok rutinlerimizi geliştirmeye çekiyor.
Artık makina dilinde ilk programlarımızı yazmaya başlayabiliriz. Vereceğimiz örnek programlar gözle görülür bir iş yapmasa da şimdiye kadar gördüğümüz komutları daha iyi kavrayıp, makina dili bilgimizde sağlam bir alt yapı oluşturmaya çalışalım.
İlk örneğimiz belli bir hafıza bölgesini bir byte'lık bir sayı ile doldurmak olacaktır.
"buffer:" label'ının ardından gelen dc.b 0,0,0,0,0,0 gibi ifade ise yine benzetme yapılırsa Basic'deki DATA satırlarına benzetilebilir, "dc" ifadesi satırın data satırı olduğunu ve ".b" ise o data satırının formatının ne olduğunu ifade eder. Örnekteki gibi ".b" ifadesi ise formatın byte olduğunu; yani satırdaki verilerin birer byte'dan oluştuğu anlamına gelir. Bu açıklama sonucunda örneğimizdeki bufferend-buffer = 20 Byte olduğunu söyleyebiliriz.
Şimdi örneğimizi satır satır açıklayalım. SATIR-1: START: MOVE.L #buffer,A0 Burada MOVE komutunu LongWord modunda kullanarak doldurulacak hafıza bölgesinin başlangıcını temsil eden "buffer" label'ını A0 Adres Registerine atıyoruz.
Amacımız, verilerinin bulunduğu hafıza bölgesinin başlangıcını temsil eden buffer label'ını bir adres registeri (A0) üzerinden kullanıp rahat bir işleyiş yapmak. SATIR-2:
Ll: MOVE.B #255,(A0) 255 sayısını doldurma işlemi bu satırda gerçekleşiyor. Move komutunu byte modunda kullanarak, A0 Adres registerinin gösterdiği hafıza bölgesine 255 değerini gönderiyoruz. Bu komut satırı ilk defa işleme girdiğinde, A0 registeri yukarıdaki satırdaki MOVE.L komutu üzerine "buffer" değerindedir ve bağlantılı olarak bu satırdaki komutun etkisi; A0 registerinin bulunduğu hafıza bölgesine atama yapıldığını düşünürsek, buffer'ın gösterdiği hafıza bölgesindeki ilk byte 255 değerini alacaktır. Böylece amacımızın ilk hamlesini yapmış olduk ve buffer'daki ilk byte'ı 255 yaptık. SATIR-3: ADD.L #1,A0 Add komutu, daha önce de gördüğümüz gibi toplama işlemi yapan bir komuttur. Örnekte de A0 adres registerindeki sayıya 1 ekleme işlemi yapıyor. A0 adres registerindeki değerin, bu satıra kadar buffer değerini gösterdiğini düşünürsek ve bu satırda Add komutu etkisi ile değerinin bir sayı arttığını düşünürsek, A0 registerindeki yeni sayı bu komutun icrasından sonra buffer+1 olacaktır.
SATIR-4:
CMP.L #bufferend,A0 İşte Cmp komutuna bir örnek. Bu satırda yapılan iş çok basit. A0 adres registerindeki sayının bufferend label'ının sayı değerine eşit olup olmadığı karşılaştırılıyor.
SATIR-5:
BNE Ll Bir üst satırdaki karşılaştırma işlemi sonucundan eşitlik sonucu çıkmamışsa, icranın Ll label'ının bulunduğu satırdan itibaren devam etmesi gerektiğini ifade ediyoruz. Aslında bizim, son iki satırda kontrol ettirmek istediğimiz şey buffer'dan bufferend'e kadar olan byte'ların 255 değerini alıp almadığı oluyor. SATIR-6:
RTS Cmp komutunun sonucunda, A0 registerindeki sayı bufferend'e ulaşmışsa, bne komutu ardındaki Ll label'ına gitmeyip altındaki komuttan itibaren icra devam edecektir. Tabii bilgisayar burada RTS komutunu görünce de programımızın işleyişi son bulacaktır. SATIR-7 buffer: dc.b 0,0,0,0,0,0,0,0,0,0,0, 0,0,0, 0,0,0,0,0,0 Burası programımızın data satırı. Program işleyişi sırasında tamamı 0 olan değerlerini sırası ile 255 değerine bırakıyor.
SATIR-8: bufferend: Bu satır normalde hiçbir iş yapmaz. Programda tek görevi buffer ile başlattığımız ve 20 adet byte'ın sonunu belirlemek.
Örnek programımızın akışını, eski bilgilerinizi hatırlayarak kavramaya çalışın. Başlangıç için bu mini rutin çok şey ifade etmektedir. Gelecek sayı görüşmek üzere....
ÖRNEK PROGRAM 1 :
1 START: MOVE.L#buffertA0 2L1: MOVE.B #255,(A0) 3 ADD.L#1,A0 4 CMP.L#bufferend.A0 5 BNE Ll 6 RTS
7 buffer: dc.b 0,0,0,0,0,0,0,0,0,0,0.0,0,0,0,0.0,0,0,0 8 bufferend:
Programda amacımız buffer diye adlandırdığınız 20 byte'lık 0 değeri bulunan hafıza bölgesini $ff (decimal=255) değeri ile doldurmaktır.
Bu arada programda kullandığımız birkaç assembler terimini açıklığa kavuşturalım.
Program içinde satır başlarında "START:", "Ll:", "buffer:", "bufferend:" ifadelerini, Amiga Basic'de olduğu gibi label olarak adlandırıyoruz. Anlamı ise hazırladığımız programın, label bulunan satırının markalanmış ve aynı adlı label tarafından anıldığı anlamına geliyor. Programın başka kısımlarında daha önceki komutlara geri dönmek için kullanıyoruz.
SYSTEM FLAGLARININ KOMUT YAPTIĞI N Z V C X HI Büyük ise
- 1 - 1 1
LS Ufak - 0 - - CC Carry - - - - CS Carry 1 - - - 0 - NE Eşit - 1 - - - EQ Eşit ise - 0 - - - VC Overflow - - 1 - - VS Overflow - - 0 - - PL Pozitif 1 - - - - MI Negatif 0 - - - - GE Büyük 1 - 1 - - 0 - 0 - - LT Küçük 1 - 0 - - 0 - 1 - - GT Büyük 0 1 0 - - 1 1 1 - - LE Küçük - 0 - - - 0 - 1 - - 1 - 0 - -5
TABLO 1
Klavyeyle gezinmek için ← ve → tuşları.
Sayfa 54
Merhaba assemblercılar. Siz geleceğin makina dili programcılarısınız. Sabırla çalışıyorsunuz. Ben makina kodunu öğrenmeyi bir tepeyi aşmak olarak yorumluyorum. Bütün dikkatinizi bu sayıdan itibaren vereceğimiz örneklerde toplamalısınız.
Makina dilinin bütün zorluğu yazacağımız programların her satırının icrasını anlama mecburiyeti. Aslında bana sorarsanız, tepeyi aştıktan sonra herkes için makina dilinde yazılmış satırlar basit aritmetik işlemleri gibi gelecektir. Önerim elden geldiğince program satırlarını sıralı olarak düşünmek ve hangi satırın sisteme ve registerlere ne etkisi oluyor, bunları aklında tutmak olmalıdır.
Şimdi bu sayıda bahsedeceğimiz Bcc komut dizisine gelelim. Bu komut ile beraber makina dilinde ilk örneği vermek için gerekli bütün komutları görmüş olacağız. Bcc komutunun açıklamasının bitiminde vereceğimiz örnekler ile şimdiye kadar öğrendiğimiz bütün komutları tekrar ediyoruz. Evet başlıyoruz....
Bcc - BRANCH KOMUTU Branch adı verdiğimiz komutların yaptığı iş, aslında JMP komutu gibi, başka bir yere dallanmaktan başka bir şey değildir. Tek farkı, karşılaştırmalara göre dallanma işlemini gerçekleştirir veya programa branch komutu arkasından devam eder.
Branch komutlarının çalışmasını BASIC'deki IF....THEN komutuna benzetebiliriz. IF komutunu geçen sayıda anlattığımız CMP komutuna ve THEN komutunu da Bcc komutlarına eş değer olarak düşünün.
Branch komutları karşılaştırmaları, system durum flagları ile gerçekleştirirler. Bu flaglar (daha önceki sayılarda gördüğümüz gibi) N-Negatif, Z-Zero, V-Overflow, C-Carry, X-Extend olmaktadır.
14 adet branch komutu yardımı ile system flaglarının bir ya da birkaçını birden kontrol edeceğiz. Komutların listesi TABLO 1'de gösterilmiştir.
Bu arada "Bcc" deyiminin ne olduğunu da anlatalım. Assembler'da Branch komutlarının hepsi üçer harften oluşur. Bcc'deki B harfi branch komutu olduğu ve küçük harfli iki cc harfi yerine yukarıda gördüğünüz 14 modu ifade etmiş oluyoruz.
Tablonun ilk iki harfini B harfinin yanına ekleyerek kullanacağız. Yani BLE, BGT, BNE, BEQ gibi...
Şimdi branch komutlarının modlarını inceleyelim:
Kullanım Modu : BHI label Örnekteki komut, Carry ve Zero bayrakları 1 ise label'ın gösterdiği adresten itibaren devam et; anlamına gelmektedir. Diğer bütün Branch komutları da aynı şekilde tablodaki system flagları doğrultusunda Label'a dallanma yaparlar. Sadece kullanılabilirlik bakımından bir mod daha açıklamakta fayda var.
Kullanım Modu : BHI (A0) Yukarıdaki örneği bu şekilde de değiştirebiliriz. Bu kullanım için daha önceden A0'a label değerini atamış olmamız gerekiyor.
Branch komutlarının ilke olarak nasıl çalıştığını görmek için birkaç örnek verelim. Tabii Bcc komutlarından sonuç almak için CMP komutu ile yaptığımız işlemler doğrultusunda system flaglarını etkilememiz gerekiyor.
1. Örnek : CMP #1,D0 BEQ label Açıklama : Örnekte Beq komutu doğrudan system flaglarından Zero'yu okuyup, değerine göre işlem yapacaktır.
Eğer cmp komutu işleme girmeden önce, D0 data registerinde 1 değeri varsa ve cmp ile biz 1 olup olmadığını sorarsak, sonuçta beq komutunun gösterdiği label'a dallanma olur. Nedeni ise örnekteki cmp komutunun (CMP #1,D0) işleme girdikten sonra Zero flag'ını 0 yapmasıdır.
Fakat cmp komutundan önce D0 registerinde 0 değeri varsa ve cmp komutu ile biz 1 olup olmadığını sorarsak beq komutu label'a dallanma yapmayacak ve program beq'dan itibaren işleyişine devam edecektir.
Aslında örneğimizdeki CMP #1,D0 komutunun etkisi N, Z ve C flaglarına aktarılıyor. Tabii D0'ın ilk pozisyonuna göre flagların değeri değişik oluyor.
Örnek. 1- D0=00000001 olsun, CMP #1,D0 komutu ardından flagların değeri şöyle olur:
N=0 Z=1 C=0 Örnek.2- D0=00000000 olsun, CMP #1,D0 komutu ardından flagların değeri şöyle olur:
N=1 Z=0 C=1 Örnek.3- D0=00000002 olsun, CMP #1,D0 komutu ardından flagların değeri şöyle olur:
N=0 Z=0 C=0 Bu örneklerle, registerlerdeki bir sayıyı, cmp komutu yardımı ile kontrol ettiğimizde ortaya çıkan sonucu system flaglarından nasıl okuyacağımızı görmüş olduk.
Şu ana kadar öğrendiğimiz komutlar ile ufak programlara başlayabiliriz. Diğer 68000 komutlarını da vereceğim örnek programlar içerisinde sırası geldikçe, yerine ve kullanıldıkları yer farklılıklarına göre açıklayacağız. Amacımız, size bir sürü komutu ezberletmek yerine komutları yavaş yavaş örnek programların arasına serpiştirip sindirmenizi kolaylaştırmaktır.
Bu arada program yazma safhasına geldiğimize göre makina dili ile assembler arasındaki farkı ayıralım.
Makina dili programları sayılardan oluşmaktadır. 68000 makina dilinde her komutun iki byte'dan oluşan bir değeri vardır. Bunun arkasında da komutuna göre iki byte'dan sekiz byte'a kadar parametresi bulunur. Assembler dediğimiz kavram ise, programcıları bu sayılar ile uğraşmaktan kurtarıp, bir kısmını açıklamasını yaptığımız komutlar dizisine döndürmüştür. Eğer Assembler dili olmasaydı, programları sayılardan oluşturacak ve bunları girmenin sıkıcılığını yaşayacaktık. Her komutun ilk önce iki byte'lık değerini, sonra o komutun hangi parametresini kullanacaksak o parametrenin değerini bulacak, daha sonra komutun parametresini yazmaya çalışacaktık. Tabii bu sırada bol bol hata yapacak, iki satırlık makina dili programı-
AMIGA ASSEMBLER