Keil de verdigim 5 C satirini derleyecek hayirsever varmi?

Başlatan bunalmis, 19 Şubat 2011, 23:29:24

z

int var1,var2,var3
int void() {
     var1=1;
     var2=2;
     var3=3;}


32K limitli versiyon kullandigim icin malesef C dosyalarini derledigimde lst dosyasini elde edemiyorum. Bu yuzden yardim istiyorum.

Bu C kodlarini 3. optimizasyon seviyesinde derleyip olusan lst dosyasini buraya yapistiracak hayirsever araniyor.
Herhangi bir cortex m3 islemci icin derleyebilirsiniz.

Bana e^st de diyebilirsiniz.   www.cncdesigner.com

z

Acele ile int main(void) yazacakken int void() yazmisim.

Gerbay ilgin icin cok ama cok tesekkur ederim. Sorumu attigim andan itibaren bir an once cevap gelse de  lst dosyayi incelesem diye beklemedeyim .
Keil kullandiklarini bildigim uyeler bir bir online olup sitede gorunup yok oldular ve topu topu 1dk larini alacak bu basit konuda yarali parmagima isemediklerini gordum ya.
Alacaklari olsun onlarin....





Bana e^st de diyebilirsiniz.   www.cncdesigner.com

z

int var1, var2, var3;
int main()
{
   var1=1;
   var2=2;
   var3=3;
}

Gibi bir deneme programinin neden lst dosyasina ihtiyac duydugumu anlatayim.

Cortex M3 icin assembly program yaziminda Keil bana zorluk cikartiyor ve anlasilirligi bozmamak adina C den daha uzun kod yazmama neden oluyor.
Halbuki kafamdan gecen anlasilir kodlari yazabilsem 3.seviyedeki optimizasyona esdeger kod olusacak.
Eger anlasililik onemli değil dersem 3. optimizasyon seviyesinde kodlayabiliyorum fakat bu hic ama hic hos bir durum değil. (Cunku anlasilirlik zaten asm de zordur.)

Data segmentde

var1 DCD 0x00
var2 DCD 0x00
var3 DCD 0x00

Seklinde tanimlama ile C deki int var1, var2, var3 tanimin aynisi yapilmis oluyor.

Daha sonra bunlarin icine sira ile 1,2,3 degerlerini yazmak icin

LDR R0,=Var1 yazarak Var1 in ramdaki adresini R0 icine atmis oluyoruz.
Ancak var1 adresinin sayisal karsiligi deger,  LDR komutunun icine dogrudan gomulemiyor, illaki islemcinin bu adresi romdan okumasi gerekiyor. Bu adres degeri yazilan programin sonlarinda bir yere program counterin uzerinden kod isler gibi kosturmayacagi bir adrese derleyici tarafindan yaziliyor.

