Picproje Elektronik Sitesi

DERLEYİCİLER => Diğer Derleyiciler => IAR => Konuyu başlatan: fatihinanc - 07 Temmuz 2011, 09:52:12

Başlık: Stack ve Heap Bölgesi Hakkında
Gönderen: fatihinanc - 07 Temmuz 2011, 09:52:12
Merhaba,

Bir projemde MSP430 ile sıcaklık ölçümü yapmam gerekiyordu ve kodu IAR da yazdım, bitirdim.
Fakat debug ederken alt kısımda Stack dolu diye bir uyarı çıktığını farkettim.
Stack alanı için 80 byte yer ayırılıyormuş. Ayarlardan tekrar düzelttim ve Stack alanını da Heap alanını da 170 byte yaptım.
Sonra debug menüsünde hiçbir uyarı çıkmamaya başladı. 170 baytın toplam 138 baytı kullanılıyor şu an.

Aslında kodu yazarken böyle birşey olacağını tahmin etmiştim ama 80 baytı da geçeceğini düşünmemiştim.
Toplamda 3 kere iç içe fonksiyon çağırıyorum. Bu kadar yüksek yer kaplamasının nedenini anlayamadım.
Program fonksiyona dallandığı anda kaldığı adresi stack e yüklediğini biliyorum. Ve eğer bu alan dolarsa da programın düzgün çalışmayacağını da biliyorum.

Sorum ise şu : Stack ve Heap alanlarının organizasyonu derleyici tarafından nasıl yapılıyor ?
Ve bu kadar yüksek bellek gereksinimine neden ihtiyaç duyuluyor ?


NOT : 16 bit MSP430 kullanıyorum. Toplam flash = 8kb, RAM = 256 Byte

Kodun tamamını ekleyip işi iyice anlaşılmaz hale getirmek istemediğimden sadece gerekli kısmı ekliyorum.
Sonradan ihtiyaç olursa tamamını ekleyebilirim.

Bu konu hakkında fikir sahibi olan forumdaki üstadlardan yardım bekliyorum.


#include "io430.h"
#include "in430.h"
#include "yazilimsal_uart.h"
#include "adc.h"

extern unsigned int txData;
unsigned int sicaklik=0;
 
unsigned int hesapla(unsigned int* gelen_s);
void sicaklik_gonder(unsigned int gelen_t);

void main( void )
{
  unsigned int sicaklik_dizi[64];
  .
  .
  .
  __enable_interrupt();

  TimerA_UART_init(); 
  adc_init();

  TimerA_UART_print("MSP430G2452 -> ADC -> UART\r\n");
  TimerA_UART_print("Sicaklik Olcme Uygulamasi\r\n"); 
 
  while(1)
  {
    ADC10CTL0 &= ~ENC;
     
    while (ADC10CTL1 & BUSY);         
    ADC10SA = (unsigned int)sicaklik_dizi;
    ADC10CTL0 |= ENC + ADC10SC;
   
    sicaklik_gonder(hesapla(sicaklik_dizi));

    _NOP(); //breakpoint için...
  }
}

unsigned int hesapla(unsigned int* gelen_s)
{
  unsigned int toplam=0;

  for(char i=0;i<64;i++)
    toplam+=gelen_s[i];
 
  sicaklik=sicaklik_oku(toplam>>=6);
 
  _NOP(); //breakpoint için...

  return sicaklik;
}
Başlık: Ynt: Stack ve Heap Bölgesi Hakkında
Gönderen: z - 07 Temmuz 2011, 10:15:55
İşlemcinle uğraşmadım bu yüzden kesin konuşmuyorum.

Herşeyden önce işlemci 16 bit. Stackda geri dönüş adresleri 2 byte byte saklanıyor.
Aynı şekilde saklanması gereken registerler de stackta 2 byte byte yer kaplıyor.
Eğer C kullanıyorsan fonskiyonlara parametre aktarımı gene stack üzerinden gerçeleşir.
Float işlemler yazboz alanı ister ve bunun için gene stack alanından yararlanılır.
Fonksiyonlarındaki lokal değişkenler de stack alanından yer çalar.


Başlık: Ynt: Stack ve Heap Bölgesi Hakkında
Gönderen: fatihinanc - 07 Temmuz 2011, 17:28:28
@bunalmis hocam
Haklısınız. Bahsettiğiniz tüm işlemler programda yapılıyor. Hem float hesaplaması hem de bir fonksiyona 64 lük int (64 x 2 = 128 b) dizi aktarıyorum.
Muhtemelen bundan olsa gerek. Bu programda hafıza sorunum yok ondan dolayı stack alanını arttırabiliyorum fakat ileride belki problem olur diye sebebini şimdiden öğrenmek istedim.
Bu arada stack %90 dolunca uyarı veriyormuş şu an 150 bayt stack ihtiyacı var ben de 152 bayt stack alanı tanımladım ve toplamda da 157 bayt RAM kullanıyorum ;)

