Re[9]: Самый низкоуровневый язык, ага
От: vdimas Россия  
Дата: 28.09.23 20:46
Оценка: +1
Здравствуйте, Marty, Вы писали:

V>>Гарвардская модель удобна для встраиваемых решений, т.к. программы сидят в ПЗУ на кристалле.

M>В фон-немановской STM32 программы точно также лежат во флешке на кристалле.

ARM-ы бывают и гарвардские.


M>В упор не вижу, причем тут архитектура Г или фН.


Для 8-16 бит было удобно, т.к. это удвоение суммарного адресного пространства кода+данных.
Для 32 бит уже не принципиально, ес-но, могут делить одно логическое адресное пространство.


M>А есть ещё извраты, когда прошивка лежит во внешней флешке и МК с ней общается по SPI, но и тут архитектура не причем


Это не то.
В гарварде прога непосредственно исполняется из другого адресного пула, где обычно внутреннее ПЗУ (программируемое или прошитое при изготвлении чипа).
Re[20]: Самый низкоуровневый язык, ага
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 28.09.23 21:03
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

M>>ничего не понял, что за проблема, о каких извращения ты говоришь


ЕМ>Ну вот нужно в зависимости от типа МК определить не макрос, а функцию. Если ее просто определить в одном из стандартных заголовков, то она будет определена в каждом модуле, включающем этот заголовок, и обычный линкер этого не переварит. Поэтому нужен либо линкер с оптимизацией множественных определений, либо готовый набор нужных функций в libc на все случаи жизни, для которых в заголовке под видом общего имени функции будет определяться макрос.


В плюсах та же проблема будет, если ты будешь не inline код писать в заголовках. Ничего, как-то справляемся


M>>>>Сортировка — std::sort

M>>Она не нуждается в CRT, и помещается по месту

ЕМ>Она и есть та часть CRT, которая реализована в заголовках в виде исходников, а не в libc в виде объектного кода.


Это не CRT



M>>Умеет, но даже десяток имён файлов легко съедят килобайт


ЕМ>Имен — не съедят, а вот путей — да. Именно поэтому было бы полезно или управлять раскрытием __FILE__, или иметь отдельный макрос только для имени.


Какая разница, суть ты понял. И никто не предоставляет средств управления раскрытием этого макроса


ЕМ>>>А если нужно выводить текст на экран?


M>>Чрезвычайно редкий кейс


ЕМ>Производители миллионов гаджетов на МК с экранами смотрят на Вас с недоумением.


Тем не менее, устройств без экрана на порядки больше. У нас в роботе легко могло быть несколько десятков плат с контроллерами, и ни одной с экраном



M>>я каждый раз лезу в доки по printf, потому что все нюансы форматной строки не держу в голове.


ЕМ>Чего там держать-то для типовых форматов (d, u, x, s)? Это для плавучки там куча нюансов, а для целых и строк — раз-два и обчелся.


Это если ты не хочешь вывести строку определенной длины с определенным выравниванием


M>>это не фетиш, а удобство


ЕМ>Я сильно сомневаюсь, что, если бы во всех руководствах по C++ не утверждалось, что только потоки — истинно правильный способ, а *printf — древнее и опасное убожество, большинство пользовалось бы потоками.


Не знаю, что там во всех руководствах написано, я сам в итоге к такому пришел


M>>обсёры с форматной строкой встречаются регулярно


ЕМ>Гораздо реже, чем логические ошибки, приводящие к тем же последствиям — просто потому, что *sprintf в типовой программе гораздо меньше, чем других конструкций, чреватых неконтролируемыми ошибками.


Только из-за этого, да. В процентах на количество использований printf — он впереди всех других способов обосраться


M>>современные компиляторы умеют о таких проблемах предупреждать


ЕМ>По уму, надо было изначально сделать эти предупреждения, а не пихать потоки везде, куда можно технически.


Мне потоки нравяться гораздо больше, чем printf. Реализация конечно так себе, но идея неплохая.
Маньяк Робокряк колесит по городу
Re[10]: Самый низкоуровневый язык, ага
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 28.09.23 21:04
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Это не то.

V>В гарварде прога непосредственно исполняется из другого адресного пула, где обычно внутреннее ПЗУ (программируемое или прошитое при изготвлении чипа).

Я в курсе, что такое гарвардская архитектура. Я не понял, к чему ты её приплёл
Маньяк Робокряк колесит по городу
Re[7]: Самый низкоуровневый язык, ага
От: vdimas Россия  
Дата: 28.09.23 21:35
Оценка: +1
Здравствуйте, Marty, Вы писали:

