Bu sayfadaki yazılar
Sayfanın metni
Sayfa 30
Merhaba Assemblercılar. Yazı dizimize, geçen sayıdaki son örneğimizin açıklaması ile devam ediyoruz. Program örneğimizin ilk iki satırını geçen sayıda anlatmıştık. Şimdi, üçüncü satırı kaldığımız yerden itibaren incelemeye devam edelim.
Üçüncü satıra, hatırlama mahiyetinde bir göz gezdirin. Buradaki Cmp komutunun işlevi şu şekildedir:
Karşılaştırma komutunu (Cmp) kullanarak P harfinin ascii kod karşılığı olan hexadecimal $50 veya decimal 80 değerini, A0 adres registerinde bulunan adresin gösterdiği hafıza adresindeki sayı ile karşılaştırıyoruz. Programımızı düşünürsek; buradaki A0, ilk girişte buffer bölgemizin başlangıcını ifade etmektedir. Bu komut ile biz, ilk byte'ın P harfi olup olmadığını kontrol ediyoruz. Bu adreste duran sayının P olup olmamasına göre işlem sonucundaki etki değişecektir.
Bu işlemin sonucu, bir alt satırda değerlendirilecek.
SATIR-4: BNE L2 İşlemci, bir önceki komutun system flagları üzerinde bıraktığı etkiyi buradan okuyarak durumu inceler ve olumlu bulursa işlem akışı Bne komutundan bir sonraki komut ile devam eder. Yukarıdaki işlemin sonucu olumsuz çıkarsa, Bne komutunun gösterdiği adrese atlama yapılır.
SATIR-5: CMP.B #"E",1(A0) İşlemcinin buraya gelebilmesi için, bir üst satırdaki bne komutundan kurtulması gerekmektedir. Programdaki ikinci cmp komutu ile A0 adres registerindeki sayıya bir değer daha ekleyerek, şu sonuca varıyor:
Bu komut işleme girdiği anda, A0'ın içerdiği değer buffer değeridir. Bu komuttaki 1 (A0) değeri ise buffer+1'i temsil etmektedir. İşlemci, programın ilk turunda buffer+1 adresindeki değerin E harfi olup olmadığını kontrol etmektedir.
SATIR-6: BNE L2 Yukarıdaki işlemin sonucu olumlu ise, yani harf bulunmuşsa bir sonraki komuta, bulunmamış ise L2 label'ına atlama yapılır.
SATIR-7: CMP.B #"R",2(A0) İşlemci buraya kadar geldiğinde, aratma
ÖMER SİNAN POLAT yaptığımız ilk iki harf bulunmuş demektir ve üçüncü harfin R olup olmadığını kontrol ediyoruz. Tabii ki 2(A0) ifadesi, ilk turda buffer+2 değeri taşıyor. Bir başka deyişle; A0'ın içeriğindeki değerin, 2 fazlasını ifade ediyor. Buna ek olarak, iyi huylu Cmp komutu A0+2'ye bakarak R harfi olup olmadığını karşılaştırır. Her zaman olduğu gibi bu işlemin de sonucu bir alt satırda değerlendirilecektir.
SATIR-8: BNE L2 Üçüncü harfin bulunması ile, bne komutu işleyişe bir alt satırdan devam eder. Eğer bulunamazsa L2 'ye atlanarak devam edilir.
SATIR-9: CMP.B #"I",3(A0) Aranacak karakter dizisinin dördüncü ve son harfi olan I'nın P harfinden uzaklığı olan +3'üncü adrese bakılır. Ve sonuç system flaglarına gönderilir.
SATIR-10: BNE L2 İşlemcinin bu satırdaki hareketi şöyledir: Son harf de bulunacak olursa, bir alt satıra git. Bulunmazsa L2'ye atla.
SATIR-11: JMP L3 Bu satırda, artık aratma yaptığımız karakter dizisini bulduk demektir. L3 label'ının gösterdiği adrese atlayarak oradaki RTS ile programdan çıkılır.
SATIR-12: L2: ADD.L #1A0 Programda 4 defa kullandığımız bne komutunun hedefi, işte bu satırdır. Görevi, A0 adres registerindeki değeri bir artırmaktan ibarettir.
SATIR-13: CMP.L A1, A0 Bildiğiniz gibi, programın başında A1 registerine bufferend değerini göndermiştik. Burada da bir önceki satırda yaptığımız işlem sonucu olan A0'ın değeri ile A1'i karşılaştırıyoruz. Amacımız tabii ki aratma yapılan bölgenin sonunun gelip gelmediğini kontrol etmek.
SATIR-14: BNE L1 Burada, üst satırın sonucu değerlendiriliyor. Sonuç olumlu ise (yani A0 ile A1 adres registerlerinin karşılaştırıldıklarında ortaya çıkan işlemin sonucu) program 15'inci satıra gelir ve durur. Böylece kısa programımız aratılan karakter dizisinin bulunamadığı sonucuna varır. SATIR-15: L3: RTS Bu komut programdan çıkışı sağlar.
AMIGA ASSEMBLER
SATIR-16: buffer: dc.b "ABCHG KPOIDFPEGFGDPERIDFfJEH^ETRYREY"
Arama yapılacak hafıza bölgesi burası olmaktadır. Byte olarak tanımlanan bu bölge, aynı zamanda ascii kodlama olarak bir dizi karakterler içermektedir.
SATIR-17: bufferend: Buffer olarak isimlendirilen bölgemizin sonunu gösteren label'dır. Bu satırdaki label; işlemcinin, programın akışı esnasında son olarak okuyacağı adresin tanımlaması için konmuştur.
Son örnek programımızı genel olarak özetlemek gerekirse:
A- İlk iki satırda, arama yapılacak bölgenin başlangıç ve bitiş adreslerini A0 ve A1 adres registerlerine yerleştiriyoruz. B- Üçüncü satırdan itibaren programımızın arama döngüsü başlıyor. Üçüncü satırdaki Cmp komutu ile, A0'daki yeni buffer bölgemizin ilk byte'ının P harfi olup olmadığı kontrol ediliyor. Sonuç hayır ise, A0'daki değer (yani, programa başlarken söz konusu bölgenin başlangıcını temsil eden değer) bir artırılarak (satır 12'deki Add komutu yardımı ile) üçüncü satıra geri dönülür ve yeni adreste (arama bölgesinin ikinci byte'ında) P harfinin ASCII kodu aranır. Bulamadığımızı düşünelim. İşlemci P harfini bulana kadar 3-4- 12-13-14 döngüsünde gidip gelecektir. Tabii A0'daki, yani değişken olarak kullandığımız bu registerdeki değeri her turda bir değer artırarak işleyişe devam etmektedir.
Bu döngü esnasında, üçüncü satırın P harfine rastladığını düşünelim. Buradan itibaren de döngünün akışı çok basit bir mantık ile olmaktadır. İşlemci, şimdi beşinci satırdaki cmp komutu ile E harfinin P'den sonra gelip gelmediğini kontrol ediyor. 5. satırdaki karşılaştırmanın da 6. satırda olumlu karşılandığını ve P-E harflerinin sıralı olarak arka arkaya bulunduğunu varsayalım. Şimdi işlemci, 7. satırda öngörülen R harfinin E'den sonra gelip gelmediğine bakıyor. Buradaki yönergenin de olumlu olduğunu düşünerek 9. satıra geliyoruz. Şimdi sıra, son harf olan I harfine geldi. Bu harfin de bulunup bulunmadığına bakılarak sonucunu iki türlü değerlendirmeye tabi tutuyoruz.
1- L2 label'ına gidilip yeni bir değer alınarak arama işlemine P'den itibaren devam edilir.
2- PERİ karakter dizisi bulunarak program durdurulur. Tabii sonuç adres (PERİ kelimesinin hafızadaki başlangıç adresi) A0'da durmaktadır.
Aslında arama programlarında bu tür bir döngü çok esnek kullanımlı olmasa da, belli bir formata sıkı sıkıya iş görmektedir. Ve aynı zamanda anlaşılabilirliği en kolay olan döngü olma özelliği taşımaktadır. Tabii aynı iş, binbir türlü rutinlerle de yapılabilir.
Evet. Şimdi size makina dilinden başka dillerde çok büyük zaman alan sıralama işlemlerine bir örnek vereceğim.
Klavyeyle gezinmek için ← ve → tuşları.
Sayfa 31
Örnek programımızda; bir hafıza adresindeki 10 adet değerin büyükten küçüğe göre sıralanmasını işleyeceğiz.
Yan sütunlardaki programa bir göz atın. Şimdi sırayla satırların açıklanmasına geçelim.
SATIR-1: START: LEA BUFFER,A1 Programımızın başında, sıralama bölgesinin başlangıcını temsil eden buffer label'ının hafıza adresinin değerini A1 registerine gönderiyoruz. Amacımız, her rutinde olduğu gibi rutinin ana öğelerini temsil eden sayı değeri veya adresleri registerler üzerinden kullanıp rahat bir çalışma ortamı yaratmak oluyor. Zaten başka türlüsü imkansız olurdu herhalde! SATIR-2: MOVE.L A1,A0 Bu satırda, sıralama bölgesinin başını temsil eden A1 registerinin içeriğini A0 adres registerine kopyalıyoruz. Amacımız değişken olarak A0 registerini ve bölgenin başlangıcı olan adresi de A1 üzerinden kullanmak olacaktır. SATIR-3: MOVE.L #10,D2 Sıralanacak değerlerin sayısını burada D2 data registerine yüklüyoruz. Bu değer, bizim programımızda komutta belirtildiği gibi 10'dur.
SATIR-4: MOVE.L D2,D0 Şimdi D2 registerindeki sayıyı, D0 registerine kopyalıyoruz. Bilindiği gibi, D2 data registerindeki sayı sıralama yapılacak değerlerin sayısını ifade etmektedir. SATIR-5: SUBQ #2, D0 Sıralama programımızın işleyişi esnasında, sıralama bölgesinden değerler sırası ile alınacak ve tek tek diğer değerler ile karşılaştırılacaktır. Tabii bu da bir döngü ile olabilir (7. satır ile 15. satırlar arasındaki döngü). Döngüyü sağlayan DBRA komutu 10'dan işleme girdiğinde 0'da son bulacağından ve sıralanacak verilerin zaten ilk ikisi ilk turda işleme girdiğinden gerçek döngü sayısı eksi iki değer oluyor, işte D0'da sıralanacak veri sayısından 2 eksiltmemizin nedeni budur.
SATIR-6: CLR.L D1 İki değeri birbirleri ile karşılaştıracağız. Bu karşılaştırma sonrası, değerler birbirlerinden büyük veya eşit olmalarına göre yer değiştirebilirler. İşte kısa sıralama rutinimiz de, bu mantık ile çalışıyor. Bu satır, aşağıdaki satırlarda göreceğiniz gibi bir göstergeç görevi yapacaktır. Görevi, yer değişecek değer olup olmadığını ve sıralama bölgesindeki son byte'a erişilip erişilmediğini ifade etmektir.
SATIR-7: L1: MOVE.W 2(A0),D3 Bildiğiniz gibi, işlemci bu satırda A0 registerinin buffer değerini aldığını biliyor. 2(A0) ibaresi ile buffer bölgesindeki 2. word'nolu adresteki değeri alıp D3 registerine gönderiyor.
SATIR-8: CMP.W (A0),D3 Bu satırdaki işlem, A0 registerinin içeriğindeki değerin adresi ile D3 registerinin içeriğini karşılaştırıyor. Bu komutun programdaki görevi, buffer bölgemizdeki A0'nolu değer ile bir sonraki değeri karşılaştırmak.
SATIR-9: BCC L3 İşte bir branch komutu. Görevi; yukarıdaki komuttaki işlemin sonucu olan sayı, ilkinden büyük ya da eşit ise atlama yapılacak olan yere git (yani L3 label'ına) olmaktadır.
SATIR-10: L2: MOVE.W (A0),D1 Bir üst satırdaki işlemin sonucunda karşılaştırılan değerler büyük ya da eşit olmadığında, işlemci bu satırdan itibaren icrasına devam edecektir. Word modunda kullanılan move komutu, A0 adres registerinin gösterdiği adresteki sayıyı alıp, D1 registerine gönderiyor.
SATIR-11: MOVE.W 2(A0),(A0) Buradaki move komutu ise, A0 adres registerindeki değerin iki fazlası olan değerin gösterdiği hafıza adresindeki değer ile yine A0 registerinin gösterdiği değerin değişimini ifade ediyor.
SATIR-12: MOVE.W D1,2(A0) Move komutu, D1 registerindeki word değeri A0 registerindeki değerin iki fazlasına koyuyor.
Son üç satırdaki komut birbirleri ile doğrudan alakalıdır. Çünkü karşılaştırılan sayılar büyük ya da eşit olmadığında, bu üç satır yardımı ile yerleri değiştiriliyor. Bu işlem şöyle olmaktadır: Birinci satırda ilk önce A0'daki değer D1'e konmaktadır. Sonra A0'ın gösterdiği değerden sonraki değer, ilk değer yerine konuyor (ikinci komut). Daha sonra üçüncü komut ile D1'deki değer ikinci değer yerine konuluyor. SATIR-13: MOVEQ #1,D1 D1 registerine değerlerin yer değişimi yapıldığını belirtmek için 1 değerini gönderiyoruz. Aşağıda bunun kontrolünü yapacağız.
SATIR-14: L3: ADDQ.L #2,A0 İşlemci, yukarıdaki BCC komutunun sonucunda karşılaştırdığı sayılardan büyük veya eşit sonucu çıkarırsa, o anda söz konusu değerin yerini sağlamlaştırmış demektir. Buradaki ADD komutu yardımı ile bir sonraki word'ün değerini A0 registerine yüklüyoruz.
SATIR-15: DBRA D0,L1 İşte meşhur döngümüzün kilit noktası. Değerler sırası ile büyükten küçüğe doğru bu döngünün filtresinden geçerek tablodaki gerçek yerlerini bulacaktır.
Komut gereği D0'daki değer 0'a ulaşıncaya kadar döngü L1 ile bu satır arasında devam edecektir.
SATIR-16: TST D1
Sıralama yapılan bölgedeki en son byte'a ulaşıldığında ve ondan büyük olmadığı anda, D1 registeri 0 değerinde olacaktır. Ama sıralama işleminin ortalarında devamlı L2 komut dizisine girilip devamlı değerlerin yerleri değiştiğinden, D1 registeri 1 değeri ile buradan çıkacaktır.
SATIR-17: BNE START Bir üst satırın system flaglarına etkisini buradan okuyabiliriz. İşlemin sonucu aynen satır-16 açıklamasındaki gibi gerçekleşecektir.
SATIR-18: RTS Programın nihayeti buradaki RTS komutudur.
SATIR-19: BUFFER: dc.w 3,510,2,6,9,4,1,7,8 Sıralama bölgesi ve karmaşık dizilmiş değerler işte karşınızda. Tabii programın sonucunda bunlar büyükten küçüğe doğru sıralanmış halde olacaklar.
Böylece kağıt üzerinde son örneğimizi vermiş oluyoruz. Artık gelecek sayıdan itibaren uygulamalı örneklere başlayabiliriz. Fakat daha önce örnekleri yazacağımız SEKA ASSEMBLER'i kullanmayı öğreneceksiniz. Gelecek sayıda görüşmek üzere!
ÖRNEK PROGRAM 5a :
1 START: LEA BUFFER.A1
2 MOVE.L Al, A0 3 MOVE.L #10,D2 4 MOVE.L D2,D0 5 SUBQ #2,D0 6 CLR.L Dİ 7 L1: MOVE.W 2(A0),D3 8 CMP.W (A0),D3 9 BCC L3 10 L2: MOVE.W (A0),D1 11 MOVE.W 2(A0),(A0) 12 MOVE.W D1,2(A0) 13 MOVEQ #1,D1 14 L3: ADDQ.L #2,A0 15 DBRA D0.L1 16 TST D1 17 BNE START 18 RTS 19 BUFFER: dc.vv 3,5,10,2,6,9,4,1,7,8