Benim işlemcim seninkini, benim C senin ASM yi döver.

Başlatan z, 13 Kasım 2009, 16:01:07

muhittin_kaplan

@azimli
merak ettim c++ ve c# ile nasıl MCU programlanır ? varda ben mi bilmiyorum acaba

muhittin_kaplan

Alıntı yapılan: "muhittin_kaplan"böyle iyi
bir basic ci :D (oda nasıl oluyorsa) olarak asm ile c nin birbirine girmesi iştahımı kabartıyor :S
Okadar Yabana Atmayın Basic i, Swordfish diye bir derleyicisi var. Hatta Flaş da bile taşınabiliniyor. Taşınabilir yani :D

lojikmemo1

Alıntı yapılan: "muhittin_kaplan"
Alıntı yapılan: "muhittin_kaplan"böyle iyi
bir basic ci :D (oda nasıl oluyorsa) olarak asm ile c nin birbirine girmesi iştahımı kabartıyor :S
Okadar Yabana Atmayın Basic i, Swordfish diye bir derleyicisi var. Hatta Flaş da bile taşınabiliniyor. Taşınabilir yani :D

Hakkaten o derleyici çok şahane biraz mikrobasic i adırıyor ama neyse :)
İnsanlara Akılları Ölçüsünde Söz Söyleyiniz.

z

Bu konuyu tekrardan uyandırmanın vakti geldi.

C ile dilediğim mikroya dilediğim programı yazabiliyorum. Aynı programı ASM ile yazarsam ASM kodum jet gibi uçuyor, C ile yazdığım ise nal topluyor.

Burada iki durum var.

İlki,  C'de hızlı koşan kodlama yapmayı beceremiyorum.
İkincisi ise, C asla ve asla ASM kadar hızlı koşabilecek kod üretemez.

Bu iki durumdan ilki kesinlikle doğru. Fakat, ikinci durumun daha doğru olduğuna inanıyorum.

Diyeceksiniz ki bu işler inançla olmaz. Ben de diyorum ki hodri meydan. Bana bunu basit bir örnek üzerinde ispatlayın.

İşlemcimiz: ARM Cortex M3
Derleyicimiz: Keil uvision 4.XX

Sorum.

Nerede ve nasil tanimlandiginin hic bir onemi olmayan a0, a1, a2, a3 8 bit, a4 ve a5 ise 16 bitlik değişkenlerdir.
0x40004000 adresinde 32 bitlik registerimiz bulunmaktadir.

Bu registerden okunan 32 bit verinin low byte'ı a0'a yerleşmek üzere, 32 bit verinin 4 adet 8'li bileşeni sırayla a0,a1,a2,a3 içine yazılacaktır.
Sözkonusu 32 bitlik registerden ikinci kez bir okuma daha yapılacak ve bu kez okunan verinin low 16 kısmı a4'e, high 16 kısmı ise a5 içine yerleşecektir.


Programimiz asagidaki gibi olacak.

void Fnk1()
{
//   Soruya cevap kodlariniz burada.
}

int main()
{
volatile char b0,b1,b2,b3; // Boyle yazilacak
volatile short b4,b5;      // Boyle yazilacak
volatile unsigned int i;

   InitCPU(); // Nasil yazdiginiz beni alakadar etmez

   Led_On() ; // Nasil yazdiginiz beni alakadar etmez

   for (i=0;i<0xFFFFFFFF;i++)
       {
         Fnk1();
         b0=a0; // Bu atama burada olsun da nasil atarsaniz atayin.
         b1=a1; // Bu atama burada olsun da nasil atarsaniz atayin.
         b2=a2; // Bu atama burada olsun da nasil atarsaniz atayin.
         b3=a3; // Bu atama burada olsun da nasil atarsaniz atayin.
         b4=a4; // Bu atama burada olsun da nasil atarsaniz atayin.
         b5=a5; // Bu atama burada olsun da nasil atarsaniz atayin.
       }
   Led_Off(); // Nasil yazdiginiz beni alakadar etmez
}

Asm kadar hızlı koşacağını iddia edeceğiniz C kodlarınızin basari olcusu = 1000 / (Ledin yanik kalma suresi(sn) * CpuClk(MHz)) 

Basari olcusunun degeri ne kadar buyukse yaziliminiz o kadar super demektir.

Ornegin lediniz 100ms de sonduyse Cpu frekansiniz 50Mhz ise 1000 /(0.1*50) den puaniniz 200 cikacaktir.
100ms lik sonucu 80Mhz islemcide elde ettiyseniz 1000/(0.1*80) den puaniniz 125'e dusecektir.

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

Kadir Can(16F84)