V>>Если пользуешь Си, то для оперирования объявленными статическими данными (структурами, массивами) необходим CRT.

M>Что именно из CRT нужно для этого?

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

Упреждая пинг-понг вопросов-ответов:
int a = 42;
int b = calcB();

Здесь в бинарном образе в сегменте данных по адресу a будет число 42, по адресу b будет 0.

Внешний загрузчик грузит образ в память, переменная a уже инициализирована (это первая фаза), а переменная b будет инициализирована из глобального связанного списка инициализации, где каждый узел примерно такого вида:
struct __init_module {
  void (*fn)(void);
  __init_module * next; 
};

CRT пробегается по этому списку, вызывая код динамической инициализации — это вторая фаза стандартной инициализации С/С++.

Для инициализации модуля, содержащего динамическую инициализацию (здесь глобальной переменной b), будет порождена безымянная ф-ия примерно такого вида:
void __some_init_xxx() {
  b = calcB();
}

Указатель на эту ф-ию будет в одном из узлов __init_module в глобальном списке динамической инициализации.

Для микриков обычно нет связанного списка, динамическая инициализация представляет собой развернутый (типа заинлайненный) код, но это всё-равно лишний код, который почти всегда не нужен, т.к. любые начальные данные или не нужны, или являются константами, тогда им не место в ОЗУ.

Т.е., статические константы в embedded никогда не используются (я давал выше по ветке условный код, а не реальный), т.к. программист не может знать — будет ли под эти константы выделена память или компилятор обойдётся без этого.

На деле всё программируется через #define константы, либо через enum, т.е. через те техники, где "воздушность" констант гарантируется.


V>>Просто напоминаю, что почти всегда микроконтроллеры выполнены по гарвардской ахитектуре, а не по фон-неймановской, с которой ты писал этот пост.

M>Весьма спорное утверждение.

Это реальность.


M>Из гарвардских видел только клоны MCS-51, хотя, не скажу, что большой опыт с различными семействами


У меня опыт достаточный, более десятка лет.

Для справки, мейнстримом для встраиваемых решений ARM не является до сих пор, не смотря на их засилье в смартфонах/планшетах, хотя гарвардские АРМ-ы тоже порой в ходу.

Повально там PIC-и, AVR-RISC, 51-я архитектура, MIPS-семейства (именно в гарварде, если ПЗУ на борту кристалла, т.е. почти всегда), недавно кучно пошли RISC-V, которые прямо по спецификации есть в исполнении для архитектуры общего назначения (фон-Нейман) и для встраиваемых (Гарвард):
https://www.sbir.gov/node/1654311

Практически все DSP-процы (включая якобы "аппаратные" микросхемы-кодеки звука или видео, кои есть в т.ч. на твоей материнке и видюхе — на самом деле не аппаратные кодеки, конечно, а программные — это просто ядро какого-нить мейнстримого DSP с заводской прошивкой) — это всё исключительно Гарвард.

И так будет всегда во встраиваемых решениях, потому что унутре любого проца всегда Гарвард при обращении к внутреннему кешу (а минимальный кеш, опять же, есть всегда при наличии конвейера, т.е. в любом современном RISC).

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

В итоге, Гарвард проще/дешевле/эффективней, т.к. шины данных и кода работают независимо.
И еще Гарвард не подвержен атакам экзекутора данных.


M>Ничего не понял. Причем тут фон-неймановская архитектура?


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


M>В любом случае, в ОЗУ инициализированные переменные должны как-то попасть, от архитектуры тут ничего не зависит.


Да не должны, в этом суть.
Редко (почти никогда) требуется инициализировать переменные значениями, известными на момент компиляции.

Тем более, во встраиваемых решениях почти всегда есть watch-dog, в т.ч. сугубо программный, который в любой момент обновит состояние системы до начального.
Вот ты можешь в любой момент в С/С++ перевызвать статическую и динамическую инициализацию модуля?
Нет.
Это только ручками.
И тогда инициализация, данная языком+CRT изкаробки, резко становится ненужной. ))

По-сути, такая якобы "необходимость" в дефолтной инициализации глобальных переменных выдаёт недостаточную продуманность графа обработки данных.
И ты не придумаешь пример, где бы я не избавился от такой "необходимости" на раз-два.

Например, в паре проектов мы измеряли тактовую конкретной платы с точностью до 7-го знака и от этой частоты вычисляли некую константу-поправку (прецизионная техника была).
И эта константа шла в код 24 бита фиксированной запятой, а не в переменную в ОЗУ.

