Re[2]: Самый низкоуровневый язык, ага
От: vsb Казахстан  
Дата: 26.09.23 14:19
Оценка:
Здравствуйте, Marty, Вы писали:

vsb>>2. Компилятор кладёт этот буфер в секцию `.bss`.


M>Я не помню, что такое .bss. Есть секции для инициализированных переменных (и вроде не обязательно нулями), и для не инициализированных. Для последних вроде никто обнуление не делает


Нет секции для не инициализированных (если самому её не создать).

M>Не совсем понял, в чем отличие стартап кода и _start из libc?


стартап запускается при старте, настраивает тактирование, копирует секцию _data из флеша в срам и запускает _start.

M>Я вообще не уверен, что в прошивке для МК есть какие-то секции.


В неявном виде есть.

vsb>>6. Наш буфер вообще никак не использует этот факт своего обнуления.


vsb>>Очень забавно за всем этим наблюдать, конечно.


M>Не наблюдай. Не инициализируй переменные там, где это не нужно. Перепиши стартап.


Ты ещё предложи компилятор С переписать.
Re[3]: Самый низкоуровневый язык, ага
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 26.09.23 15:03
Оценка:
Здравствуйте, vsb, Вы писали:

M>>Я не помню, что такое .bss. Есть секции для инициализированных переменных (и вроде не обязательно нулями), и для не инициализированных. Для последних вроде никто обнуление не делает


vsb>Нет секции для не инициализированных (если самому её не создать).


Полистал гугл, он говорит, что .data — сегмент инициализированных данных, .bss — сегмент неинициализированных данных. Ты что-то путаешь, похоже


M>>Не совсем понял, в чем отличие стартап кода и _start из libc?


vsb>стартап запускается при старте, настраивает тактирование, копирует секцию _data из флеша в срам и запускает _start.


Ну, вообще-то не совсем так, у тебя какая-то каша в голове.
Я уже давно не брал в руки шашки, могу конечно, тоже ошибаться.
Изначально там есть какой-то "бутлоадер", который присовывает компилятор/линкер твоей системы разработки, который распаковывает инициализированные данные из прошивки в ОЗУ. Всё. Больше он ничего не делает. Да, этот бутлоадер, возможно, обнуляет неинициализированные глобальные переменные. Но с тем же успехом он может ничего не делать, или забивать неинициализированные данные значением 0xDEADBEAF, например.
Этот "бутлоадер" — примерный аналог загрузчика ОС, который загружает твой EXE в систему с диска. И, полагаю, его тоже можно подменить, и не думаю, что это очень сложно.

Далее, если говорить о сишечке, то управление просто передаётся в твой main. Для плюсов есть точка входа до main, в которой вызываются конструкторы глобальных объектов, и уже из которой управление передаётся в main.
Хотя, конечно, где-то может и не совсем так. На STM32, с которыми я имел дело, там до main исполнялся код, который вызывал настройку тактирования. Для STM32 я имел дело с Keil и GCC. Там этот стартап написан на асме (у кейла и гцц — разные диалекты), и его без проблем можно поправить ручками, например, задать размер кучи (я переделал, чтобы можно было дефайнами задавать без правки стартапа). Там я не припоминаю никаких обнулений. Кстати, настройку тактирования я сам писал для STM32F1/3/4, мне хотелось, чтобы частоту кристалла и частоту кварца можно было просто задать define'ами в проекте. Честно говоря, я уж и не помню, как оно до меня работало, но там какой-то гемор был с переносом на другие чипы-кварцы, что у нас случалось регулярно, и поэтому тактирование я и переписал.


M>>Не наблюдай. Не инициализируй переменные там, где это не нужно. Перепиши стартап.


vsb>Ты ещё предложи компилятор С переписать.


Компилятор — нет. А вот стартапы твоей железяки полезно знать. И залезть в них и что-то переписать ни разу не рокет саенс.

Да, пока писал, немножко вспомнил. У нас использовались стартапы от CMSIS вроде, изрядно переделанные под себя.


Кстати, а с чего ты взял, что там на старте всё по десять раз нулями перезаписывается?
Маньяк Робокряк колесит по городу
Re: Самый низкоуровневый язык, ага
От: Слава  
Дата: 26.09.23 15:38
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>1. Язык С гарантирует, что все глобальные переменные инициализируются нулями.

vsb>2. Компилятор кладёт этот буфер в секцию `.bss`.
vsb>3. Стартап код на ассемблере обнуляет секцию `.bss` сразу после запуска контроллера.
vsb>4. _start из libc ещё раз обнуляет секцию `.bss` (видимо для надёжности).
vsb>5. Итого наш хиленький процессорчик после подачи питания просто так потратил порядка сотни тысяч тактов, гоняя нули.

