AMIGA C

C dili bütün hızıyla devam ediyor. Artık hepinizin Amiga C diline ısınmış olduğunu farz ediyorum. Bu nedenle daha profesyonel çalışmalara girebileceğimizi tahmin ederekten, bu ayki konumuzu geçen aylarda vermiş olduğum C'de Assembler dilinin kullanımının biraz daha gelişmişi olarak seçtim. Önceki sayılarda C'den Assembler alt

pea 30
pea 20
pea 10
jsr — rutine2
lea 16(sp),sp
pea |
pea 2
pea 3
pea 4
jsr Trutine3
lea 16(sp),sp
:)
4
(sp)4,.3
unik a
Tİs
egu 0
3 reg
public — rutine3
public — rutine2
public — rutinel
public
dseg
end

Assembler listesi yukarıdaki C programına ait. Şimdi dikkat edilecek nokta, alt rutinlerin nasıl kullanıldığı ve parametrelerin yollanması. C programından takip ederseniz, birinci rutinde 1, 2, 3 ve 4 sayıları parametre olarak yollanıyor. Assembler alt rutinlerinin nasıl kullanıldığını ve hazırlandığını öğrenmiştik. Bu ay, C'den Assembler alt rutinlerine nasıl parametre yollandığını daha derinlemesine inceleyeceğiz. Bunu yapmak için ilk olarak isterseniz bir C ve C'den çevrilme Assembler rutinini inceleyelim;

main()
rutine2(10,20,30,40);
rutine3(4,3,2,1);

Üç adet rutinin çağrıldığı basit bir C programı görüyorsunuz. Rutinler içerisinde dikkat ettiyseniz parametreleri de mevcut. Rutinlerin işlevlerini göz önüne almıyoruz. Şimdi bir de bu programın assembler'a çevrilmiş halini inceleyelim; :A5=8

;main()
public — main
—Main:
link a5,#.2
movem. .3,-(sp)
ş;Tutine1(1,2,3,4);
pea 4
pea 3
pea 2
pea 1
jSr — Tutinel
lea 16(sp),sp
ürer 10,20,30,40);
a 40

Assembler listesinde ise bu parametrelerin SP (Stack Pointer) göstergecine aktarılarak yollandığını görüyoruz. Buradan da anlaşılıyor ki, parametreler SP'ye yerleştiriliyor. Bu durumda bizim yapmamız gereken, rutin içerisinde iken parametreleri SP'den geri almak. Aşağıdaki örnek programı dikkatle izleyin;

int a;
main()
90d",a);
)
#asm
- topla:
move.l 4(sp),d0
add.l 8(sp),d0
add.l 12(sp),d0
add.l 16(sp),d0
Tits
public
#endasm

Program içerisinde bir toplama rutini hazırladım. Bu rutin verilen dört adet sayıyı toplayarak geri dönüyor. İlk olarak topla() rutinini çağırıyoruz: a=topla(0,5,10,20);

Yollanan parametreler 0, 5, 10 ve 20 sayıları olsun. Bu parametreler ilk örnekteki gibi SP'ye aktarılacaktır. Daha sonra program Assembler alt rutinine sıçrayarak parametreleri SP'den alacaktır. Bu iş için SP'nin gösterdiği adresin 4 ilerisinden ilk parametreyi alıyoruz. Çünkü SP'ye son yollanan değerden sonra, SP, 4 byte azaltılır. SP, yollanan her değerden sonra 4 azaltıldığından, diğer parametreleri de 4'er aralıkla SP'den çekiyoruz:

move.l — 4(sp),d0 — ; 1.parametre
add.| 8(sp),d0 — ; 2.parametre
add.l 12(sp),d0 ; 3.parametre
add.l 16(sp),d0 ; 4.parametre

Değerler toplanarak D0 register'ına yükleniyor. RTS Assembler komutu ile de, C'ye geri dönüyoruz. Toplam değer D0 üzerinde olduğundan sonuç 'a' değişkenine aktarılıyor ve 'printf()' ile değerin doğruluğunu kontrol ediyoruz. Evet parametre yollamanın püf noktalarını öğrendiğinize göre artık daha kapsamlı bir örneğe geçebiliriz. Aşağıda vermiş olduğum program, Assembler yardımıyla library'yi ve ekran açmamızı sağlıyor. Fakat bu ekranın bazı özellikleri mevcut. İlk olarak "show bitmap();" rutini ile istediğiniz hafıza bölgesini C'den kontrol ederek gösterebiliyorsunuz. İsterseniz programımıza bir göz atalım;