То бишь, известные на момент компиляции данные оформляются в виде констант компиляции, но ни в коем случае не переменными.


M>Да, вспомнил, про STM32. Там у них уже есть кое-какой прошитый код, который собственно, и занимается всей инициализацией для запуска прошивки.


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

В то время как встраиваемый микрик — это всегда непременно SoC с некоторой периферией на борту.
(их не зря в одной серии десятки разнообразных вариантов, где варианты отличаются не только объемом ОЗУ/ПЗУ, но как раз набором периферии)

При таких раскладах в каждой конкретной конфигурации SoC фактор "общего назначения" отсутствует как класс. ))


M>Ещё этот встроенный бутлоадер анализирует пины BOOT0/BOOT1, и в зависимости от их состояния может переходить в режим общения по UART, через который можно обращаться к памяти читать/писать, или даже залить прошивку, без какого-либо ST-LINK'а


Только нафига это в микроволновке, стиралке, цифровом приёмнике или рации?
Отредактировано 02.10.2023 10:34 vdimas . Предыдущая версия . Еще …
Отредактировано 29.09.2023 13:11 vdimas . Предыдущая версия .
Отредактировано 29.09.2023 13:05 vdimas . Предыдущая версия .
Re[11]: Самый низкоуровневый язык, ага
От: vdimas Россия  
Дата: 28.09.23 21:38
Оценка: +1
Здравствуйте, Marty, Вы писали:

V>>В гарварде прога непосредственно исполняется из другого адресного пула, где обычно внутреннее ПЗУ (программируемое или прошитое при изготвлении чипа).

M>Я в курсе, что такое гарвардская архитектура. Я не понял, к чему ты её приплёл

Приплёл к embedded, где она абсолютным мейнстримом.
Re[9]: Самый низкоуровневый язык, ага
От: vdimas Россия  
Дата: 28.09.23 21:55
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

V>>Двухфакторная инициализация — статическая и динамическая.

ЕМ>CRT не является безусловно необходимым для этого.

Тогда будет UB. ))
Т.е. ты тогда не можешь полагаться на спецификации языка.


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


Для динамической фазы инициализации CRT требуется, тут подробней:
http://www.rsdn.org/forum/flame.comp/8608986.1


V>>Гарвардская модель удобна для встраиваемых решений, т.к. программы сидят в ПЗУ на кристалле.

ЕМ>Так ПЗУ не является необходимым элементом гарвардской архитектуры.

Ес-но.
ТУт зависимость другая: есть ПЗУ — удобней Гарвард.
И кристаллу удобней (подробности тоже по ссылке выше, почему кристаллу всегда удобней Гарвард), и программисту удобнее, когда численно совпадающие адреса данных и программы на самом деле смотрят в разную память.


ЕМ>В общем случае эта архитектура никак не мешает загрузке в память заранее подготовленных данных.


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


ЕМ>И даже в тех случаях, когда такой возможности нет, именно CRT не требуется. Для одномодульной программы компилятор может складывать код инициализации в заранее известную функцию, которую нужно будет явно вызвать до использования статических переменных.


Так и делается.
Одно плохо — тебе недоступна возможность явного вызова этой ф-ии, этим занимается CRT.
А в случае watch-dog таймеров иногда эту ф-ию надо бы вызывать явно.
А никак!

И вот ты целиком отказываешься от этого раздела спецификации языка и пользуешь другие решения, которые, к тому же, оказываются резко эффективней, бо каждое такое решение выходит "по-месту".

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


ЕМ>Для многомодульных программ это делается складыванием кода в секции, для обработки которых также могла бы генерироваться служебная функция, вызываемая явно.

ЕМ>По сути, это часть CRT, но поднятая чуть выше, вроде явной инициализации вместо умолчания.

Да нет такой возможности в языке, забудь. ))
Только описать такую инициализацию явно, но тогда конструкции языка объявления+инициализации глобальных переменных получаются нерабочими.

Взять простой пример — некая табличная ф-ия, например, кодировка из PCM в u-law.
По классике если, ты опишешь эту таблицу констант в данных, т.е. в ОЗУ, и будешь извлекать из таблицы константы простым обращением к глобальному массиву.

