Отговори на тема  [ 31 мнения ]  Отиди на страница 1, 2, 3  Следваща
GCC - НЕинициализирани променливи? 
Автор Съобщение
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пон Сеп 27, 2004 9:22 am
Мнения: 15501
Местоположение: София
Мнение GCC - НЕинициализирани променливи?
Как се обявява в GCC статична променлива която не се инициализира от startup кода?

_________________
"Да еба и шибаната държава" мислеше си Гошо, докато се опитваше да улучи кофата за боклук от балкона на осмия етаж.


Сря Май 27, 2009 2:02 pm
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Сря Яну 26, 2005 2:01 pm
Мнения: 1952
Местоположение: Варна
Мнение 
Аз правя отделна секция в линкер скрипта и после в сорса използвам това:
Код:
uint32   g_ulResetID      __attribute__((section(".noinit_variables")));

_________________
Най-опасният враг на истината и свободата е мнозинството.


Сря Май 27, 2009 2:24 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Вто Юли 31, 2007 2:55 pm
Мнения: 1792
Местоположение: София
Мнение 
Какво имаш предвид под неинициализирана?

Както казва Zdrav, правиш си твоя секция в линкер скрипта и си я слагаш в нея с атрибута за секция.


Сря Май 27, 2009 3:10 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пон Сеп 27, 2004 9:22 am
Мнения: 15501
Местоположение: София
Мнение 
Мда. Ама тоя линкерски език ми е много тегав.

Как точно се обяснява на линкера, кои секции трябва да се инициализират и кои не?

Иначе става дума точно за променлива обслужваща кучето.....

_________________
"Да еба и шибаната държава" мислеше си Гошо, докато се опитваше да улучи кофата за боклук от балкона на осмия етаж.


Сря Май 27, 2009 3:49 pm
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Вто Юли 31, 2007 2:55 pm
Мнения: 1792
Местоположение: София
Мнение 
Преди да се викне "main()" се изпълнява малко кодец обикновено с име близко до CRT0, идва от "C runtime".
Там се прави каквото се прави за съответната платформа/OS. Например се занулява ".bss" секцията и ".data" се копира от ROM ако е била такава постановката.

Така че каквато и твоя секция да сложиш, никой няма да ти я прави нищо. :)

Има и друг вариант. Понеже секциите на обектните файлове се събират после в секции на изходния файл (и това се указва от линкер скрипта как точно да става), можеш дори да не правиш специална изходна секция. Достатъчно е да укажеш някаква твоя обектна секция, примерно ".ceco" и после в скрипта да я набуташ в ".text" примерно ако адресното пространсто за код и данни е едно и също и позволява писане (зависи от постановката ти). Или в коя да е друга която отговаря на изискванията ти.

Пример:

Код:
int special_var __attribute__((section(".ceco")));


