Обновить
34
Михайлов Алексей Анатольевич@MinimumLaw

Linux Kernel, Bare metal, Embedded developer

0,2
Рейтинг
13
Подписчики
Отправить сообщение

Согласен, не самая правильная формулировка. Но...

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

Почему не меняет? Как раз меняет. Достаточно посмотреть на ассемблерных код, получаемый из указанного примера.

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

Потом переделываем процессоры, чтобы они такие глупости не делали, а клали в вещественный, нечего остатку пропадать.

Ты не поверишь (с), но в большинстве известных мне архитектур остаток не пропадает. А путь для работы оптимизатора в конструкциях типа

int a,b,c,d;
...
  c = a/b;
  d = a%b;

вполне очевиден. В отличии от операций с вещественными числами.

Вы можете продолжать думать, что код на C++ написан для оборудования, я вряд ли в силах вас переубедить.

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

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

Я утащу это в список цитат. Про остальное - сдвиг отрицательных чисел тоже не просто так UB. И те, кто работает с реальным железом об этом знают. К сожалению, авторы компиляторов... Впрочем, не будем о грустном.

P.S.

Впрочем, доля правды есть. На С переносимо очень сложно поймать overflow/underflow. И не только это. И тут да - не все хотелки можно.

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

Интересно. А я думал, что мне, embedder'щику, деньги платят ровно за это. И язык С создавался как "переносимый ассемблер"... Я бы позволил такие вольности плюсам. Они, обычно, сильно дальше от аппаратуры. Но классическому, безплюсовому С... Это уже перебор.

Проверьте, если GCC под них собирать умеет.

Прямо сейчас в доступе нет. Да и специфика тамошней аппаратуры накладывает некоторые ограничения на использование scanf/printf. Но при случае проверю. Не забуду - отпишусь с результатами.

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

Т.е. все таки цензура. Вариант "потому, что могу" не катит. Малоли что ты можешь - высший разум считает что не нужно.

Тогда и выражайте свои намерения явно, x = 255?

Вы ограничиваете мою свободу, как автора? В другом мире это называется словом цензура и сильно не приветствуется. Я не говорю что так правильно. Я говорю что так можно - аппаратура это не запрещает. А любой компилируемый код, в конце концов работает именно на аппаратуре. Даже если кому-то кажется по другому.

Компилятор ничего не додумывает, да и на намерения художника ему все равно.

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

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

Я не против, чтоб деление или умножение на 2^n заменяли сдвигом - все в рамках. Но если я пишу x/x то это означает именно то, что мне НЕОБХОДИМО поделить x на x. И я, как автор, понимаю как это будет работать на конкретной аппаратуре. И ожидаю вполне конкретный выхлоп от компилятора и реакцию оборудования. Я не нарушаю ни правила для оборудования, ни правила формальной системы. С чего вдруг не делается то, что нужно мне как автору?

То же про volatile - к сожалению очень часто приходится пользоваться этим указанием там, где оно не должно стоять в принципе. Это приводит к крайне плохому стилю написания кода, когда оное указание ставится "на всякий случай". Что в корне неправильно.

Либо берете в руки asm.

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

Впрочем, SUN еще в далеком 2008-ом с гордостью рассказывала о том, что мы теперь оптимизируем и ассемблерные вставки. Мы лучше знаем - у нас есть контекст окружения. А недовольны - используйте volatile asm {}; Так что лучше отдельным файлом.

Ну да - та самая детская уверенность. Мы лучше взрослых все знаем... И взрослая улыбка в ответ: "Ок! Действуй! Пока сам шишек не набъешь все равно не поймешь". Так что пусть не страдает. Страдать будет позже, когда подрастет.

Дайте ссылку на компилятор Rust для PIC и AVR. А еще для AIX, beOs, OS/2 и MSDOS (а еще Windows 3.1, QnX и прочего зооларка и бестиария возможных осей и архитектур).

Нет, он не умер молодым. Но в лучшем случае детский сад с отличием закончил. А доживет ли хотя бы зрелости - это мы еще посмотрим.

