| Автор |
Съобщение |
|
Цецо
Ранг: Форумен бог
Регистриран на: Пон Сеп 27, 2004 9:22 am Мнения: 15501 Местоположение: София
|
 GCC - НЕинициализирани променливи?
Как се обявява в GCC статична променлива която не се инициализира от startup кода?
_________________ "Да еба и шибаната държава" мислеше си Гошо, докато се опитваше да улучи кофата за боклук от балкона на осмия етаж.
|
| Сря Май 27, 2009 2:02 pm |
|
 |
|
Zdrav
Ранг: Форумен бог
Регистриран на: Сря Яну 26, 2005 2:01 pm Мнения: 1952 Местоположение: Варна
|
Аз правя отделна секция в линкер скрипта и после в сорса използвам това:
_________________ Най-опасният враг на истината и свободата е мнозинството.
|
| Сря Май 27, 2009 2:24 pm |
|
 |
|
woody
Ранг: Форумен бог
Регистриран на: Вто Юли 31, 2007 2:55 pm Мнения: 1792 Местоположение: София
|
Какво имаш предвид под неинициализирана?
Както казва Zdrav, правиш си твоя секция в линкер скрипта и си я слагаш в нея с атрибута за секция.
|
| Сря Май 27, 2009 3:10 pm |
|
 |
|
Цецо
Ранг: Форумен бог
Регистриран на: Пон Сеп 27, 2004 9:22 am Мнения: 15501 Местоположение: София
|
Мда. Ама тоя линкерски език ми е много тегав.
Как точно се обяснява на линкера, кои секции трябва да се инициализират и кои не?
Иначе става дума точно за променлива обслужваща кучето.....
_________________ "Да еба и шибаната държава" мислеше си Гошо, докато се опитваше да улучи кофата за боклук от балкона на осмия етаж.
|
| Сря Май 27, 2009 3:49 pm |
|
 |
|
woody
Ранг: Форумен бог
Регистриран на: Вто Юли 31, 2007 2:55 pm Мнения: 1792 Местоположение: София
|
Преди да се викне "main()" се изпълнява малко кодец обикновено с име близко до CRT0, идва от "C runtime".
Там се прави каквото се прави за съответната платформа/OS. Например се занулява ".bss" секцията и ".data" се копира от ROM ако е била такава постановката.
Така че каквато и твоя секция да сложиш, никой няма да ти я прави нищо.
Има и друг вариант. Понеже секциите на обектните файлове се събират после в секции на изходния файл (и това се указва от линкер скрипта как точно да става), можеш дори да не правиш специална изходна секция. Достатъчно е да укажеш някаква твоя обектна секция, примерно ".ceco" и после в скрипта да я набуташ в ".text" примерно ако адресното пространсто за код и данни е едно и също и позволява писане (зависи от постановката ти). Или в коя да е друга която отговаря на изискванията ти.
Пример:
Линкер-скрипт парчето указва обектната секция ".ceco" да се разположи в изходната ".text".
|
| Сря Май 27, 2009 4:38 pm |
|
 |
|
woody
Ранг: Форумен бог
Регистриран на: Вто Юли 31, 2007 2:55 pm Мнения: 1792 Местоположение: София
|
А ето и един още по-лесен вариант. Изключи някаква област от RAM-та от линкер скрипта, т.е. да не се ползва.
Направи си структура и указател към нея. Инициализирай указателя към парчето директно с абсолютен адрес щом не ти се занимава с линкер скриптове. Воала! Имаш NV променливи (каквато разбирам ти е целта).
|
| Сря Май 27, 2009 4:44 pm |
|
 |
|
Цецо
Ранг: Форумен бог
Регистриран на: Пон Сеп 27, 2004 9:22 am Мнения: 15501 Местоположение: София
|
Бе това ми е горе долу ясно. Това което не ми е ясно е как се обяснява коя секция какво да я прави компилатора?
Т.е. къде се указва че точно bss трябва да се занули, а точно data да се копира от ROM-a? Гледам линкерския скрипт не виждам подобни "разяснения" в него.
.text ми е в FLASH-а, т.е там променливи няма какво да търсят.
_________________ "Да еба и шибаната държава" мислеше си Гошо, докато се опитваше да улучи кофата за боклук от балкона на осмия етаж.
|
| Сря Май 27, 2009 4:45 pm |
|
 |