Daha sonra pespese siralanmis var1, var2 ve var3 e bir seyler yazmak icin (ornekte var1=1, var2=2, var3=3)
MOV  R1,#1
STR  R1,[R0,#0]
MOV  R1,#2
STR  R1,[R0,#4]
MOV  R1,#3
STR  R1,[R0,#8]

demek yeterli olur. Ancak burada 0, 4 ve 8 degerleri asm yazim icin yakisikli gosterimler değiller. Cunku bunlar degiskenlere ait relatif adres degerleri olup bu tur gosterimler debuggerlar icin normal karsilanabilir fakat asm yazimda bunlari sayisal degerler değil de dogrudan degisken ismi yada degisken ismine cok benzer kelimlerle kodlariz.
Boylece kodlari okurken kolay anlariz.

Assembler derleyiciler degisken adlarini kendisi cozup adresleri linker esliginde otomatik olarak hex kodlara yazar.

ARM yapisinda dogrudan fiziksel adres degerini komut icine gommek mumkun değil. Cunku STR  R1,[R0,#XXX]  gibi bir yazimda XXX in numerik bir deger olmasi gerekiyor.

Fakat anlasilirlik bozulmasin diye var1 degiskenini yazildigi yerde gorebilmek adina var1_ gibi farkli bir gosterim bile tercih edilir. (Kotunun iyisi)

ornegin var1 DCD 0x00 olarak tanimlanmis var1 degiskenini

STR R1,[R0,#0] olarak kullanmak yerine
STR R1,[R0,#Var1_] seklinde kullanmak isteyelim;

Boylece bu satira baktigimda Var1 degiskeninin icine erisildigini anlarim.  Mukayese etmek acisindan  STR R1,[R0,#0] R0 base adresinde 0 ofsetli degiskene erisilmek istendigini anlariz. Haliyle bu kodun var1 icine eristigini anlamak icin extra caba gerekecek geriye dogru kodlari incelemek gerekecektir.
Zaten bu yazim asmcilere bile yakismayan bir yazim seklidir.

O halde STR R1,[R0,#Var1_] yazimi icin var1 adresinin sayisal karsiligini bulup ofset hesabi ardindan bunu var1_ gibi bir sabite equ directifi ile donusturmek yeterlidir.

Fakat tum cabalarima ragmen bir degiskenin adresini (sayisal karsiligini) bulma direktifini goremeyince bunu Keil form sitesinde sorma ihtiyaci duydum. Fakat 2 zibidi ile eksik ingilizcem nedeniyle gereksiz ve uzun yazismalar yapmam gerekti.

Hala da sorun da benim acimdan cozulemedi.

Ancak gordugum kadariyla degiskenlerin adreslerini alip kullanmama yarayan direktif Keil ortaminda yok gorunuyor.

Bu durumda 3 nolu optimizasyona esdeger kod yazma sansim elimden aliniyor ve gereksiz yere daha uzun kodlama yapmam gerekiyor.

Bu da

LDR  R0,=var1
MOV  R1,#1
STR  R1,[R0,#0]

LDR  R0,=var2
MOV  R1,#2
STR  R1,[R0,#4]

LDR  R0,=var3
MOV  R1,#3
STR  R1,[R0,#8]

Bu yazim sekli,  ilk yazim sekline gore 6 byte ilave kod demekken birde beraberinde romda 3 tane de 32 bitlik yani toplamda 6 bytelik alan da goturuyor. Yani 12 byte fazla kod yaziliyor. (Aslinda 10 tane) Zaten C derleyicinin yukaridaki uzun yazimi uretmesi icin optimizasyon seviyesini 0 yapmaniz yeterli. Bence keil optimizasyonda yapacaksey bulamamis
eften puften seylerle optimizasyon yapmaya calismis. Asm yazan en basit yukaridaki ornegi bile 3. optimizasyona denk olacak sekilde yazar. Neden 0 nolu optimizasyonda oldugu gibi uzun kodlama yapsinki?

Gerbayin verdigi lst dosyaya, bu soruna keil kendi nasil cozum bulmusun cevabini gormek icin baktim ve malesef cozumunun olmadigini gordum.

Cunku keil dogrudan var1 var2 ve var3 relatif adreslerini kod icine gommus. Eger anlasilir bir lst kod uretseydi

STR  R1,[R0,#8] yerine STR R1,[R0, direktif(var1)]  yada STR R1,[R0,var1_] gibi kod uretmeliydi.

Bu durumda yazilan asm kodlari asm derleyiciye vermeden once oncu bir derleyiciye vermem ve bu oncu derleyicinin STR R1,[R0, #direktif(var1)] gibi bir yazimdan
STR  R1,[R0,#8] gibi yazima donusum yapmasi ardindan da asil keil asm derleyicisini cagirmam gerekecek.

Son derece gereksiz bir yol. Fakat asm derleyiciye bu istedigim kodlamayi yaptirmamis olmasi cok sacma.

Demek istedigi aynen su;

Keil kendi kod uretirken LDR R1,=Var1 gibi bir kod gordugunde Var1 adresini alip kodlarin sonuna yazacak, ama keile kardesim var1 adresini senden bir directif ile talep ettigimde verirmisin dersem yok oyle bir direktif desin vermesin.

Bu durumda,

Asm ile yazacaksan variable ismi kullanma dogrudan adresini yaz yada C kullan demeye getirsin.

YOK YAAA.

Bunun gereksiz oldugunu dusunebilirsiniz. Keildeki zibidiler de oyle dusundu. Fakat ben boyle dusunmuyorum. derleyici yazara olabildigince yardimci olmali.
Tamam assembler ne yazarsan onu cevirir ama adres hesaplamalarinda vs de bana bazi luksleri de yasatmali. Adresleri de ben hesaplayacaksam kusura bakma mnemoniklerin de sayisal karsiliklarini ezberlerim kodlarimi asm derleyicisiz kendim yazarim. (Bu kadar da cusss tabiki)

Arm harici calistigim tum islemcilerde asm derleyicileri adresmis, ofsetmis bana zorluk cikartmaz dogrudan degisken isimlerini istedigim gibi kullandirirdi.

Umarim ben bilmiyorumdur da keil asmde de bana bu luksler yasatilir.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

fatihkuzucu

Exp.Kits http://tinyurl.com/3qhs8pm   Küçük adamların, küçük fikirleri... Büyük adamların, büyük hayalleri...

z

O ayri bir mesele.

Derinlerinde farkli sebepler var.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

z

Projemi tek bir C dosyasi ile degilde C ve asm dosyalari uzerinden yurutuyorum. Haliyle inline asm kullanmiyorum.
Keilin C derleyicisinden memnunum. Asm derleyicisini yukaridaki yazimdan anlasilacagi uzere sevemedim.

GCC ile sadece asm dosyalarini derlesem, Keil ile de C kodlarimi derlesem bunlarin link islemini  uvision basligi altinda gerceklestirebilirmiyim?
Yada Keili tamamen bir kenara biraksam GCC bana alli gullu gorsel bir IDE imkani sunacakmi?

Bir de hangi linki tiklarsam  cortex m3 uzerinde proje gelistirmek icin c ve asm derleyiciler makinama yuklenir.  :)


Bana e^st de diyebilirsiniz.   www.cncdesigner.com

z

C den gicik kapmamin bir sebebi de optimizasyon olayi.

Pek cok tartismada asagidakine benzer ifadeler gordum.

Vatandas1: Soyle soyle bir sorun yasadim ve sorunun ne oldugunu anlamadim.

Vatandas2: Optimizasyon seviyesini 0 yapip derlersen calisir.

Bu konu mide bulandirmak icin yeterli sebep. Bekleki derleyicinin muhendisleri bu sorunu sozsun.

O yuzden optimize gerektiren kisimlarin kodlamasinda cokca zaman kaybi yasasam da asm den vazgecemiyorum.  Hatali bir yer varsa
kendime surda hata var duzelt diye emredebiliyorum.

Gerbay

Olay sadece initialize asamasi değil. En tepedeki 5 satirlik C programini degiskenlere ulasimi gormek adina yazmistim.

Programda pek cok noktadan global degiskenlere erisim gerekecek. Haliyle bu durum her global degiskene erisilen noktada kendini gosterecek.
Hatta ve hatta her 8K da bir ayni degiskenlere erisim ihtiyaci olsa bu degisken adreslerinin tekrar tekrar roma gomulmesi gerekiyor.

Bu sorun, Cortex m3 mimarisinden kaynaklaniyor diye dusunuyorum. Sonucda cortex m3 sifirdan dusunulmis 4/4 luk bir mimari değil. ARM7 nin kolu bacagi kesilip thumb2 kodlama ile yapilabilecekleri en iyisi. (Benimkisi biraz ahkam kesmek oldu ama oyle gorunuyor)

ARM islemcide ARM modunda yazsaydim muhtemelen boyle sikintilarim olmayacakti.(?)

Alıntı Yap...Her durumda da 2 byte yer tutuyor instruction lar ama 2. durumda data segment de (yani ram de) 4 byte az yer tutuyor. Global ya da statik değişkenleri direk initialize etmek her durumda sizin ilk örneğinize göre hem kod olarak hem de ram kullanımı açısından daha avantajlı olur..

Bahsettiginiz kodlari derinlemesine incelemedim ama ramda ilk deger alacak degiskenlere deger atamasi maine girmeden once startup asamasinda yapiliyordur. Haliyle optimize kod gibi gorulebilir fakat sonucta atamalar burda degil de orda gene yapilacak.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

z

Bir de bir yada iki ay once keilin help menulerinde gezinirken asagidakine benzer bir ifadeyle karsilasmistim fakat bu uyariyi ilerleyen versiyonlarla birlikte bulamaz oldum. (Yada ben bulamiyorum)

"Bir etketin adresi $ ile ogrenilebiliyordu, yeni surumle birlikte bu ozellik kaldirildi." Gerekce olarak, kod etiketlerinin adreslerinin alinip kullanilmasi pipeline mekanizmasindan dolayi sorun olusturuyor  diye acikladigini hatirliyorum.(?)

Zaten su anki sikintim da $ gibi bir ifadenin olmayisi.

Adim gibi eminim eger ki su anki versiyonlarda $ yada benzeri bir directif kaldirildi ise onumuzdeki versiyonlarda buna benzer direktif tekrar geri gelecek.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

z

Alıntı Yaphocam tahmin ettiğiniz şekilde olmuyor. ilk durumda siz initialize edilmemiş bir değişken tanımladığınızda data segment de o değişken için bir yer ayrılıyor ve sıfır ile initialize ediliyor. Daha sonra siz herhangi bir atama yazptığınızda da atadığınız değeri alıyor. Direk tanımlama aşamasında (lokal değişkenler hariç) initialize ederseniz datasegment de ayrılan yer direk kod derlenirken atadığınız değere initialize ediliyor, onu initialize etmek için tekrardan herhangibir kod parçası çalıştırılmıyor. Yukardaki assembly file ları incelerseniz bu durumu çok net görürsünüz zaten.

Bu dedigin mumkun olabilirmi iyi dusun.

Eger degisken değilde constand olsaydi roma derleme asamasinda gomebilirdi. Fakat ramda degisken tanimi gerekiyorsa ve bu ilk deger alacaksa bunun ilk degeri main oncesinde atanmasi gerekir.

var1 DCD 0x01 gibi bir gosterim, sadece var1'e ilk deger atanmasi gerektigini ve degerinin de 1 olacagini soyler o kadar.

Zaten initialized degiskenler ayri bir alanda tutulur diye biliyorum. Gerci ben asm de boyle bir ayrima girmiyorum. Once tum degiskenleri siliyor daha sonra ilk deger alacaklara deger atiyorum. Tabiki kodla.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

z

Alıntı YapTam olarak yapmaya çalıştığınız şey için kod örneği verebilirmisiniz? pseudo kod da olur

Ornegin

Ram alaninda

Var1 DCD 0x0
Var2 DCD 0x0

tanimlansin. Ardindan herhangi bir yerde

Var1_ equ  Var1 adresi
Var2_ equ  Var2 adresi

Bunu yapabilsem benim tum dertlerim bitecek.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

z

Bende bunu soyluyorum iste. Initialize edilecek degiskenlere degerler startup kodlar icinde kopyalanir. Bu tek tek atama olmaz da blok kopya olur o onemli değil. Sonucta romdan rama veriler kod ile atanir diyorum. Haliyle

int a=1; gibi ilk atamanin

int main()
{
  a=1;
}

Gibi bir koda gore daha optimize kod urettigi sonucu cok da dogru olmaz.

Alıntı Yapvar1 e datasegment de açılan yerin 0x01 initialize edileceğini söyler. Bu compile aşamasında yapılır, runtime da değil..

Bu dogru, ama startup codlarini da runtime asamasi islenen kodlar olarak dusunmek gerekir. (Bence bu kritik bir konu tersi de soylense kabul)

Ha romda var1=1 yap demisim. Ha startupta var1 alanina romdaki 1 degerini ata demisim tamamen ayni sey.

Dogru olan kesin konu,  int a=1; atamasinin C kodlari ile yapilmadigi.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

z

Birbirimiz de ayni sey soyluyoruz. Cok da kritik bir durum degil son kez dusuncelerimi yazmaya calisayim.

int a=1; gibi ondeger yuklenmis bir degisken derleme asamasinda

initialized datalarin bulundugu segmentte
a dcd 1 seklinde asm koda donusur.

Hex kodlar olusturuldugunda ise romun bir yerinde 00010000 gibi bir deger kuzu kuzu bekler.

Islemci reseti yedigi anda startup kodlari romdaki 00010000 degerini alir ve ramdaki a degiskeni icin ayrilmis adrese yazar. (Bu atamayi tek tek degisken bazinda yapmaz da
blok bazinda yapar. )

initialize edilmemis degiskenler icin bunun yapilmasina gerek yok. Eger derleyici yazanlar boyle yapiyorlarsa ayip ediyorlar.
Startup kodlarinda ramin degiskenler icin ayrilmis alanini dongu icinde sifirlarsin boylece romda bosu bosuna uninitialized degiskenler icin 0 degeri saklanmis alan ayirmazsin.

Neyse konunun bu kismi gercekten beni ilgilendirmiyor.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

z

extern int VarX;

int main()
{  
  VarX = 1;  
  int *pInt = &VarX;  
 *pInt = 0xABCD;
}


Kodunuzu derlemeden once olacaklari hemen soyleyeyim.

LDR R0,=VarX seklinde bir kod olusacak
bir kac satir asagidada

VarX adresi rom kodlarin icine gomulecek.

Aslinda LDR R0,=VarX tamamen pseudo bir kod.
Bunun dogrusu LDR R0,[PC,#n]

Derleyici Varx degerini bulacak n byte ileriye sanki label DCD Var1Adresi  kodmus gibi gomecek.

Ama ne olur bana VarX icin n deger ileriye yazdigin degeri equ ile atamama izin ver dedigimde kusura bakma diyecek.

int *pInt = &VarX;

satirinda ise bu kez LDR R0,[PC,#k] kodu ile VarX adresini Ro icine cekecek

*pInt = 0xABCD; ile de 0xABCD gibi sayisal degeri MOV tarzi bir komutla ornegin R1 icine atacak ve R0 in gosterdigi yere yazacak.

Simdi derliyorum.

Sanirim demek istedigim anlasilmistir. Keil asm uretirken kendi istedigi gibi at kosturuyor. Ben asm yazmak istedigimde hoop sana bu adresi vermem diyor.
Eger roma yazilmasina raziysam zaten

bende asm kodlamada LDR R0,=Var1 kullanabiliyorum. Fakat bunun neden optimize 3 kodlar yazmami engelledigini en basta acikladim.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

z

Aynen dedigim gibi yapmis iste. Durumun vahamiyetini gormek icin VarY, VarZ seklinde bir kac tane daha degisken ekle.

Simdi beni konunun bu kismi ilgilendirmiyor, boyle yapiyorlarsa ayipediyorlar dedim ama gene de sormadan edemeyecegim.

Diyelimki C programinizda 1000 tane int degisken tanimladiniz. Bunlarin hic birini de initialize etmediniz.

int a1,b1,c1,d1,...;
int a2,b2,c2,d2,...;
....

int main()
{
   while (1);
}

gibi de bir kod yazdiniz. Eger bu kodu derledigimde eger initialize edilmemis degiskenler icin romda bu adamlar yer ayirmis yerlerine 0 yazmislarsa sonrada bunu startupta
rama kopyaladilarsa standarti yazanlar gercekten ayip etmisler. (Benim fikrim)

Cunku yukaridaki basit kod bile en azindan 1000*4 den 4000 byte lik rom alani goturur.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

z

Sonucta asm de bunlarla ugrasmak gerekmiyor ve zaten olmasi gereken optimize kodu daha ilk satirdan itibaren yazmis oluyoruz.

Neyse, peki ilk sorunuma geri donersek, ne diyecegiz bu durumda?

var1 DCD 0 seklindeki tanimin ardindan,

var1 EQU (variable 1 in adresi) seklindeki tanimi asla yapamayacakmiyim?
Bana e^st de diyebilirsiniz.   www.cncdesigner.com