Давненько мы не говнокодили :(

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Берём Uno или Нано (или что угодно на 328P), подключаем светодиод на 9-ый пин и любуемся :-)

//
// Uno / Nano и всё, что на ATmega328P
// Нужен светодиод на 9-ом пине
//
#define _ (&ADC-42)
void setup(void) { digitalWrite(9, *_=(_[50]=(_[46]=53<<6)<<1)>>10); }
void loop(void) {}

Или вот ещё, тоже самое, но чуть покороче и поговнистее:

//
// Uno / Nano и всё, что на ATmega328P
// Нужен светодиод на 9-ом пине
//
#define _ (&ADC+4)
void setup(void) { pinMode(9, _[4]=(*_=3392)*2); }
void loop(void) {}
negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

И не лень же вам :) &ADC+4+4 будет TCCR1A :)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

negavoid2 пишет:

И не лень же вам :) &ADC+4+4 будет TCCR1A :)

Да что Вы!? Не может быть!

На самом деле - это секретное, недокументированное значение второго параметра pinMode. которое вгоняет пин в секретный, недокументированный режим мигания! Во как!

А не то, что тут некоторые ... инсинуации ... панимаешь! 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

а так можно было )))

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Нет, конечно!

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

На самом деле ваши загадки интересные, в процессе отгадки обязательно узнаётся что-то новое, так что давайте истчо :)

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

negavoid2 пишет:

На самом деле ваши загадки интересные, в процессе отгадки обязательно узнаётся что-то новое, так что давайте истчо :)

присоединюсь, по ощущениям будто "кобылу на невольничьем рынке выбираешь" )))

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

Нет, у меня не такие ощущения :)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

ua6em пишет:
будто "кобылу на невольничьем рынке выбираешь" )))
Не доводилось выбирать. Это как?

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Женя! Прости старого пьяницу, но мне захотелось спросить тебя, вместо анализа стандарта. Почему xxx[4] прибавило 4, а не 8, когда xxx указатель на  uint16_t? Пусть это будет считаться пробелом в моей эрудиции ;)))).

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, вот же второй скетч

//
// Uno / Nano и всё, что на ATmega328P
// Нужен светодиод на 9-ом пине
//
#define _ (&ADC+4)
void setup(void) { pinMode(9, _[4]=(*_=3392)*2); }
void loop(void) {}

_ = (&ADC+4) = 0x78 + 8 = 0x80 (TCCR1A)

Далее само выражение

_[4]=(*_=3392)*2

Первой выполняется жёлтая часть. Здесь по адресу 0x80 укладывается значение 3392 (0x0D40). При этом младший байт попадает в TCCR1A (0x80), а старший байт - в TCCR1B (0x81). Результат присваивания - как всегда то, что присвоилось - 3392.

В объемлющей части, это число умножается на 2 и попадает по адресу 0x80  + 8 = 0x88, а это 16-битный регистр OCR1A. 

Вот и весь фокус.

Кстати, на 2 можно было и не умножать - было бы ещё короче. Частота вдвое больше - и нормально, она ещё вполне прилично мигает - не слишком часто.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

В качестве извинений за то, что никак не мог совместить 4, 8 и 40° я "приговнокодил" мигание на встроенном диоде. ;))

Пришлось еще макрос и ISR добавить, но так даже поговнистие выглядит! Можно было не делать макрос с указателем на uint8_t, но тогда  придется пренебречь искажением соседних регистров, хотя ради говнокода - можно. А прерывание придает значимости! ;))

Для "образности" можно вместо 13 написать LED_BUILTIN.

#define _ (&ADC+4)
#define __ (&ADCL-85)
ISR(__vector_11) {*__ = (int)__-3;}
void setup(void) { pinMode(13, _[4]=(*_=3392)*(__[76]=2));}
void loop(void) {}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Граф, вот на самом деле сволочи гуры пудрят новичкам мозг какой-то тарабарщиной и птичьим языком типа digitalWrite и прочими никому непонятными HIGH и LOW.

А способы программировать просто - выдавая команды обычным текстом, почти по русски - скрывают.

Вот например, что понятнее

digitalWrite(13, HIGH);
digitalWrite(13, LOW);

или простыми словами:

U > 13   ---  подать напряжение на 13-ый пин
U < 13   ---  снять напряжение с 13-го пина  