|
miro_atc
Ранг: Форумен бог
Регистриран на: Нед Фев 26, 2006 6:52 pm Мнения: 11278 Местоположение: Добрич
|
1. Компилаторът генерира обекти - променливи, константи и всякакви други глупости, като за всеки обект се указва секция в обектния файл.
По принцип ти с __attribute__ може да кажеш в коя секция искаш дадения обект да бъде разположен, но ако не го направиш ще ти я наблсъка в съответната секция по подразбиране. Поне засега не ми попадала документация относно всички секции по подразбиране. Така че за bss, text и т.н. се ориентирам, но има и разни други дето пък не ги разбирам...
2. Линкерският скрипт описва как от многото обектни файлове и техните секции да се сглоби изходен файл. Така ти на практика определяш разпожението на секциите от обектните файлове в изходния файл (това което казва woody).
3. Линкерът изпълнявайки скрипта разполага всяко нещо на мястото му (евентуално премахва ненужните неща) но в крайна сметка всеки обект си получава конкретни адреси. Включително се изчисляват и константите (етикетите).
4. Обикновено имаш два етикета между които се разполагат променливите в RAM-a. Примерно при мен е:
В случая това са _szero и _ezero. Между тези два адреса линкера ще разположи BSS-те на всички (*) обектни файлове...
5. В стартъп кода имам едно цикълче дето нулира паметта между _szero и _ezero
Накратко казано компилатора нищо не указва (освен кое в коя секция на обектния файл се намира). Линкерът (и скрипта) реално разполагат нещата. А стартъп кода е отговорен за нулирането.
С други думи по подразбиране нищо в GCC не се инициализира и даже няма изобщо да се линкне. Забрави за С-стандандартите дето ти казват, че static глобална променлива трябва да се нулира - ще се нулира само ако ТИ вкараш такъв линкерски скрипт и стартъп код и го извикаш този код и при това го извикаш навреме (преди да си разрешил прекъсванията).
|
| Сря Май 27, 2009 6:34 pm |
|
 |
|
woody
Ранг: Форумен бог
Регистриран на: Вто Юли 31, 2007 2:55 pm Мнения: 1792 Местоположение: София
|
Цецо, ела с лапнитоп на бира и ще дигнем мъглата. 
|
| Сря Май 27, 2009 6:51 pm |
|
 |
|
Zdrav
Ранг: Форумен бог
Регистриран на: Сря Яну 26, 2005 2:01 pm Мнения: 1952 Местоположение: Варна
|
Не че знам повече от woody и miro_atc ама гледам, че има леко разминаване между въпросите и обясненията. По подразбиране всяка глобална променлива която е инициализирана с нещо различно от нула отива в .data секцията. Всички останали глобални променливи отиват в .bss. Стартъп кода е този който решава коя секция да се занули и коя да се копира и коя да не се пипа. miro_atc го е обяснил по-горе механизма. В стартъп кода са видими адресите за начало и край на секциите. И с едно просто цикълче се извършва нулиране или копиране.
Като си направиш твоя секция гледай да не съвпадне името и с някоя от стандартните все пак. Щом като са променливи естествено че ще е в RAM. Може да си направиш и отделна изходна секция съдържаща само твоята входна секция.
В стартъп кода просто тази секция няма да се пипа. За да се прави там нещо с нея трябва да си драснеш собственоръчно код в стартъп файла.
_________________ Най-опасният враг на истината и свободата е мнозинството.
|
| Сря Май 27, 2009 9:02 pm |
|
 |
|
Цецо
Ранг: Форумен бог
Регистриран на: Пон Сеп 27, 2004 9:22 am Мнения: 15501 Местоположение: София
|
Ясно. Утре ще пробвам.
А гледам че в моя линкерски скрипт (който съм присвоил), за .data и .bss са дефинирани като:
1. Що за животно е обект от тип COMMON?
2. >ram АТ>rom - що чини тоя "ром" тука?
@woody - Абе ти за какъв човек ме имаш? Ще дойда да пием бира и ще седна да с лаптопа да чопля подобни дивотии? Как пък не. Ай сиктир  Бирата трябва да се уважава.
_________________ "Да еба и шибаната държава" мислеше си Гошо, докато се опитваше да улучи кофата за боклук от балкона на осмия етаж.
|
| Сря Май 27, 2009 9:39 pm |
|
 |
|
woody
Ранг: Форумен бог
Регистриран на: Вто Юли 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 |
|
 |
|
Zdrav
Ранг: Форумен бог
Регистриран на: Сря Яну 26, 2005 2:01 pm Мнения: 1952 Местоположение: Варна
|
Не, по същия начин със отделна секция се прави.
_________________ Най-опасният враг на истината и свободата е мнозинството.
|
| Вто Юни 16, 2009 12:42 pm |
|
 |
|
woody
Ранг: Форумен бог
Регистриран на: Вто Юли 31, 2007 2:55 pm Мнения: 1792 Местоположение: София
|
С атрибут не може. Нямам под ръка за проба в момента, но пробвай да сложиш в линкер скрипта в правилната секция:
str = 0x1234;
Другите начини са с отделна секция, като аз лично бих сложил всички такива "фиксирани" данни в една структура.
|
| Вто Юни 16, 2009 12:52 pm |
|
|