Насколько я знаю, в Аде это поведение настраивается. Можно не инициализировать.
Re[4]: Самый низкоуровневый язык, ага
От: CRT  
Дата: 26.09.23 16:54
Оценка:
Здравствуйте, Marty, Вы писали:



M>>>Я думал, что чтобы произошла инициализация нулями, надо написать что-то типа

M>>>
byte buf[1024] = { 0 };


CRT>>здесь ты явно инициализировал нулем элемент с нулевым индексом


M>Ну, плюсики вроде бы при этом весь массив обнуляют, хз как сишечка


наврал я.
Ну то есть да, если ты написал byte buf[1024] = { 0 } то это явная инициализация только элемента с нулевым индексом. Однако если у тебя указана инициализация хотя бы одного элемента, то остальные по умолчанию обнуляются. Поэтому твоя конструкция обнулит весь массив. Это и для С и для С++
Отредактировано 26.09.2023 17:46 CRT . Предыдущая версия . Еще …
Отредактировано 26.09.2023 16:59 CRT . Предыдущая версия .
Re: Самый низкоуровневый язык, ага
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 27.09.23 10:04
Оценка: +1
Здравствуйте, vsb, Вы писали:

vsb>3. Стартап код на ассемблере обнуляет секцию `.bss` сразу после запуска контроллера.

vsb>4. _start из libc ещё раз обнуляет секцию `.bss` (видимо для надёжности).

Достоинства C/C++ в том, что в них зависимость от стартапа и вообще CRT достаточно прозрачна — большинство конструкций языка порождает только голый код, и лишь небольшая их часть зависит от функций/переменных CRT/стартапа. Функции, которая не использует этих зависимых конструкций, для работы требуется только настроенный стек (и то не всегда). Если все это контролировать, нетрудно писать программы, которым не нужны ни CRT, ни стартап — вход может быть в любую функцию, не только в main.

Если Вы используете "канонический" C/C++ со стандартным стартапом и автоматическим входом через main, и при этом изменить стандартное поведение, то нужно управлять размещением и режимами работы вручную (секции, прагмы, ключи компилятора/линкера и т.п.).

У меня под винду уже очень давно свой стартап для C++, написанный целиком на C++, без единой строчки ассемблерного кода. Если бы не требовалось вызывать конструкторы статических объектов и регистрировать их деструкторы, можно было бы обойтись и вовсе без стартапа. А для 8-разрядных AVR, если писать на C++ без статических объектов классов, имеющих конструкторы, даже стартап не линкуется, насколько я помню.
Re[3]: Самый низкоуровневый язык, ага
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 27.09.23 10:08
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>это уже не C. В C нет никаких секций.


В C также нет ни "процессора" или "микроконтроллера", ни "тактов". Тот C, который "гарантирует" — это спецификация абстрактной машины, не более того. Она позволяет Вам писать на C даже для "хилого микроконтроллера", и программа будет как-то работать. Желаете более эффективной работы — придется настраивать реализацию, это очевидно.
Re[4]: Самый низкоуровневый язык, ага
От: vsb Казахстан  
Дата: 27.09.23 10:43
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

vsb>>это уже не C. В C нет никаких секций.


ЕМ>В C также нет ни "процессора" или "микроконтроллера", ни "тактов". Тот C, который "гарантирует" — это спецификация абстрактной машины, не более того. Она позволяет Вам писать на C даже для "хилого микроконтроллера", и программа будет как-то работать. Желаете более эффективной работы — придется настраивать реализацию, это очевидно.


Но в С есть требование того, чтобы глобальные переменные были обнулены. И от этого никуда не уйдёшь. Если это требование игнорировать, то это уже не С.

А реализация этого требования бесплатно не бывает. Кто бы что про операционную систему не говорил, память сама собой не обнулится.

И это кардинально противоречит философии языка, на мой взгляд.
Отредактировано 27.09.2023 10:44 vsb . Предыдущая версия .
Re[5]: Самый низкоуровневый язык, ага
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 27.09.23 10:57
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>Но в С есть требование того, чтобы глобальные переменные были обнулены.


Это не требование, а утверждение. Это для программиста, который может рассчитывать, что в стандартной реализации они будут обнулены. Самому же C глубоко фиолетово, что будет в тех переменных.

vsb>Если это требование игнорировать, то это уже не С.


Во-первых, это классическая ситуация из серии "шашечки или ехать". Если нужно "все как в стандарте", то забудьте про скорость и объем памяти, в C об этом тоже ничего не говорится. Гарантируется лишь правильный результат исполнения программы в соответствии со стандартом.

Во-вторых, C в микроконтроллере, ядре ОС и подобных местах — это по определению "уже не C". Что там в argv и argc, что в environ, куда идет результат, возвращаемый main, куда печатает printf, что делают _spawn, _exec и подобные функции стандартной библиотеки?