Код:
SECTIONS {
        .text : {
                ...
                * (.ceco)
                ...
        }


Линкер-скрипт парчето указва обектната секция ".ceco" да се разположи в изходната ".text".


Сря Май 27, 2009 4:38 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Вто Юли 31, 2007 2:55 pm
Мнения: 1792
Местоположение: София
Мнение 
А ето и един още по-лесен вариант. Изключи някаква област от RAM-та от линкер скрипта, т.е. да не се ползва.
Направи си структура и указател към нея. Инициализирай указателя към парчето директно с абсолютен адрес щом не ти се занимава с линкер скриптове. Воала! Имаш NV променливи (каквато разбирам ти е целта).

Код:
struct nv {
    int wd;
    int prm1, prm2, prm3;
    // ...
} *nv;

// ...

nv = (struct nv *)0xFFFF0000;    // at upper 64K

nv->wd = 0;
nv->prm1 = ...


Сря Май 27, 2009 4:44 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пон Сеп 27, 2004 9:22 am
Мнения: 15501
Местоположение: София
Мнение 
Бе това ми е горе долу ясно. Това което не ми е ясно е как се обяснява коя секция какво да я прави компилатора?

Т.е. къде се указва че точно bss трябва да се занули, а точно data да се копира от ROM-a? Гледам линкерския скрипт не виждам подобни "разяснения" в него.

.text ми е в FLASH-а, т.е там променливи няма какво да търсят.

_________________
"Да еба и шибаната държава" мислеше си Гошо, докато се опитваше да улучи кофата за боклук от балкона на осмия етаж.


Сря Май 27, 2009 4:45 pm
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Фев 26, 2006 6:52 pm
Мнения: 11278
Местоположение: Добрич
Мнение 
1. Компилаторът генерира обекти - променливи, константи и всякакви други глупости, като за всеки обект се указва секция в обектния файл.
По принцип ти с __attribute__ може да кажеш в коя секция искаш дадения обект да бъде разположен, но ако не го направиш ще ти я наблсъка в съответната секция по подразбиране. Поне засега не ми попадала документация относно всички секции по подразбиране. Така че за bss, text и т.н. се ориентирам, но има и разни други дето пък не ги разбирам...

2. Линкерският скрипт описва как от многото обектни файлове и техните секции да се сглоби изходен файл. Така ти на практика определяш разпожението на секциите от обектните файлове в изходния файл (това което казва woody).

3. Линкерът изпълнявайки скрипта разполага всяко нещо на мястото му (евентуално премахва ненужните неща) но в крайна сметка всеки обект си получава конкретни адреси. Включително се изчисляват и константите (етикетите).

4. Обикновено имаш два етикета между които се разполагат променливите в RAM-a. Примерно при мен е:

Код:
   .zero (NOLOAD) :
   {
        _szero = .;
       *(.bss)
      *(.bss.*)
      *(.gnu.linkonce.b.*)
       *(COMMON)
       . = ALIGN(4);
        _ezero = .;
     } >ram


В случая това са _szero и _ezero. Между тези два адреса линкера ще разположи BSS-те на всички (*) обектни файлове...

5. В стартъп кода имам едно цикълче дето нулира паметта между _szero и _ezero



Накратко казано компилатора нищо не указва (освен кое в коя секция на обектния файл се намира). Линкерът (и скрипта) реално разполагат нещата. А стартъп кода е отговорен за нулирането.

С други думи по подразбиране нищо в GCC не се инициализира и даже няма изобщо да се линкне. Забрави за С-стандандартите дето ти казват, че static глобална променлива трябва да се нулира - ще се нулира само ако ТИ вкараш такъв линкерски скрипт и стартъп код и го извикаш този код и при това го извикаш навреме (преди да си разрешил прекъсванията).


Сря Май 27, 2009 6:34 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Вто Юли 31, 2007 2:55 pm
Мнения: 1792
Местоположение: София
Мнение 
Цецо, ела с лапнитоп на бира и ще дигнем мъглата. :drinkers:


Сря Май 27, 2009 6:51 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Сря Яну 26, 2005 2:01 pm
Мнения: 1952
Местоположение: Варна
Мнение 
Цецо написа:
Бе това ми е горе долу ясно. Това което не ми е ясно е как се обяснява коя секция какво да я прави компилатора?

Т.е. къде се указва че точно bss трябва да се занули, а точно data да се копира от ROM-a? Гледам линкерския скрипт не виждам подобни "разяснения" в него.

.text ми е в FLASH-а, т.е там променливи няма какво да търсят.


Не че знам повече от woody и miro_atc ама гледам, че има леко разминаване между въпросите и обясненията. По подразбиране всяка глобална променлива която е инициализирана с нещо различно от нула отива в .data секцията. Всички останали глобални променливи отиват в .bss. Стартъп кода е този който решава коя секция да се занули и коя да се копира и коя да не се пипа. miro_atc го е обяснил по-горе механизма. В стартъп кода са видими адресите за начало и край на секциите. И с едно просто цикълче се извършва нулиране или копиране.
Като си направиш твоя секция гледай да не съвпадне името и с някоя от стандартните все пак. Щом като са променливи естествено че ще е в RAM. Може да си направиш и отделна изходна секция съдържаща само твоята входна секция.
Код:
.noinit_out_section(NOLOAD) :
   {
       *(.noinit)
     } >ram

В стартъп кода просто тази секция няма да се пипа. За да се прави там нещо с нея трябва да си драснеш собственоръчно код в стартъп файла.

_________________
Най-опасният враг на истината и свободата е мнозинството.


Сря Май 27, 2009 9:02 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пон Сеп 27, 2004 9:22 am
Мнения: 15501
Местоположение: София
Мнение 
Ясно. Утре ще пробвам.

А гледам че в моя линкерски скрипт (който съм присвоил), за .data и .bss са дефинирани като:

Цитат:
.data : ALIGN ( 8 )
{
__cs3_region_start_ram = .;
*(.cs3.region-head.ram)
KEEP(*(.jcr))
*(.got.plt) *(.got)
*(.shdata)
*(.data .data.* .gnu.linkonce.d.*)
. = ALIGN ( 8 );
*(.ram)
_edata = .;
} >ram AT>rom
.bss :
{
*(.shbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
. = ALIGN ( 8 );
*(.ram.b)
_end = .;
__end = .;
} >ram AT>rom


1. Що за животно е обект от тип COMMON?

2. >ram АТ>rom - що чини тоя "ром" тука?

@woody - Абе ти за какъв човек ме имаш? Ще дойда да пием бира и ще седна да с лаптопа да чопля подобни дивотии? Как пък не. Ай сиктир :) Бирата трябва да се уважава.

_________________
"Да еба и шибаната държава" мислеше си Гошо, докато се опитваше да улучи кофата за боклук от балкона на осмия етаж.


Сря Май 27, 2009 9:39 pm
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Вто Юли 31, 2007 2:55 pm
Мнения: 1792
Местоположение: София
Мнение 
Тези готовите линкер скриптове са пълни с какви ли не неща за да угаждат на всички конфигурации и варианти.

1) COMMON са едни стари UNIX разбирания за неинициализираните променливи, че може да ги декларираш във всеки обектен файл и линкерът ги припокрива после. Отсвири го, това е мухъл от някога-бешило, дори ако можеш слагай "-fno-common" че да врещи при дефиниция на повече от едно място.