@FxDev
Dedğin bugün öğlen aklıma geldi aslında. Diziden olduğundan şüphelendim fakat bunun tek alternatifi o diziyi global tanımlamak olacağından o da işime yaramayacaktı ki öyle oldu.
Diziyi global tanımladım. RAM kullanımı 160 baytlardan 213 bayta çıktı. Fakat stack alanında dediğin gibi azalma oldu. Ama totalde işe yaramıyor ;)

Üstadlar yardımcı olduğunuz için teşekkür ediyorum.

Heap alanı hakkında bir fikri olan var mı peki ? Ben hem heap alanını hem de stack alanını 152 bayt tanımladım çünkü...
Başlık: Ynt: Stack ve Heap Bölgesi Hakkında
Gönderen: Klein - 08 Temmuz 2011, 22:42:29
Alıntı YapHeap alanı hakkında bir fikri olan var mı peki ? Ben hem heap alanını hem de stack alanını 152 bayt tanımladım çünkü...

OOP programlamada nesneleri tutmak için ayrılmış alan.  Aslında bir çeşit stack. Ama Stack alanında  değişkenler tutulurken , heap alanında nesneler ( sınıflar , class) tutulur.
C++ için gerekli bir ayar. C'de bir işlevi var mı bilmiyorum. Belki yapılar(struct) burada tutuluyor olabilir. Emin değilim.

diziyi global alanda tutmak neden işini görmedi? 
Başlık: Ynt: Stack ve Heap Bölgesi Hakkında
Gönderen: fatihinanc - 08 Temmuz 2011, 23:22:29
Alıntı yapılan: Klein - 08 Temmuz 2011, 22:42:29
diziyi global alanda tutmak neden işini görmedi? 

Anladım hocam sağolun.
Diziyi global alana aldığım zaman toplam kullanılan bellek miktarı arttı. Normalde 160 bayt (152 bayt stack için ayrılıyor) civarında olan RAM kullanımı 213 bayta çıktı.
Zaten bu şekilde de ancak stack alanını azaltınca kodu derleyebiliyorum. Çünkü toplam hafızam 256 bayt.

Ben de stack alanını geniş tutup diziyi local alanda tanımlayarak bellekten tasarruf sağlamayı seçtim.
Başlık: Ynt: Stack ve Heap Bölgesi Hakkında
Gönderen: fatihinanc - 08 Temmuz 2011, 23:37:23
Az önce tekrar denedim. Normalde diziyi global alana alınca stack kullanımı 22 bayta düşüyor.
Eğer ben de maksimum stack alanını 24 bayt yaparsam toplam RAM kullanımı 157 bayt oluyor.

dizi localde iken de toplam RAM kullanımım 157 bayt idi.

Fakat ben dizi alanını globalde tutmak yerine localde tutmanın daha iyi olacağını düşünüyorum.
Neticede dizinin kullanılmadığı bloklarda bu alan yerine başka değişkenler iş yapabilecek.
Globalde ise o alanlar programın başından sonuna kadar dizi için ayrılacak diye biliyorum.
Doğru mudur?
Başlık: Ynt: Stack ve Heap Bölgesi Hakkında
Gönderen: Klein - 08 Temmuz 2011, 23:41:55
:) Yok aslında öyle olmayacak.
Çünkü:
Dizi "main" fonksiyonu içinde tanımlı.  Main fonksiyonuna ilk girişte o dizi için stack ayrılacak. Ancak siz "main" fonksiyonundan hiç çıkmadığınız için o dizi için ayrılan stack alanı hiç boşaltılmayacak.

Ben olsam stack'i  rahatlatmaya çalışırdım.
Başlık: Ynt: Stack ve Heap Bölgesi Hakkında
Gönderen: fatihinanc - 08 Temmuz 2011, 23:47:18
 :o