Да я и не отрицал этого.

А это, на самом деле, очень спорный вопрос. Дело компилятора транслировать код в язык аппаратуры. И если автор желает делить на ноль - на здоровье. Дели. И уже аппаратура будет решать что делать. А решить она может по разному. Например 8051 выставит флаги и (сюрприз!) неопределенный результат (который обычно 0xFF, но это не точно). АVR и PIC даже флагами не пошевелят, правда выставят 0xFF. ARM кинет исключение. Собственно это и есть причина, по которой в С это UB.

И не дело компилятора додумывать что я, как автор, хочу в данном месте. Может мне надо таким вот образом 0xFF в регистры на AVR поместить. Или флажки выставить на PIC. Или принудительно в исключение свалиться. Я автор - мне решать. А компилятор... Может помочь - замечательно. Но мешать не надо.

Да что вы прицепились к стандарту языка, которому уже много лет. Он пережил разный endian, разную разрядность и много чего еще. Все его UB просто следствие необходимости работы в очень разном окружении, которое не ограничивается Linux на amd64/arm64. Проблема не в стандарте. Проблема в избыточной оптимизации, ломающей логику работы. А подобные проблему будут у абсолютно любого языка, когда он достигнет зрелости. Только вот... Большинство умирает молодыми и просто не доживут до этой прекрасной поры. Ну устаю повторять про python при переходе со 2-ой на 3-ю версию. Он уже поломался. В отличии от дряхлого старичка, который держится.

Впрочем - ну его нафиг. Я не буду ввязываться в очередной раз в эти войны. Вообще учить детей сегодня С или плюсам - ну так себе идея. Сюда надо ЗАХОТЕТЬ погрузиться. Это очень специфические языки для очень специфических задач. Это не то, с чем есть шанс случайно встретиться. Удел инженеров. С старом смысле этого слова.

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

Впрочем, это порождает "проблему вагонетки" в мире кода - что лучше, выдать неверный результат на определенной итерации или упасть и прекратить дальнейшую работу совсем. Плохо только, что вот такими скрытыми оптимизациями решает ту дилемму не разработчик (который должен был бы проверить на ноль, если не сразу то после N-ого падения). От него-то как раз проблему спрятали и сильно усложнили отладку. Хорошо когда результат вот так запросто воспроизводится. А если вычисляется? Да из множества переменных? Впрочем, в таком варианте этой проблемы вроде бы и возникнуть не должно.

Где-то мир свернул не туда. Иногда очень хочется вернуться к славному ассемблеру, где только ты был автором.

Проверил для "младшего брата"
#include <stdio.h>

int x;

void main(void)
{
    scanf("%d",&x);
    printf("%d\n", x/x);
}

константа в коде. Четко как в статье. gcc (Ubuntu 13.3.0-6ubuntu2~24.04.1) 13.3.0

0000000000001169 <main>:
    1169:       f3 0f 1e fa             endbr64
    116d:       55                      push   %rbp
    116e:       48 89 e5                mov    %rsp,%rbp
    1171:       48 8d 05 9c 2e 00 00    lea    0x2e9c(%rip),%rax        # 4014 <x>
    1178:       48 89 c6                mov    %rax,%rsi
    117b:       48 8d 05 82 0e 00 00    lea    0xe82(%rip),%rax        # 2004 <_IO_stdin_used+0x4>
    1182:       48 89 c7                mov    %rax,%rdi
    1185:       b8 00 00 00 00          mov    $0x0,%eax
    118a:       e8 e1 fe ff ff          call   1070 <__isoc99_scanf@plt>
    118f:       be 01 00 00 00          mov    $0x1,%esi
    1194:       48 8d 05 6c 0e 00 00    lea    0xe6c(%rip),%rax        # 2007 <_IO_stdin_used+0x7>
    119b:       48 89 c7                mov    %rax,%rdi
    119e:       b8 00 00 00 00          mov    $0x0,%eax
    11a3:       e8 b8 fe ff ff          call   1060 <printf@plt>
    11a8:       90                      nop
    11a9:       5d                      pop    %rbp
    11aa:       c3                      ret