ну, ведь второе намного же понятнее! 

Но ни один гура никогда такого новичку не покажет! Конкурентов будущих боятся.

Хотя, казалось бы, чего проще:

#define RUN_PHRASE(s) { static const uint8_t n[4] PROGMEM = { s[0]-'(',s[1]+'\\',s[2]-')',s[3]+'b'};((void(*)(void))n)(); }

void setup(void) { 
	pinMode(13, OUTPUT);
}

void loop(void) {
	RUN_PHRASE("U>13"); // подать напряжение на 13-ый пин
	delay(500);
	RUN_PHRASE("U<13"); // снять напряжение с 13-го пина
	delay(500);
}

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

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

sbi pinb небось :)

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

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ворота как-то какому-то такому "сдатчику", под обещание, что расскажет как сдал, написал готовый код (на брейнфаке). Так тот, сучка, исчез и так ничего и не рассказал.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

negavoid2 пишет:

sbi pinb небось :)

Ну, макрос-то один. Так что, от строки зависит

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

Лень опкоды смотреть, а историю эту я помню, не будут они такое сдавать, побоятся.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

ЕвгенийП пишет:

В объемлющей части, это число умножается на 2 и попадает по адресу 0x80  + 8 = 0x88, а это 16-битный регистр OCR1A. 

на вавгаде не сработает видимо, так как OCR1A надо грузить как два восьмибитных

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

ua6em пишет:

на вавгаде не сработает видимо, так как OCR1A надо грузить как два восьмибитных

Первая строка первого сапщения. 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

ua6em пишет:

на вавгаде не сработает 

На Fugaku - тоже :-(

ua6em пишет:

OCR1A надо грузить как два восьмибитных

На Atmega тоже. И не только OCR1A, а и все 16-битные регистры (TCNT1, ADC и т.п.) - они именно так и грузятся - об этом заботится компилятор.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

И все же Гарвардская архитектура не так много простора для говнокода дает, как родная и любимая фон Неймановская! Согласимся?

Как здорово и свободно говнокодится на ПиСюке! Мечта просто!

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

ЕвгенийП пишет:

На Atmega тоже. И не только OCR1A, а и все 16-битные регистры (TCNT1, ADC и т.п.) - они именно так и грузятся - об этом заботится компилятор.

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

kolyn
Offline
Зарегистрирован: 18.01.2019

ЕвгенийП пишет:

Хотя, казалось бы, чего проще:

#define RUN_PHRASE(s) { static const uint8_t n[4] PROGMEM = { s[0]-'(',s[1]+'\\',s[2]-')',s[3]+'b'};((void(*)(void))n)(); }

Вам с Графом весело, а я дурак-дураком второй час этих "пляшущих человечков" пытаюсь расшифровать...

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

kolyn пишет:
"пляшущих человечков" пытаюсь расшифровать...
Ну, хоть запускал? Работает?

kolyn
Offline
Зарегистрирован: 18.01.2019

ЕвгенийП пишет:

kolyn пишет:
"пляшущих человечков" пытаюсь расшифровать...
Ну, хоть запускал? Работает?

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

суровый пустой молчаливый пост :)

kolyn
Offline
Зарегистрирован: 18.01.2019

kolyn пишет:

ЕвгенийП пишет:

kolyn пишет:
"пляшущих человечков" пытаюсь расшифровать...
Ну, хоть запускал? Работает?

Вот это и печально)) Работает!

Пысы. Предидущий пост - мой бок))

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

ну а чего бы и не работать :)

перед компиляцией макрос разворачивается в 4-байтную функцию, ((void(*)(void))n)(); вызывает её. Функция, скорее всего, ставит/выключает бит в зависимости от < >. Вычислите значения этих четырех байт U-(, <+\ или >+\, 1-), 3+b да посмотрите по таблице опкодов 328p что за инструкции.

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

Эти же два примера также отлично демонстрируют возможности си по стрелянию себе в ногу, вон, у мк прямой доступ ко всей памяти, порти что хочешь, всё на твоей ответственности :)