А в микриках другая техника.
Там обычно достаточно большое ПЗУ, но небольшое ОЗУ.
Занимать это ОЗУ большой таблицей — ересь, заслужить линейкой по пальцам.
И ты прошиваешь эти константы в ПЗУ, т.е. по адресу кода.
Причём, если архитектура не позволяет непосредственно читать байты из адресного пространства команд, то ты через макросы прошиваешь команду сложения рабочего регистра с константой (или загрузки константы в регистр) + операция ret.
Тогда обращение к таблице вырождается в call c предвычисленным смещением.
И никакого ОЗУ. Ву а ля! ))
Отредактировано 28.09.2023 21:56 vdimas . Предыдущая версия .
Re[8]: Самый низкоуровневый язык, ага
От: vdimas Россия  
Дата: 28.09.23 22:27
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

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

ЕМ>Но не обязательно в CRT. Это может быть тот же загрузчик — хоть примитивный в МК, хоть навороченный в ОС.

Нет никакой ОС за ненадобностью.
После reset программа тупо исполняется с некоторого адреса.


V>>Допустим, не в БД, а в неоднородном NUMA-окружении, в неких суперкомпах.

V>>Под это есть свои Си-подобные диалекты, позволяющие декларативно описывать неоднородную память, дабы сохранять переносимость программ в исходниках.
ЕМ>Такое надо делать на плюсах, заворачивая в классы.

Повторю, для этого есть специальные языки для NUMA, которые выглядят как расширения к мейнстримовым.

Увы, весь современный мейнстрим создан для SMP-архитектур, и это одна из причин, почему в С++ не было библиотек для потоков — потому что SMP окончательно победила всех и вся только в нулевые, когда даже суперкомпы стали делать на обычных процах от персоналок.


V>>На асме, однако, приходилось писать критичные вещи, где надо расчитывать код с точностью до такта.

V>>Ну и еще для уменьшения вложенности вызова подпрограмм, т.к. на асме легко сделать в одну подпрограмму несколько точек входа
ЕМ>Все это успешно делается на "расширенных сях" с псевдопеременными, intrinsic-функциями, ассемблерными вставками и т.п.

Учитывая изкаробочную развитую модульность в Си/С++, ассемблерные вставки не всегда нужны.
Полноценный асм (макро-асм) на порядки удобнее убогих "вставок". ))


ЕМ>Если под архитектуру есть только "канонический" C, то вряд ли она сильно популярна.


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


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

ЕМ>Не понял, для чего здесь "трассировка". Эта задача решается сочетанием struct/union.

Зачем?
Вот у тебя есть локальные переменные.
В обычной архитектуре локальные переменные живут в стеке, а в микриках часто стек обслуживает только возвраты, а локальные данные живут во вручную организуемом стеке данных в ОЗУ.
Так вот, эта техника далека от эффективности.

В простейших случаях (и в отсутствии рекурсии) компиляторы способны статически распределить в ОЗУ локальные переменные с перекрытием.

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

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

Да, можно через union, но с той оговоркой, что ты не объявляешь такую глобальную переменную, а высчитываешь ее адрес "в уме", как показывал выше, где адрес будет константой времени компиляции.
Отредактировано 28.09.2023 22:45 vdimas . Предыдущая версия . Еще …
Отредактировано 28.09.2023 22:44 vdimas . Предыдущая версия .
Отредактировано 28.09.2023 22:30 vdimas . Предыдущая версия .
Отредактировано 28.09.2023 22:30 vdimas . Предыдущая версия .
Re[7]: Самый низкоуровневый язык, ага
От: vdimas Россия  
Дата: 28.09.23 22:39
Оценка:
Здравствуйте, Marty, Вы писали:

V>>Или на микроконтроллере мало памяти, что всё лишнее выметается, т.е. даже подменяется CRT.

M>Не очень понятно, в чем смысл подмены CRT?

Заменить код начальной инициализации, отказаться от инициализации глобальных переменных.
В том числе от инициализации скрытых глобальных переменных самой CRT.


M>Я вот как-то и не припомню, что из CRT я использовал. Разве что mem* функции


CRT в любом случае для встраиваемых решений всегда идёт в т.ч. в виде исходников, можно подключить любую библиотечную часть из неё.
mem* и str* функции да, порой удобны.

А ввод/вывод, математика и начальная инициализация — обычно на помойку.
Оно громоздкое и почти всегда не нужное.
Re[6]: Самый низкоуровневый язык, ага
От: 777777w Россия  
Дата: 29.09.23 05:12
Оценка:
Здравствуйте, ononim, Вы писали:

O>>>... обнуляется ядром — потому что в ином случае это была бы утечка данных из какого нить соседнего процесса.