Справедливости ради - в реальном коде такое встретить сложно, но... Если угораздит, то седых волос при отладке добавит.

И да, для учебного примера куда лучше сгодился бы вариант

#include <stdio.h>

int x;

void main(void)
{
    scanf("%d",&x);
    printf("%d\n", x/(x-1));
}

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

... а в не идеальном, к сожалению, по другому просто невозможно. И это ровно то, на чем всех ловят, и на чем основано 99% методов "социальной инженерии".

В наших краях, видимо, они были экзотикой. А вот эти вполне себе ставили и разрабатывали железки с ними.И даже программировали и отлаживали без BIOS/DOS. Что характерно документация на них была вполне доступна. Да, традиционно под NDA, но доступна. И при желании их вполне можно было применять. Другое дело, что желание их применять не всегда совпадало с возможностью производственных линий - но это уже другая тема. Впрочем до определенного момента они были избыточны, а потом как-то резко стали недостаточны.

Хехе. 386EX в спутниковом телефоне выглядел эпичнее:

Еще эпичнее было обнаружить его в отечественном GPS приемнике. Вообще довольно популярный камушек. И точно более популярный, чем его конкурент ELAN SC300 от AMD. Правда их 400-ая и тем более 500-ая прямых конкурентов не имели. Впрочем, и потребность в подобных решений уже вызывала некоторые сомнения. Что хорошо и видно - так, некоторое количество плат в факторе PC104/PCI104 и не более того.

Ох уж мне эти безопасники....

На самом деле надо исходить из простого - о тебе не знает или ленивый, или тот, кому ты не интересен. Все остальные о тебе знают все - от паспортных данных (привет ЖКУ, сотовые операторы, медицина) до интересов и мест, где ты бываешь (привет соц.сети, не свои так друзей). А самый главный аргумент сегодня - это всякие Deep Fake. В мире, где оное присутствует, напугать чем-то человека знающего что он открытая книга - крайне сложно. Легкость сопоставления реального персонажа с DeepFake ровно так же работает и в другую сторону. Она же становится сложностью в части сопоставить меня с файлом. Чем некоторые наши руководители активно пользуются. Особенно с учетом современной реальности и законов о фейках.

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

Спасибо, просто и со вкусом.

Единственная деталь - все же этот таймер использовать как таймер общего назначения - ну в специальных случаях. А вот оценить время реакции кода на событие - это его основная задача, с которой он очень успешно справляется. Выдавая прямо мечту любого embedder'а - количество тиков. И тут, как правило, отрезка даже в секунду более чем достаточно.

Отличный ответ! Жму руку. И мысли, в принципе, такие же. А у той функции есть ряд подводных камней. Например, если таймерный callback меняет очередь, в первую голову удаляя из нее самого себя...

Но реально есть ощущение, что это мало интересно. В лучшем случае в очередной раз породит срач на тему "как просто это сделать на Rust". Нашего брата здесь совсем не много.

А вариант exec(sha256sum argv[0]) с перехватом stdout в таком варианте не прокатит? Как самый простой вариант?

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

Хороший вариант, а может это быть вызвано плохим монтажом компонента? Лучше с пояснениями.

Мне, право слово, не очень хочется вести собеседование в комментариях. Да и с наймом сейчас откровенно не очень. Я готов продолжать, но надо ли?

Я бы уточнил - все, это ВООБЩЕ ВСЕ, включая SyTick, Watchdog и прочие. А вот про организацию программных таймеров я бы уточнил.
Первый случай - не хватает одного-двух и на заранее известные интервалы. Другой случай - нужно в разные моменты во время выполнения программы, и на разные (рассчитываемые) временные промежутки. Как быть в первом и втором случае. Желательно с подсветкой раскиданных граблей.

1
23 ...

Информация

В рейтинге
3 487-й
Откуда
Пушкин, Санкт-Петербург и область, Россия
Дата рождения
Зарегистрирован
Активность

Специализация

Инженер встраиваемых систем, Архитектор программного обеспечения
Старший
От 350 000 ₽