/* Programming by C. OZKURT */
/* (c) 1992 Amiga Dünyası */
#include <exec/memory.h>
#include <graphics/gfxbase.h>
#include <intuition/intuitionbase.h>
struct GfxBase *GfxBase;
struct RastPort rp;
struct BitMap bm;
mainO
start(); /* library ve ekranı aç */
set color(1,0xfff); /* birinci rengin pa-
letini Oxfff yap */
Move(&rp,0,0);
Draw(&rp,320,256);
ları ile çizgi çiz */
left mouse();  /* sol mouse kontrolu */
/* library ve ekranı kapa */
)
alloc start()
/* sistem komut-
InitBitMap(&bm,3,320,256);
10240,MEMF
CLEAR);
bm.Planes| 10240,MEMF
-CHIPİMEME CLEAR);
bm.Planes|2)J-AllocMem( 10240,MEMF
CLEAR);
InitRastPort(&rp);
rp.BitMap-&bm;
|
alloc stop()
FreeMem(bm.Planes(0)1,10240);
FreeMem(bm.Planes|11,10240);
FreeMem(bm.Planes|21,10240);
in j
ik |
lib start);
de alloc start();
/* Acmis oldugumuz 3 bitplane'lik hafi-
za bolgesini goster */
/* show bitmap(plane1, plane2, plane3); */
show bitmap(bm.Planes(0),bm.Planes-
(1),bm.Planes|2));
scr start();
ına
de,
DO | stop0
ni- (
)ö- ser. stop();
et- alloc stop();
ni- lib stopO;
ge- | |
NS #asm
|
| left mouse:
rak btst #6,$bfe001
ha- | bne.s — left mouse
te- Tts
ıza
ib start:
move.l 4,a6
lea Gfxname,al
İST -408(a6)
dOzopenlibrary(al)
move.l d0, GfxBase
İsr -132(a6) ; forbid();
TİS
ib stop:
move.l 4,a6
move.l  GfxBase,al
jsr -414(a6) ; closelibrary(al)
jsr -138(a6) ; permit()
Wi Tts
pa start:
lea copper,a0
yut- move.l — GfxBase,a6
move.w #$00a0,$dff096
y*/ move.l  50(a6),oldcop
*/ move.l a0,50(a6)
move.w #$8380,$dff096
rts
—scer stop:
move.l — GfxBase,a6
ME move.w #$00a0,$dff096
move.l oldcop,50(a6)
ME move.w #$83a0,$dff096
TİS
MF
bitmap: move.l #bitmap,a0
move.w 4(sp),2(a0)
move.w 6(sp),6(a0)
move.w ),10(a0)
move.w 10(sp),14(a0)
move.w 12(sp),18(a0)
move.w 14(sp),22(a0)
rts
—set color:
move.l #color42,a0
move.l 4(sp),d0
#4,d0
mulu şi
move.l
add.l — d0,a0
move.w
rts
dseg
copper:
de.w 0100,$3200,$0102,$0000
dec.w — $0108,$0000,$010a,$0000
de.w — $0092,$0038,$0094,$00d0
dc.w — $008e,$3081,$0090,$30c1
bitmap:
de.w — $00e0,$0000,$00e2,$0000
de.w $00e4,$0000,$00e6,$0000
— $00e8,$0000,$00ea,$0000
color:
de.w — $0180,$0000,$0182,$0£00
de.w — $0184,$000f,$0186,$00f0
dec.w — $0188,$0ff0,$018a,$00ff
de.w — $018c,$0c0c,$01 8e,$0aff
dec.w
Gfxname: dc.b library',0
oldcop: 0
cseg
public set color
public left mouse
public show bitmap
; #endasm

Program temel olarak 3 bitplane'lik bir bitmap yaratıyor. Bu bölgeyi AllocMem() sistem fonksiyonu ile ayırıyoruz. İkinci kademede bu bölgeyi daha önce açmış olduğumuz 'copper' ekranı ile gösteriyoruz. İlk olarak library'ler aşağıda olduğu gibi bir Assembler rutini (lib start();) ile hazır hale getiriliyor. Bu rutinde 'graphics.library' açılıyor. Kapama işlemini ise lib stop() Assembler rutini ile gerçekleştiriyoruz.

ib start:
move.l 4,a6
lea Gfxname,al jsr -408(a6) ;
dOzopenlibrary(al)
move.l GfxBase
jİsr -132(a6) ;
ib stop:
move.l 4,a6
move.l  GfxBase,al
jsr -414(a6) ; closelibrary(al)
jsr -138(a6) ; permit()
rİs

Copper ekranımız aşağıdaki rutinlerde hazırlanıyor:

—scr. start:
lea copper,a0
move.l — GfixBase,a6
move.w  #$00a0,$dff096
move.l — 50(a6),oldcop
move.l — a0,50(a6)
move.w #$8380,$dff096
rts
stop:
move.l — GfixBase,a6
move.w #$00a0,$dff096
move.l — oldcop,50(a6)
move.w #$83a0,$dff096
rts

Assembler start() ekran açma, scr stop() kapama rutinimiz. Copper listemiz ise listenin girişinde bulunuyor. Bu listeyi kontrol ederek renk ve göstermesi gereken hafıza bölgesini seçebiliyoruz. set color() rutini istediğimiz rengin paletiyle oynamamızı sağlıyor. show bitmap() ise harika bir rutin. İstediğimiz hafıza bölgesini gösteriyor. Biz burada açmış olduğumuz bitmap bölgesini seçiyoruz. Yapmış olduğumuz işlemleri rahatça test edebilmek için. Şimdi gelelim programımızın compile işlemlerine. Programda dikkat edilecek husus, copper listesinin CHIP hafızada bulunmasıdır. Aksi takdirde program çalışmaz. Çünkü bildiğiniz gibi Amiga'nın DMA (Direct Memory Access) entegresi yalnızca CHIP hafızaya ulaşabiliyor ve diğer işlemcilere bilgi yollayabiliyor. Eğer FAST hafızanız yoksa problem yok. Sonuç olarak program hep CHIP'te çalışacaktır. Fakat FAST'li bir alete geçtiğinizde programın FAST'te çalışma olasılığı oldukça fazla. Bu durumda programınız çalışmaz. Programın devamlı CHIP hafızada çalışmasını sağlamak için link sırasında *C (CHIP) opsiyonunu koymalıyız. Bu opsiyon ile program her zaman için CHIP hafızaya yüklenecektir. Örnek göstermek gerekirse;

CC *L prog. c
LN *C prog. o

işlemlerini yapmalıyız. Artık programı yazıp seyretmek size kalmış. Bu aylık da benden bu kadar. Gelecek ay hızlı rutinlerle buluşmak üzere, saygılar....