Hocam işi bayağı ilerletmişsiniz. :)
Bu hodri meydana cevap veren olursa zevkli ve öğretici bir yarışma izleyeceğiz.
Yalnız siz kıyaslamak için gereken ASM kodlarını vermemişsiniz.

ErsinErce

union {
			struct{
				unsigned char a0;
				unsigned char a1;
				unsigned char a2;
				unsigned char a3;
			} cbyte;
			struct{
				unsigned short a4;
				unsigned short a5;
			} cshort;
		}ersin __attribute__((at(0x40004000)));

	b0=ersin.cbyte.a0; // Bu atama burada olsun da nasil atarsaniz atayin.
        b1=ersin.cbyte.a1; // Bu atama burada olsun da nasil atarsaniz atayin.
        b2=ersin.cbyte.a2; // Bu atama burada olsun da nasil atarsaniz atayin.
        b3=ersin.cbyte.a3; // Bu atama burada olsun da nasil atarsaniz atayin.
        b4=ersin.cshort.a4; // Bu atama burada olsun da nasil atarsaniz atayin.
        b5=ersin.cshort.a5; // Bu atama burada olsun da nasil atarsaniz atayin.


fonksiyona gerek yok hocam asm kodları aşağıdaki gibi çıkıyor ama adreslemeyi tam yapamadım galiba iftardan sonra araştırırım

    94:                  b0=ersin.cbyte.a0; // Bu atama burada olsun da nasil atarsaniz atayin. 