Ama ana döngü içerisinde fonksiyondan fonksiyona toplam 3 kere geçiş yapıyorum hocam.
O geçişlerde burayı boşaltması lazım ki debug ekranında diğer fonksiyonların içindeki satırlara breakpoint koyup içeriği gözlemlediğim zaman bu dizinin değişkenlerini göremiyorum.
içerikler Unknown... olarak görünüyor.
Başlık: Ynt: Stack ve Heap Bölgesi Hakkında
Gönderen: Klein - 08 Temmuz 2011, 23:57:51
Boşaltmaz.
Bir fonksiyonun değişkenlerininin yığından boşaltılmasının şartı fonksiyondan çıkmaktır.  içiçe yazdığımız fonksiyonlarda stack şişmesinin sebebi de budur.  Sen fonksiyondan fonksiyona geçiş yapmıyorsun. Main fonksiyonu içinde başka bir fonksiyon çağırıyorsun.
Şöyle düşün.
Bir fonksiyon çağırdık fonksiyon işlenirken başka bir fonksiyon çağırdık. ilk fonksiyonumuzun bilgileri nerede? stack'te , sonra bir fonksiyon daha çağırdık önceki fonksiyonumuzun içeriği nerede? stack'te
eğer böyle olmasaydı fonksiyon içinde fonksiyon çağırdığımızda önceki fonksiyonun içeriği kaybolmaz mıydı? ya da stack şişer miydi?
Main de sonuçta bir fonksiyon. Main içerisinde başka fonksiyon çağırman main fonksiyonunu sonlandırmaz.
Program eğer stack üzerinde bir array açtıysa  onun neresi kullanılmış , neresi kullanılmamış bakmaz. Çünkü çok farklı yollardan , dolaylı adresleme ile vs.. oraya veri atmış olabilirsin. O alanı başka birine kullandırması çok ciddi karışıklıklara neden olabilir.
Başlık: Ynt: Stack ve Heap Bölgesi Hakkında
Gönderen: fatihinanc - 09 Temmuz 2011, 00:09:53
Anladım hocam. Haklısınız. bu şekilde fonksiyon sonlanmıyor. Hem de diğer fonksiyona geçişte bu bilgileri stacke attığı için stack doluyor.
Az önce tekrar debugtan baktım stack tamamen 64 lük dizi ile dolu neredeyse...

Bu alanı globalde tutup stacki daha geniş(rahat) tutmayı tavsiye ediyorsunuz...
Peki hocam sağolun vakit ayırıp ilgilendiğiniz için...
Başlık: Ynt: Stack ve Heap Bölgesi Hakkında
Gönderen: camby - 04 Aralık 2012, 10:31:58
Donanımsal Stack ve yazılımsal stack farklı yerler değil mi ?

Bir fonksiyona giderken , geri dönülecek yerin adresini tutan stack alanı donanımsal alan. Push pop Call return gibi komutlardan etkilenen alan burası.

Bunun dışında yukarıda bahsettiğiniz fonksiyon parametreleri ve local değişkenler de ayrıca tanımlanmış yazılımsal bir stack alanında mı saklanıyor ?

Fonksiyona ait parametreler ve local değişkenler bu donanımsal stack alanına kayıt ediliyor mu ?

( Bunları genel olarak soruyorum MSP için yada IAR için değil  )
Başlık: Ynt: Stack ve Heap Bölgesi Hakkında
Gönderen: z - 04 Aralık 2012, 11:15:37
Cevabı kullanılan işlemciye de bağlı.

Donanımsal stack, return adresi yanısıra, parametre aktarımı için de kullanılır.

Bu tür numaralarda işlemcinin yetenekleri çok ön plana çıkıyor.

Yazılımsal stack olayına ihtiyaç CPU nun beceriksizliğinden.
Başlık: Ynt: Stack ve Heap Bölgesi Hakkında
Gönderen: camby - 04 Aralık 2012, 12:08:06
18f'lerde tek stack dönüş adresi için bildiğim kadarıyla.

M3 , M4 'de durum nasıl ? Donanım destekliyor mu peki ?


Yazılımsal olarak oluşturacağım ben de..
Başlık: Ynt: Stack ve Heap Bölgesi Hakkında
Gönderen: camby - 04 Aralık 2012, 14:52:32
Gerbay hocam , konu biraz eski ancak başlıkta konuşulmuşlar yararlı olduğu olduğu için bu konu altına yazayım dedim ben de.

ASM ortamına bir stack yapısı oluşturmaya çalışıyordum , çünkü kesmede aynı fonksiyonları tekrar tekrar kullanınca datalarım bozuluyor. Donanımsal ekstra bir FIFO'ya sahip değil 18f , yazılımsal yapmaya da karar veremedim henüz. RAM çok o yüzden şuan lık kritik ram alanlarını kesmeye giderken yedekliyorum.
Başlık: Ynt: Stack ve Heap Bölgesi Hakkında
Gönderen: fatihinanc - 05 Aralık 2012, 00:16:14
Selamlar,

Konu biraz eskimiş ama bilgiler faydalı olabilir.

@camby hocam,
Kullandığımız 8-16 bit kontrolörlerin çoğunda stack için ayrı bir FIFO yok diye biliyorum.
Editör'de stack alanı için kullanacağınız boyutu belirledikten sonra derleme sonucunda derleyici "Sen kullansan da kullanmasan da ben RAM den bu alanı stack için ayırdım arkadaş !" diyor aslında. Ve ona göre de normale göre daha fazla RAM kullanımı çıktısı veriliyor.