2) Това най-вероятно са run и load адресите. Run е виртуалния, адресът с който ще се резолвира дадено име. Load е къде физически ще бъде в имиджа.


Аз си пиша мои кратки линкер скриптове и CRT0 и си контролирам всичко. Не е трудно и помага за цялостния контрол. Така знам кои променливи са инициализирани, как, кога и т.н. ;)

Цената е малко RTFM първия път, после всичко си идва на мястото. Тези концепции са си същите от десетилетки и за щастие всичко е просто и логично.


Сря Май 27, 2009 10:03 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пон Сеп 27, 2004 9:22 am
Мнения: 15501
Местоположение: София
Мнение 
Следващ въпрос:

Как да напъхам константен стринг на специфичен адрес? Трябва ли да му правя отделна секция???? Не мога ли да го направя директно от кода с някакъв атрибут? Нещо от сорта на:

const char str[] = "bla-bla" __атрибут тури го ей тука.

_________________
"Да еба и шибаната държава" мислеше си Гошо, докато се опитваше да улучи кофата за боклук от балкона на осмия етаж.


Вто Юни 16, 2009 12:35 pm
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Сря Яну 26, 2005 2:01 pm
Мнения: 1952
Местоположение: Варна
Мнение 
Не, по същия начин със отделна секция се прави.

_________________
Най-опасният враг на истината и свободата е мнозинството.


Вто Юни 16, 2009 12:42 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Вто Юли 31, 2007 2:55 pm
Мнения: 1792
Местоположение: София
Мнение 
С атрибут не може. Нямам под ръка за проба в момента, но пробвай да сложиш в линкер скрипта в правилната секция:

str = 0x1234;


Другите начини са с отделна секция, като аз лично бих сложил всички такива "фиксирани" данни в една структура.


Вто Юни 16, 2009 12:52 pm
Профил
Покажи мненията от миналия:  Сортирай по  
Отговори на тема   [ 31 мнения ]  Отиди на страница 1, 2, 3  Следваща

Кой е на линия

Потребители разглеждащи този форум: 0 регистрирани и 6 госта


Вие не можете да пускате нови теми
Вие не можете да отговаряте на теми
Вие не можете да променяте собственото си мнение
Вие не можете да изтривате собствените си мнения
Вие не можете да прикачвате файл

Търсене:
Иди на:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.
Хостинг и Домейни