Самый низкоуровневый язык, ага
От: vsb Казахстан  
Дата: 26.09.23 03:32
Оценка: +1 -1 :)
Вроде общепринятая точка зрения, что C ближе всего к железу, ну если не считать языков ассемблера.

Однако есть такая простая конструкция, как глобальные переменные. В частности буферы.

В программах, запускаемых на микроконтроллерах, эта конструкция очень распространена. Объявляем глобальный буфер на 10 кибибайтов и используем его.

Если всмотреться, что происходит при этом, то можно заметить следующее:

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

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

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

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

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

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

Очень забавно за всем этим наблюдать, конечно.
Re: Самый низкоуровневый язык, ага
От: Shmj Ниоткуда  
Дата: 26.09.23 05:37
Оценка:
Здравствуйте, vsb, Вы писали:

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

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

Согласно Талмуду руки мыть нужно 3 раза, так что все верно.

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

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

А что если туда каким-то образом попадет вредоносный код?
Re[2]: Самый низкоуровневый язык, ага
От: vsb Казахстан  
Дата: 26.09.23 05:44
Оценка:
Здравствуйте, Shmj, Вы писали:

S>А что если туда каким-то образом попадет вредоносный код?


Это просто буфер. Я туда данные записываю, которые надо отправить и в отдельной процедуре отправляю. Пока данные туда не записались, значение этого буфера никак не используется.
Re: Самый низкоуровневый язык, ага
От: night beast СССР  
Дата: 26.09.23 06:15
Оценка: +5
Здравствуйте, vsb, Вы писали:

vsb>Вроде общепринятая точка зрения, что C ближе всего к железу, ну если не считать языков ассемблера.


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


никто не заставляет тебя размещать буфер в bss
можешь сделать свою секцию
Re[2]: Самый низкоуровневый язык, ага
От: vsb Казахстан  
Дата: 26.09.23 06:25
Оценка: +1
Здравствуйте, night beast, Вы писали:

vsb>>Вроде общепринятая точка зрения, что C ближе всего к железу, ну если не считать языков ассемблера.


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


NB>никто не заставляет тебя размещать буфер в bss

NB>можешь сделать свою секцию

Я так и сделал. Но это уже не C. В C нет никаких секций. Это уже что-то вроде GCC-C.

Меня просто сам подход удивил. С одной стороны вроде как топят за то, что язык ничего не делает сам по себе. Даже локальные переменные не инициализирует, хотя тут какой вред, вообще сложно представить, с локальной переменной компилятор прекрасно видит — инициализировали ли её перед использованием. А с глобальными логика инвертировалась.
Re: Самый низкоуровневый язык, ага
От: Zhendos  
Дата: 26.09.23 06:43
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>Вроде общепринятая точка зрения, что C ближе всего к железу, ну если не считать языков ассемблера.


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


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


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


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



1. Очевидно двойная инициализация это баг. Баги есть везде, непонятно какое это отношение
имеет к языку C.
2. По стандарту статические переменные без инициализатора обнуляются.
Если это не нужно, то можно использовать статический указатель, и инициализировать его в "main",
или присвоить этому статическому указателю конкретное значение, если речь идет об embedded,
где используют кастомные скрипты линковщика и подобные хитрости.
Re[3]: Самый низкоуровневый язык, ага
От: ononim  
Дата: 26.09.23 07:24
Оценка: 1 (1) +1
vsb>Меня просто сам подход удивил. С одной стороны вроде как топят за то, что язык ничего не делает сам по себе. Даже локальные переменные не инициализирует, хотя тут какой вред, вообще сложно представить, с локальной переменной компилятор прекрасно видит — инициализировали ли её перед использованием. А с глобальными логика инвертировалась.
В "больших" операционках, память, выделяемая на уровне ОС (то есть не malloc, а mmap какой нить или VirtualAlloc) обнуляется ядром — потому что в ином случае это была бы утечка данных из какого нить соседнего процесса. Ну и соответственно bss всякие загрузчик в линуксе не обнуляет — они сразу мапятся в процесс обнуленными. Возможно решили использовать этот факт в стандарте.
Как много веселых ребят, и все делают велосипед...
Re: Самый низкоуровневый язык, ага
От: Maniacal Россия  
Дата: 26.09.23 07:45
Оценка:
Здравствуйте, vsb, Вы писали:

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


Нет, только статические обнуляются.
Re: Самый низкоуровневый язык, ага
От: Pzz Россия https://github.com/alexpevzner
Дата: 26.09.23 08:50
Оценка: +3
Здравствуйте, vsb, Вы писали:

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


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


Ну, руки-крюки у кого-то.

Я в свое время для TurboC 2.0 писал минималистичный стартап на асме. Получалось строк типа 20, что ли. Как раз, в основном, обнуление _bss и инициализация стека (не уверен, что с моим стартапом работал malloc() и зависящие от него функции, но не всякой же программе они нужны, правда?).

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


Он после подачи питания сколько-то там миллисекунд, если не десятков, ждет просто, пока тактовый генератор раскрутится и застабилизируется. Неужели на этом фоне эти обнуления заметны? Особенно если учесть, что к хиленьким процессорам редко когда большой кусок памяти приделывают.
Re[3]: Самый низкоуровневый язык, ага
От: Pzz Россия https://github.com/alexpevzner
Дата: 26.09.23 09:33
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>Меня просто сам подход удивил. С одной стороны вроде как топят за то, что язык ничего не делает сам по себе. Даже локальные переменные не инициализирует, хотя тут какой вред, вообще сложно представить, с локальной переменной компилятор прекрасно видит — инициализировали ли её перед использованием. А с глобальными логика инвертировалась.