0x08000D06 4822      LDR      r0,[pc,#136]  ; @0x08000D90
0x08000D08 7805      LDRB     r5,[r0,#0x00]
    95:          b1=ersin.cbyte.a1; // Bu atama burada olsun da nasil atarsaniz atayin. 
0x08000D0A 7846      LDRB     r6,[r0,#0x01]
    96:          b2=ersin.cbyte.a2; // Bu atama burada olsun da nasil atarsaniz atayin. 
0x08000D0C 7887      LDRB     r7,[r0,#0x02]
    97:          b3=ersin.cbyte.a3; // Bu atama burada olsun da nasil atarsaniz atayin. 
0x08000D0E F8908003  LDRB     r8,[r0,#0x03]
    98:          b4=ersin.cshort.a4; // Bu atama burada olsun da nasil atarsaniz atayin. 
0x08000D12 8800      LDRH     r0,[r0,#0x00]
0x08000D14 FA0FF980  SXTH     r9,r0
    99:          b5=ersin.cshort.a5; // Bu atama burada olsun da nasil atarsaniz atayin. 
0x08000D18 481D      LDR      r0,[pc,#116]  ; @0x08000D90
0x08000D1A 8840      LDRH     r0,[r0,#0x02]
0x08000D1C FA0FFA80  SXTH     r10,r0

camby

Bunalmış hoca , Cortex M3'e Assembly mi yazıyorsun ?

arslan74

Merhaba,

@cynetron arkadaşımız güzel bir örnek vermiş ancak ufak bir eksik var gibi. struct içinde tanımlı 32bit değişken yok.

typedef union {
	struct{
		unsigned char a0;
		unsigned char a1;
		unsigned char a2;
		unsigned char a3;
	} cbyte;
	struct{
		unsigned short a4;
		unsigned short a5;
	} cshort;
	unsigned long degisken_32bit;
} karisim_32bit;  //


kod içinde bu değişkeni tanımlayıb kullanacak.

Oda söyle olabilir.

karisim_32bit degiskenler; // istenirse değişkeni belirli bir adrese tanımlanabilir.

void Fnk1()
{

  degiskenler.degisken_32bit = okunan32bit; // ataması yapıldığında diğer bütün değişkenlere otomatik atama yapılmıştır.

}


Böyle kodla yapıldığında ASM hızlı mı olur, orası tartışılır. Ama kesin olan şudur ki; Okunaklılık, anlaşılırlık ve taşınabilrlik acısından tartışmasız bu şekilde yapılması gerekir. Hele 32 bit bir işlemcide bu atamanın hızı gözardı edilebilinir. 8 bit bir işlemcide 32 bit atama yapabilmek için 4 defa atamak yapmak gerekir oysa 32 bit bir işlemci tek atama ile yapabiliyorsunuz. Ama değişkenlerin uzunluğu 32 bit olarak saklanıyorsa ve bu 32bit sadece tekbir adres temsil ediliyorsa yani içindeki 8bitlere adresle erişemiyorsak bu seferde 8bit atamarı yapmak zorlaşacak. 32bit işlemciler hiç çalışmadığım için bu ayrıntıyı tam olarak bilemiyorum. Kullananlar bu ayrıntılı acıklar ise sevinirim.

Kolay gelsin.



z

#83
Alıntı yapılan: arslan74 - 22 Ağustos 2011, 02:00:59
.... 8 bit bir işlemcide 32 bit atama yapabilmek için 4 defa atamak yapmak gerekir oysa 32 bit bir işlemci tek atama ile yapabiliyorsunuz. Ama değişkenlerin uzunluğu 32 bit olarak saklanıyorsa ve bu 32bit sadece tekbir adres temsil ediliyorsa yani içindeki 8bitlere adresle erişemiyorsak bu seferde 8bit atamarı yapmak zorlaşacak. 32bit işlemciler hiç çalışmadığım için bu ayrıntıyı tam olarak bilemiyorum. Kullananlar bu ayrıntılı acıklar ise sevinirim.....

ARM CM3 islemciler icin cevabini vereyim.

32 bitlik veri 4 bytelik alani isgal ediyor.

Ornegin

0x20000000 adresine  8   bit veri yazarsaniz verinin adresi 0x20000000 olur ve 1 byte kaplar. 0x20000000
0x20000000 adresine  16 bit veri yazarsaniz verinin adresi 0x20000000 olur ve 2 byte kaplar. 0x20000000  0x20000001
0x20000000 adresine  32 bit veri yazarsaniz verinin adresi 0x20000000 olur ve 4 byte kaplar. 0x20000000  0x20000001 0x20000002  0x20000003

Fakat;

8 bitlik verileri herhangi bir adrese yazabilirken, 16 bitlik verileri sadece cift adreslere yazabiliyorsunuz.
32 bit verileri ise sadec 0 ve 4 un katlari adreslere.

Aksi takdirde bazi asm komutlarla bu verilere ulasilmak istenirse exception denen durum olusur. Bu yuzden C derleyici verinin uzunlguna gore gerekiryorsa  bos alanlar birakarak veri adrelerinde hizalama yapar.

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

arslan74

Merhaba,

Yanı bu durumda veriler Flash ve RAM de byte byte saklanıyor tıpki PC de olduğu gibi. O zaman union kullanmak gercekten cok avantaj getirecek. O zaman 32bit uzunuğundaki registerler hangisi oluyor. 32bit registerden 8 bit registere atama yapıldığında bu atama sanıl gercekleşiyor?

Bu kısım aydınlandığında Cok daha iyi optimum kod yazılabilinir.

Kolay gelsin.

z

#85
Alıntı yapılan: arslan74 - 22 Ağustos 2011, 02:50:11
Merhaba,

Yanı bu durumda veriler Flash ve RAM de byte byte saklanıyor tıpki PC de olduğu gibi. O zaman union kullanmak gercekten cok avantaj getirecek. O zaman 32bit uzunuğundaki registerler hangisi oluyor. 32bit registerden 8 bit registere atama yapıldığında bu atama nasil gercekleşiyor?

Bu kısım aydınlandığında Cok daha iyi optimum kod yazılabilinir.

Kolay gelsin.

ARM islemcide CPU registerleri (accumulator benzeri registerler) 32 bit. Birde cevre birimi registerleri var. Bunlardan bazilarida 32 bit.

32 bitlik bir CPU registerinin icerigini isterseniz 8 bitlik alana, isterseniz 16 bitlik alana isterseniz 32 bitlik alana yazabilirsiniz. Bunlarin her biri ayri asm kodu ile gerceklestirilir.

Eger 8 yada 16 bitlik alana 32 bitlik cpu registerleri uzerinden yanlis bir komutla aktarim yaparsaniz, 8 yada 16 bitlik verinin saklanacagi hedef adresini takip eden adreslerdeki verileri ezersiniz.

Eger pespese adreslerde 8 bitlik 4 ayri degiskeniniz varsa bunlardan ilkinin adresini kullanarak 4une birden 32 bit veriyi tek komutla yazabilirsiniz. (Endian tipini gozardi etmemek kaydiyla)

C yi ne kadar iyi bilirseniz bilin, yukarida sordugum soruda buyuk basari puani saglayacak  C kodlamasini, derleme sonunda uretilmis asm kodlarina baktiginizda, bu kodlari anlamadan yapamazsiniz.

C, editor icindeki gorunen kodlarin yakisikli, sade ve anlasilir olmasini saglar. Kod yalinligi konusunda Asm nin yeri ayridir.

C programim, saf asm ile yazilmis koda kiyasla sadece mikrosaniyeler mertebesinde yavas denilirrse, ortalikta fazlalik kodlar var demektir.
Cunku kucucuk bir program parcaciginda  fazlalik oluyorsa, buyuk program parcaciklarininda da buyuk fazlaliklar olacak demektir ve bunlar kodlarin belirgin sekilde yavaslamasina neden olur.

Bazi uygulamalarda, bazi program parcaciklarinda olusacak zaman kayiplarina tahammul olmaz. En basitinden int rutinleri. Tabiki extrem durumlardan bahsediyorum.
Hic kimse, bana muhasebe programini asm ile yazdiramaz.

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

arslan74

Merhaba,

Sayın @bunalmis vermiş olduğumuz yapıyı kullanma şansınız oldumu? ASM göre arasındaki farkı daha iyi kısyas yapmış oluruz.

Ben daha 32bit lere gecmediğim için şimdilik deneme şanşım yok.

Selamlar

z

Verdiğiniz yapıyı denemedim.

Fakat yapının daha önce verdiğim şekilde olması önemli. Yani;

void Fnk1()
{
//   Soruya cevap kodlariniz burada.
}

int main()
{
volatile char b0,b1,b2,b3; // Boyle yazilacak
volatile short b4,b5;      // Boyle yazilacak
volatile unsigned int i;

   InitCPU(); // Nasil yazdiginiz beni alakadar etmez

   Led_On() ; // Nasil yazdiginiz beni alakadar etmez

   for (i=0;i<0xFFFFFFFF;i++)
       {
         Fnk1();
         b0=a0; // Bu atama burada olsun da nasil atarsaniz atayin.
         b1=a1; // Bu atama burada olsun da nasil atarsaniz atayin.
         b2=a2; // Bu atama burada olsun da nasil atarsaniz atayin.
         b3=a3; // Bu atama burada olsun da nasil atarsaniz atayin.
         b4=a4; // Bu atama burada olsun da nasil atarsaniz atayin.
         b5=a5; // Bu atama burada olsun da nasil atarsaniz atayin.
       }
   Led_Off(); // Nasil yazdiginiz beni alakadar etmez
}

Soruyu soran olarak, soruyu çözeceklere, buradaki b değişkenlerini  structure yapısında kurmamaları için daha en baştan onları main içinde char tipinde ayrık değişkenler olarak tanımladım. A nın nasıl tanımlandığını size bırakmıştım.

Fnk1'de fonksiyon olarak dışarda özellikle tuttum. Bunu ana programın içine aldığınız takdirde otomatik olarak Call ve Return işlemi yapan asm komutlarını kaldırmış ve en azından 2 komut kısalma yapmış olursunuz. Bu da başarı puanınızı artıran bir durumdur.

İlerleyen dönemde  bir porttan kare dalga üretiminde kod uzunluğunun frekansa olan etkisi üzerine ara konu açacağım.
Bu konu altında C nin asm'ye kıyasla daha fazla kod üretmesinin band genişliğimize olan etkisini ve bu etkinin hangi durumda etkisini yitirmeye başladığını inceleyeceğiz.

@Aslan74

Bu devirde ARM kiti olmayan bir elektronikçi düşünemiyorum.






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

ErsinErce

b tipi değişkeni ellemeden direk a yı structure olarak tanımlamıştım ve belirtilen bölgeye yerleştirmiştim,
tabi ki call return clock kaybına yol açar ve sistemi etkiler ama bunun önüne geçmek içinde C de inline fonksiyonlar mevcut

ayrıca @arslan74 hocam union içine harici bir 32 bit daha koymaya gerek yok, eğer 32 bitlik bir giriş yapmıyorsak,
structure boyutları 32 bit olduğundan linker o alanı 32 bit olarak ayıracaktır

CLR

Alıntı yapılan: arslan74 - 22 Ağustos 2011, 02:50:11
Merhaba,

Yanı bu durumda veriler Flash ve RAM de byte byte saklanıyor tıpki PC de olduğu gibi. O zaman union kullanmak gercekten cok avantaj getirecek. O zaman 32bit uzunuğundaki registerler hangisi oluyor. 32bit registerden 8 bit registere atama yapıldığında bu atama sanıl gercekleşiyor?

Bu kısım aydınlandığında Cok daha iyi optimum kod yazılabilinir.

Kolay gelsin.

Merhaba,

32bit işlemciler byte byte veri saklıyor ve program counter, hafızaya byte yazılırken 1, half word yazılırken 2 ve word yazılırken 4 adım atlar.  Dolayısıyla 32bit için 4 byte yazar ve PC+=4 olur.

Dediğin gibi Union yapı işlemcinin çalışma performansını etkilemez çünkü zaten işlemci byte erişimli. Ve örneğini verdiğin union 8bit,16bit,32bit erişimi çalışıyor. Hatta senin verdiğin yapıda eksik denebilir, istenirse içine 1 bit erişimde eklenebilir.
   

Knowledge and Experience are Power