@gerbay hocam stack ve heap i çok güzel anlatmış aslında. Ben bu başlığı açtığımda hala bazı yerler oturmamıştı. Yakın zamanda bir kaynaktan okuduktan sonra iyice anladım. Benim okuduğumun tam özeti olmuş bu anlatım.

Bu arada IAR'dan elf çıktısını aldım. Aşağıda;
http://bit.ly/THJZtt (http://bit.ly/THJZtt)
Başlık: Ynt: Stack ve Heap Bölgesi Hakkında
Gönderen: yamak - 05 Aralık 2012, 10:26:40
@gerbay hocam
Alıntı Yapeğer sizin programınızda malloc/calloc/alloc/strdup/new     vs. çağrısı yapılmıyorsa hiç bir zaman (kullandığınız kütüphanelerin içi dahil) bu durumda heap in boyunu 0 (sıfır) olarak tanımlayın boş yere yer ayrılmasın..
Bunun tam tersi de doğru mudur.Yani en ufak bir dinamik bellek tahsisi yapsak heap artırmak zorunda mıyız? Yani start up dosyasında heap i 0 olarak bıraksak dinamik bellek tahsisatı yapamaz mıyız?
Bi de bu stack olayı mimariye göre değişiyo değil mi? Yani PIC MCU larda stack te artırıp azaltma yapamyız di mi? Çünkü PIC lerde stack ram den ayrı biryer.
Başlık: Ynt: Stack ve Heap Bölgesi Hakkında
Gönderen: yamak - 05 Aralık 2012, 11:26:15
Peki hocam fragmentation oluşmaması için nasıl bi yol izlememiz gerekir.Ya da dinamik bellek kullanıyorsak bu durum kaçınılmaz mı?
Başlık: Ynt: Stack ve Heap Bölgesi Hakkında
Gönderen: Tagli - 05 Aralık 2012, 11:33:00
İşletim sistemleri bu sorunu nasıl çözüyor? İşletim sistemi kullanmasak bile, belli aralıklarla çalışıp hafızayı düzene sokan bir programcık yazabilir miyiz? Bu durumda mevcut adresleme yapısının çökmesi nasıl engellenir? Modern işletim sistemlerinde kullanılan sanal bellek olayının çıkış noktası bu mu? Yani program içinde sanal adresler değişmiyor ama ayrılan alan programın haberi olmadan başka bir yere taşınabiliyor (yanlış bilmiyorsam...).
Başlık: Ynt: Stack ve Heap Bölgesi Hakkında
Gönderen: z - 05 Aralık 2012, 12:19:20
Alıntı yapılan: Tagli - 05 Aralık 2012, 11:33:00
İşletim sistemleri bu sorunu nasıl çözüyor? İşletim sistemi kullanmasak bile, belli aralıklarla çalışıp hafızayı düzene sokan bir programcık yazabilir miyiz? Bu durumda mevcut adresleme yapısının çökmesi nasıl engellenir? Modern işletim sistemlerinde kullanılan sanal bellek olayının çıkış noktası bu mu? Yani program içinde sanal adresler değişmiyor ama ayrılan alan programın haberi olmadan başka bir yere taşınabiliyor (yanlış bilmiyorsam...).

İşlemcinin memory erişim komutları adresi iki registerin toplamı şeklinde kullanabiliyorsa bu dediğiniz oldukça kolay bir işlem.

Örneğin MOV  A,[B+C] gibi sanal bir komut düşün.

Memory'nin 0x1000 adresinde değişkenlerin olsun.

B=0x1000 yaptığında örneğin C=0......0x100 aralığında program 0x1000...0x1100 aralığındaki değişkenlere erişir.

Programdaki jump adresler, relatif adres olarak oluşturulduğunda artık hiç sorun kalmaz.

Aynı programı dilediğin adrese taşıyabilirsin.  Değişkenleri de 0x2000...0x2100 aralığında kullanmak istersen

Bu durumda sadece B=0x2000 yapman yeterli olur.

Bu durumda programda hiç bir değişiklik yapmana gerek kalmaz.
Başlık: Ynt: Stack ve Heap Bölgesi Hakkında
Gönderen: z - 05 Aralık 2012, 17:20:59
Hocam PC lerde dediğim gibi değilmi?

İşletilecek exe program çalıştırılmak istendiğinde programın, ramın hangi adresine yükleneneceği, değişkenlerin hangi adrese yerleşeceği program yazım aşamasında en başta kestirilemez.

Fakat işletim sistemi ramın o anki kullanılabilir durumdaki adresine programı yükler CS, DS, ES işletim sistemi tarafından init edilir ve kod koşmaya bırakılır.

MMU kullanmadan ARM işlemcide pozisyondan bağımsız kod yazmamı engelleyen durum nedir?

80x86 da da ARM işlemcide de MMU suz bu iş olur çünkü işlemcinin adresleme yeteneği bu işe uygun.