Я думаю, в том древнем UNIX, в котором C родился, неинициализированные данные зануляло ядро, а вовсе даже не сишный стартап. И это, с одной стороны, убирало утечку данных между программами через мусор в памяти, а с другой — было дешевле, чем в каждой программе явно инициализировать глобальные переменные,
Re: Самый низкоуровневый язык, ага
От: velkin Удмуртия https://kisa.biz
Дата: 26.09.23 09:36
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>Самый низкоуровневый язык, ага

vsb>Вроде общепринятая точка зрения, что C ближе всего к железу, ну если не считать языков ассемблера.

1. Си это язык программирования высокого уровня абстракций.
2. Ассемблер это язык программирования низкого уровня абстракций.

Даже у ассемблера есть абстракции, но их там мало и они в основном носят организационный характер. Что касается Си, то он очень далёк от машинных кодов. А все абстракции строятся именно поверх машинных кодов.

Си (язык программирования)

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

Re[2]: Самый низкоуровневый язык, ага
От: Pzz Россия https://github.com/alexpevzner
Дата: 26.09.23 09:37
Оценка:
Здравствуйте, Maniacal, Вы писали:

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


M>Нет, только статические обнуляются.


Все голабальные переменные — статические.

Но Си, действительно, обнуляет все статические переменные, а не только глобальные:

int foo;          // Глобальная переменная; будет обнулена
static int bar;   // Неглобальная, но статическая. Тоже будет обнулена

void f(void)
{
    static int c; // И эта тоже;
    . . .
}
Re: Самый низкоуровневый язык, ага
От: kov_serg Россия  
Дата: 26.09.23 09:42
Оценка:
Здравствуйте, vsb, Вы писали:

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

Пример в студию
Re[3]: Самый низкоуровневый язык, ага
От: Pavel Dvorkin Россия  
Дата: 26.09.23 09:50
Оценка: +2
Здравствуйте, vsb, Вы писали:

<объединил цитирование>

vsb>Я так и сделал. Но это уже не C. В C нет никаких секций. Это уже что-то вроде GCC-C.


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


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


Равно как нет и никакого стартап кода и функции _start тоже нет.

Так что не путай язык и его реализацию. Язык лишь определяет, что они должны быть занулены. Как это будет сделано — он не определяет.
With best regards
Pavel Dvorkin
Отредактировано 26.09.2023 9:53 Pavel Dvorkin . Предыдущая версия .
Re[4]: Самый низкоуровневый язык, ага
От: vsb Казахстан  
Дата: 26.09.23 09:58
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Равно как нет и никакого стартап кода и функции _start тоже нет.


PD>Так что не путай язык и его реализацию. Язык лишь определяет, что они должны быть занулены. Как это будет сделано — он не определяет.


Про двойное обнуление это так, к слову. Может и не везде это, в STM32 стартапе я это увидел и в libc которая линкуется через gcc с сайта arm я это тоже увидел.

А про язык я написал потому, что считаю требование обнулять глобальные переменные без явной инициализации — глупостью. Кому нужны нули, тот напишет int n = 0; char s[123] = {}, зря что-ли специальный синтаксис выдумали.
Re[5]: Самый низкоуровневый язык, ага
От: Sergei I. Gorelkin Россия  
Дата: 26.09.23 10:56
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>А про язык я написал потому, что считаю требование обнулять глобальные переменные без явной инициализации — глупостью. Кому нужны нули, тот напишет int n = 0; char s[123] = {}, зря что-ли специальный синтаксис выдумали.


Если ты так в embedded напишешь, то линкер эти твои нули засунет в ПЗУ, занимая там место, а стартап-код будет заботливо копировать в ОЗУ. Возможно дважды, как в STM32
Re: Самый низкоуровневый язык, ага
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 26.09.23 11:45
Оценка: +1
Здравствуйте, vsb, Вы писали:


vsb>Если всмотреться, что происходит при этом, то можно заметить следующее:


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


Разве? Я думал, что чтобы произошла инициализация нулями, надо написать что-то типа
byte buf[1024] = { 0 };


А если написать
byte buf[1024];

то инициализации не будет


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


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


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


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


Не совсем понял, в чем отличие стартап кода и _start из libc? Я вообще не уверен, что в прошивке для МК есть какие-то секции.


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


Или нет


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


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


Не наблюдай. Не инициализируй переменные там, где это не нужно. Перепиши стартап.
Маньяк Робокряк колесит по городу
Re[2]: Самый низкоуровневый язык, ага
От: CRT  
Дата: 26.09.23 12:26
Оценка:
Здравствуйте, Marty, Вы писали:



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


M>Разве?


Ага

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

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


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

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


M>>Разве?


CRT>Ага


Ну может, я в чистой сишечке так себе спец


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

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


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


Ну, плюсики вроде бы при этом весь массив обнуляют, хз как сишечка
Маньяк Робокряк колесит по городу
Re[6]: Самый низкоуровневый язык, ага
От: vsb Казахстан  
Дата: 26.09.23 14:12
Оценка:
Здравствуйте, Sergei I. Gorelkin, Вы писали:

vsb>>А про язык я написал потому, что считаю требование обнулять глобальные переменные без явной инициализации — глупостью. Кому нужны нули, тот напишет int n = 0; char s[123] = {}, зря что-ли специальный синтаксис выдумали.


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


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