vsb>это кардинально противоречит философии языка, на мой взгляд.


Вы делаете программы на языке, или таки на его философии? Чем философия мешает делать программы с любым желаемым поведением?
Re[5]: Самый низкоуровневый язык, ага
От: kov_serg Россия  
Дата: 27.09.23 13:23
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>Но в С есть требование того, чтобы глобальные переменные были обнулены. И от этого никуда не уйдёшь. Если это требование игнорировать, то это уже не С.

1. Нафига вам вообще понадобились глобальные переменные.
2. В микроконтроллере никто не мешает разместить переменные самому в допустимы диапазон SRAM
struct AppGlobals {
  int x,y;
};

#define GLOBAL ((struct AppGlobals*)APP_GLOBALS_ADDRESS)
...
GLOBAL->x=47;

3. вы можете объяснить линковщику что вам надо (у него есть скрипт для этого) и ваш код инициализации может ничего не обнулять и даже не копировать если это вам не требуется.
Re: Самый низкоуровневый язык, ага
От: vdimas Россия  
Дата: 27.09.23 15:22
Оценка: :)
Здравствуйте, vsb, Вы писали:

vsb>4. _start из libc ещё раз обнуляет секцию `.bss` (видимо для надёжности).

vsb>5. Итого наш хиленький процессорчик после подачи питания просто так потратил порядка сотни тысяч тактов, гоняя нули.

В контроллерах доступную память зачастую распределяют "в уме", т.е. просто определяют константы адерсов этой памяти, и ничего нулями забивать не нужно.
byte * const dataSpace = SOME_VALUE;
Descriptor1 * const descriptor1 = dataSpace;
const Descriptor2 * const descriptor2 = ((byte*)descriptor1) + sizeof(Descriptor1);

Только оно не настолько ручками, пару макросов сверху, для удобства.
Re[7]: Самый низкоуровневый язык, ага
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 27.09.23 15:25
Оценка:
Здравствуйте, vsb, Вы писали:

SIG>>Если ты так в embedded напишешь, то линкер эти твои нули засунет в ПЗУ, занимая там место, а стартап-код будет заботливо копировать в ОЗУ. Возможно дважды, как в STM32


vsb>Это понятно но это текущая кривая реализация. Ничего не мешает такие переменные сувать в bss, а неинициализированные ещё куда.



В bss как раз неинициализированные суются. Ты, кстати, под STMку в чем разрабатываешь?
Маньяк Робокряк колесит по городу
Re[5]: Самый низкоуровневый язык, ага
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 27.09.23 15:26
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>Но в С есть требование того, чтобы глобальные переменные были обнулены. И от этого никуда не уйдёшь. Если это требование игнорировать, то это уже не С.


Разве?


vsb>А реализация этого требования бесплатно не бывает. Кто бы что про операционную систему не говорил, память сама собой не обнулится.


Это копейки в любом случае


vsb>И это кардинально противоречит философии языка, на мой взгляд.


Или это уже за рамками языка, если говорить об ОС
Маньяк Робокряк колесит по городу
Re[6]: Самый низкоуровневый язык, ага
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 27.09.23 15:29
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Во-вторых, C в микроконтроллере, ядре ОС и подобных местах — это по определению "уже не C".


С чего бы не C?


ЕМ>Что там в argv и argc,


Ничего. Это нормально


ЕМ>что в environ,


Ничего. Это нормально


ЕМ>куда идет результат, возвращаемый main,


Никуда. Это нормально


ЕМ>куда печатает printf,


printf, если под Keil'ом, внезапно выводит в Output


ЕМ>что делают _spawn, _exec и подобные функции стандартной библиотеки?


Полагаю, их просто нет. От этого C не перестаёт быть C
Маньяк Робокряк колесит по городу
Re[2]: Самый низкоуровневый язык, ага
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 27.09.23 15:34
Оценка: +1
Здравствуйте, vdimas, Вы писали:

V>В контроллерах доступную память зачастую распределяют "в уме", т.е. просто определяют константы адерсов этой памяти, и ничего нулями забивать не нужно.

V>
V>byte * const dataSpace = SOME_VALUE;
V>Descriptor1 * const descriptor1 = dataSpace;
V>const Descriptor2 * const descriptor2 = ((byte*)descriptor1) + sizeof(Descriptor1);
V>



Это для работы с периферией, она там обычно прикидывается памятью. Для обычного кода зачем что-то распределять в уме?
Маньяк Робокряк колесит по городу
Re[7]: Самый низкоуровневый язык, ага
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 27.09.23 16:35
Оценка: :)
Здравствуйте, Marty, Вы писали:

ЕМ>>Во-вторых, C в микроконтроллере, ядре ОС и подобных местах — это по определению "уже не C".


M>С чего бы не C?


С того, что это не полноценный C, состав которого включает ядро языка, стандартную библиотеку и стандартное же окружение. Это подмножество, куда даже ядро может входить не полностью (например, без плавучки), а уж библиотека чаще всего прилично урезана. Соответственно, там может не скомпилироваться или не заработать полностью корректная, платформенно-независимая программа (скажем, POSIX-совместимая), даже если для нее достаточно памяти.

M>От этого C не перестаёт быть C


Если говорить о "самом языке" (его ядре), то да. Но той же инициализацией статических переменных занимается не оно.
Re[8]: Самый низкоуровневый язык, ага
От: vsb Казахстан  
Дата: 27.09.23 19:01
Оценка: +1
Здравствуйте, Marty, Вы писали:

SIG>>>Если ты так в embedded напишешь, то линкер эти твои нули засунет в ПЗУ, занимая там место, а стартап-код будет заботливо копировать в ОЗУ. Возможно дважды, как в STM32


vsb>>Это понятно но это текущая кривая реализация. Ничего не мешает такие переменные сувать в bss, а неинициализированные ещё куда.


M>В bss как раз неинициализированные суются. Ты, кстати, под STMку в чем разрабатываешь?


Блин, сто раз уже написали — нет в С неинициализированных глобальных переменных. Только локальные. bss обнуляется на старте, точка. Ты вроде в С спец, должен это лучше меня знать. Можно удалить из стартапа этот код обнуления, можно не вызывать libc _start, тогда не будет обнуляться, но это уже не соответствует тому, что требует стандарт.

Под vscode. Не совсем под STM, под её китайский перепев (GD32).
Отредактировано 27.09.2023 19:09 vsb . Предыдущая версия . Еще …
Отредактировано 27.09.2023 19:09 vsb . Предыдущая версия .
Отредактировано 27.09.2023 19:04 vsb . Предыдущая версия .
Отредактировано 27.09.2023 19:03 vsb . Предыдущая версия .
Re[8]: Самый низкоуровневый язык, ага
От: vsb Казахстан  
Дата: 27.09.23 19:06
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>>>Во-вторых, C в микроконтроллере, ядре ОС и подобных местах — это по определению "уже не C".


M>>С чего бы не C?


ЕМ>С того, что это не полноценный C, состав которого включает ядро языка, стандартную библиотеку и стандартное же окружение. Это подмножество, куда даже ядро может входить не полностью (например, без плавучки), а уж библиотека чаще всего прилично урезана. Соответственно, там может не скомпилироваться или не заработать полностью корректная, платформенно-независимая программа (скажем, POSIX-совместимая), даже если для нее достаточно памяти.


А при чём тут POSIX и C? Это как бы разные вещи. Не, я согласен, у меня printf тоже не линкуется, ему там ещё с десяток вызовов нужно реализовать, но в целом ничего там не урезано, что не относится к вводу-выводу, обычная libc (newlib). Плавающую точку gcc умеет компилировать софтово (с производительностью, полагаю, будет крайне грустно, но работать будет).
Отредактировано 27.09.2023 19:07 vsb . Предыдущая версия .
Re[9]: Самый низкоуровневый язык, ага
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 27.09.23 21:35
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>А при чём тут POSIX и C? Это как бы разные вещи.


Вы таки или крестик снимите, или трусы наденьте. То у Вас "в C нет никаких секций, это уже не C", то "при чем тут POSIX?". Есть спецификация языка, есть стандарты, которые соблюдаются в канонических "пользовательских" реализациях, но почти никогда не соблюдаются в ограниченных "системных". Если это "все-таки C", то и "C с секциями" — "тоже C".

Вообще, любой серьезный язык только выигрывает от наличия возможностей управления генерацией кода, режимами связывания, размещением кода/данных в памяти и прочими платформенно-зависимыми вещами. Даже строгий Pascal во многих реализациях такое имеет, а уж C/C++ сам бог велел все это иметь, и желательно побольше.
Re[9]: Самый низкоуровневый язык, ага
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 27.09.23 21:37
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>Можно удалить из стартапа этот код обнуления, можно не вызывать libc _start, тогда не будет обнуляться, но это уже не соответствует тому, что требует стандарт.


И что за беда с того, что не соответствует?
Re[3]: Самый низкоуровневый язык, ага
От: vdimas Россия  
Дата: 27.09.23 22:18
Оценка: :)
Здравствуйте, Marty, Вы писали:

M>Это для работы с периферией, она там обычно прикидывается памятью. Для обычного кода зачем что-то распределять в уме?


Чтобы уменьшить размер образа, оставив в нём только код.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.