7>>Офигеть шпиономания. А как наш процесс мог этим воспользоваться?
O>Пароль спереть, ваш кэп.

Как пароль может оказаться в данных прикладной программы? Речь идёт о том, что при запуске программы она может оказаться там, где ранее работала другая программа. И если выделенные ей данные не инициализировать, то программа получает к ним доступ. И вот представь себе, что она должна делать, какой анализ проводить, чтобы осмыслить эти данные и извлечь из них что-нибудь полезное?
Re[6]: Самый низкоуровневый язык, ага
От: 777777w Россия  
Дата: 29.09.23 05:14
Оценка:
Здравствуйте, Marty, Вы писали:

M>Про спектр и мельдоний уязвимости слышал? А там шпиономания уже на порядок выше


Не слышал. Можно ссылку?
Re[21]: Самый низкоуровневый язык, ага
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 29.09.23 08:01
Оценка:
Здравствуйте, Marty, Вы писали:

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


Вот и интересно, как с этим справляются стандартные заголовки. Или они просто никогда не определяют функций?

M>Это не CRT


Да — строго говоря, это "стандартная библиотека", как и mem*, str* и прочие. И не все шаблоны, определенные в стандартных заголовках C++, самодостаточны, они могут тянуть функции из библиотеки — те же mem*.

M>Это если ты не хочешь вывести строку определенной длины с определенным выравниванием


А если хочу, то через потоки это делается интуитивно, в голове ничего держать не нужно, и в документацию лезть — тоже?
Re[7]: Самый низкоуровневый язык, ага
От: ononim  
Дата: 29.09.23 08:13
Оценка:
7>Как пароль может оказаться в данных прикладной программы?
Вот ты когда в браузере в окошке вводишь пароль, он именно там и оказывается

7>Речь идёт о том, что при запуске программы она может оказаться там, где ранее работала другая программа. И если выделенные ей данные не инициализировать, то программа получает к ним доступ. И вот представь себе, что она должна делать, какой анализ проводить, чтобы осмыслить эти данные и извлечь из них что-нибудь полезное?

Погрепать по слову password и отправить все рядом располагающееся своим хозяевам. Это если действовать тупо. А если знать точно что искать то — искать более конкретные сигнатуры.
Как много веселых ребят, и все делают велосипед...
Re[10]: Самый низкоуровневый язык, ага
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 29.09.23 09:56
Оценка:
Здравствуйте, vdimas, Вы писали:

V>>>Двухфакторная инициализация — статическая и динамическая.

ЕМ>>CRT не является безусловно необходимым для этого.

V>Тогда будет UB. ))


Да и хрен бы с ним.

V>ты тогда не можешь полагаться на спецификации языка.


Уж где-где, а во встроенных системах, где без регулярной ревизии порождаемого кода можно словить разнообразных глюков, полагаться на общие спецификации языка — последнее дело.

V>Для динамической фазы инициализации CRT требуется


Если Вы об инициализации неконстантным выражением, то да. Я даже не подумал, что кто-то в здравом уме может использовать такое на МК.

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


Далеко не всегда удобнее — с теми же табличными функциями.

V>Считай, что это чуть другой образ мышления.


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

V>Одно плохо — тебе недоступна возможность явного вызова этой ф-ии, этим занимается CRT.


Во многих реализациях ее вполне себе можно вызвать, объявив прототип. Но лучше бы такие вещи включать в спецификацию и давать возможность управления. Разбить все служебные функции CRT на группы, выделить каждой определенные функции, тогда весь стартап сведется к их последовательному вызову, и нетрудно будет заменить как любую из функций, так и стартап.

V>Тут во всей красе проявляется то правило инженерии, что самое общее решения является наихудшим для каждого конкретного случая. ))


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

V>нет такой возможности в языке, забудь. ))


"Жопа есть, а слова — нет?"

V>если архитектура не позволяет непосредственно читать байты из адресного пространства команд, то ты через макросы прошиваешь команду сложения рабочего регистра с константой (или загрузки константы в регистр) + операция ret. Тогда обращение к таблице вырождается в call c предвычисленным смещением.


Все бы хорошо, но вот быстродействие такого...
Re[9]: Самый низкоуровневый язык, ага
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 29.09.23 10:14
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Полноценный асм (макро-асм) на порядки удобнее убогих "вставок". ))


Когда на нем нужно написать нечто обширное — безусловно. Но, если некое сочетание МК и реализации C/C++ под него, с одной стороны, не вызывает желания написать все на ассемблере, а с другой — вызывает необходимость писать на ассемблере не вставки по нескольку команд, а полноценные функции, то с таким сочетанием что-то не в порядке.

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