Забавный момент для Евгения Петровича, я избалованный тем самым х86, поначалу тупанул, думаю, какая там нафиг память с нуля, и только потом сообразил, а мля, codeseg-то не там, а отдельно :) Из полезного - узнал как маппинг i/o у 328 сделан, оказывается, в начале адресов перед оперативкой, мило. Ну а второй пример уже не тупил )) Может это вы так тренируете нас на архитектуры? ))

kolyn
Offline
Зарегистрирован: 18.01.2019

negavoid2 пишет:

Вычислите значения этих четырех байт U-(, <+\ или >+\, 1-), 3+b 

Если это  понятно, то

negavoid2 пишет:

перед компиляцией макрос разворачивается в 4-байтную функцию, ((void(*)(void))n)()

как это работает (массив в прогмем становится функцией) - понять не могу

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

Прогмем - секция флеша, кода, всё, что хранится в ней - код, его можно вызвать переходом по адресу, и он начнёт выполняться. Когда мы пишем строки F(***), мы на самом деле просто сохраняем данные в кодовый сегмент, просто потому, что он большой, а потом они оттуда читаются. Можете вызвать jmp *("xxx"); и строки как бы исполнятся, смотря какие там опкоды, это, видимо, Евгений Петрович приберёг для следующего примера.

Вот эта конструкция, с войдами :) - это такой сишный трюк, чтобы вызвать на исполнение код по адресу n в прогмем, а там находится соответственно эта строка опкодов, вычисленных перед компиляцией из s+символ.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

negavoid2 пишет:
Может это вы так тренируете нас
Нет, я так развлекаюсь.

Вот даже не знаю, верить или нет - мне эту историю рассказал парень - очень скромного/небольшого ранга дипломат. Он клялся, что правда ... Рутинная тусовка в ООН, никаких высоких лиц - обычная каждодневная рутинная встреча чиновником самого мелкого масштаба. Американец (А) наезжает на китайца (К) и тычет ему в нос спутниковые фото на которых видно, что с крейсера Ляонин взлетают самолёты:

К. И что Вас не устраивает? Зона закрыта для судоходства, опасности ни для кого нет.

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

К. Оно именно так и используется.  Развлекательный центр.

А. А почему же с него взлетают истребители?

К. (не моргнув глазом) Мы так развлекаемся.

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

вот-вот :)

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

negavoid2 пишет:

вот-вот :)

Это как квайн - упражнение для ума.

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

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

Мне-то объяснять не нужно, сам такой же. Хотя чаще всё же стараюсь больше в непрофессиональной области развлекаться, типа как ваш кемпер. Демками в 90е  немножко увлекался, можно было писать в регистры vga и трясти мониторы по-разному, воксели, родители нынешних шейдеров были прикольными :)

kolyn
Offline
Зарегистрирован: 18.01.2019

Если кому окромя меня интересно, что значит

((void(*)(void))n)();

тыц сюда. Интернет великая весчь, жаль будет, если запретят))

Остался последний вопрос "опкоды" - это куда?

 

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020
kolyn
Offline
Зарегистрирован: 18.01.2019

(задумчиво, печально) -Ндааа.

Но, тем не менее спасибо, буду знать, что такое существует))

 

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

А как без этого писать компилятор, тот же gcc?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

неужели кто-то еще пишет в машинных кодах, повеяло далёкими 80 и интел 8080

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

kolyn пишет:

(задумчиво, печально) -Ндааа.

Но, тем не менее спасибо, буду знать, что такое существует))

На самом деле всё проще. Чтобы пошутить, как пошутил я, вовсе необязательно изучать все коды. Достаточно написать на Си и посмотреть ассемблерный листинг (а AVR Studio он доступен сразу без всяких телодвижений, а в IDE надо дизассемблер запустить)

	_digitalWrite(13, HIGH);
  90:	2d 9a       	sbi	0x05, 5	; 5
  92:	08 95       	ret

	_digitalWrite(13, LOW);
  94:	2d 98       	cbi	0x05, 5	; 5
  96:	08 95       	ret

Красненькое - это оно и есть.

Как видите, разница между кодами только в одном байте: 9A и 98. И разница эта равна 2. А теперь смотрим на разницу в кодах '>' и '<' - тоже 2. Вот макрос единообразно куда надо и преобразует.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

а это что значит?

0x05, 5	; 5

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

0x05, 5- операнды команды. Точка с запятой - начало комментария. Всё, что после неё - комментарий.