Какой в этом смысл, если область стека нормально адресуется? Разве только в крайних вариантах экономии ОЗУ?

V>В простейших случаях (и в отсутствии рекурсии) компиляторы способны статически распределить в ОЗУ локальные переменные с перекрытием.


Они это делают в точности по тому же принципу, что и распределение памяти для вложенных друг в друга struct/union.

V>тогда программист закатывает рукава и выполняет такое распределение сам, если знает, что некие ф-ии не вызывают друг друга (даже сколь угодно косвенно) ни в каком из сценариев.


Вот я и не понимаю, для чего тут "закатывать рукава", ежли достаточно определить соответствующую комбинацию struct/union, в которой каждой структуре будет соответствовать ее собственный набор локальных переменных. Если есть рекурсия, то один общий union распадается на несколько, достаточно лишь двигать указатель по тому ручному стеку. Ну а дальше напрашивается только запихать все это в общий стек.

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


V>Да, можно через union, но с той оговоркой, что ты не объявляешь такую глобальную переменную, а высчитываешь ее адрес "в уме"


В упор не понимаю, зачем что-то "высчитывать в уме". Если нет рекурсии, то общий/корневой union, в который вложено все остальное, тупо размещается по известному адресу — хоть по нулевому, если возможно. Если рекурсия есть, то добавляется переменная-указатель этого "ручного стека".
Re[7]: Самый низкоуровневый язык, ага
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 29.09.23 10:20
Оценка:
Здравствуйте, 777777w, Вы писали:

7>что она должна делать, какой анализ проводить, чтобы осмыслить эти данные и извлечь из них что-нибудь полезное?


Это далеко не всегда настолько сложно, как может показаться. Атаки всегда проводятся адресно — на известные приложения, используемые ими библиотеки (системные или сторонние), на определенные последовательности операций. Это почти всегда создает в памяти определенную "картинку", на которую всего лишь нужно правильно посмотреть.
Re[7]: Самый низкоуровневый язык, ага
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 29.09.23 10:46
Оценка:
Здравствуйте, 777777w, Вы писали:

M>>Про спектр и мельдоний уязвимости слышал? А там шпиономания уже на порядок выше


7>Не слышал. Можно ссылку?


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

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


ЕМ>Вот и интересно, как с этим справляются стандартные заголовки. Или они просто никогда не определяют функций?


В заголовках — только объявления. Определения — в сишниках. Ты что, правда не знаешь, заче м нужны заголовки?



M>>Это не CRT


ЕМ>Да — строго говоря, это "стандартная библиотека", как и mem*, str* и прочие. И не все шаблоны, определенные в стандартных заголовках C++, самодостаточны, они могут тянуть функции из библиотеки — те же mem*.


Тянуть могут, но это не CRT


M>>Это если ты не хочешь вывести строку определенной длины с определенным выравниванием


ЕМ>А если хочу, то через потоки это делается интуитивно, в голове ничего держать не нужно, и в документацию лезть — тоже?


Ха стандартные потоки не скажу, а у меня это будет так:
using namespace omanip;
out << left << width(20) << str;

И никуда лазать не надо, и с типами не обосраться
Маньяк Робокряк колесит по городу
Re[8]: Самый низкоуровневый язык, ага
От: 777777w Россия  
Дата: 29.09.23 12:52
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

7>>что она должна делать, какой анализ проводить, чтобы осмыслить эти данные и извлечь из них что-нибудь полезное?


ЕМ>Это далеко не всегда настолько сложно, как может показаться. Атаки всегда проводятся адресно


Что значит "атака"? Программа здесь совершенно пассивна, если повезёт — то ей будут доступны данные каких-то программ (и она даже не знает каких именно), а не повезёт — будет пустая память.
Re[9]: Самый низкоуровневый язык, ага
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 29.09.23 13:20
Оценка:
Здравствуйте, 777777w, Вы писали:

7>Что значит "атака"?


Это значит, что есть такой термин в сфере информационной безопасности. Вроде отрезка или множества в математике.
Re: Самый низкоуровневый язык, ага
От: andyp  
Дата: 01.10.23 11:20
Оценка: +1
Здравствуйте, vsb, Вы писали:

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


И ты ее разделяешь что ли? С — абстрактная машина, описанная в стандарте. Много какое железо плохо с этой абстрактной машиной согласуется. На нем С близким к железу быть перестает.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.