ViKo 1 25 августа, 2018 Опубликовано 25 августа, 2018 · Жалоба Поскольку было объяснение, что писалось на конкурс уложить код в 1К, то допустимы и приветствуются любые извращения. Классические принципы здесь не нужны. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 241 25 августа, 2018 Опубликовано 25 августа, 2018 · Жалоба Про CPU с различными подходами в копировании char не знал, спасибо. Интересно конечно, как это может так быть - ведь копируются 8 бит все равно... Загляните как-нить в листинг Cortex-M3/4 кода и сравните команды LDRB и LDRSB например. Поймёте почему. Для этого имхо и ввели дополнительный чекбокс в IAR "signed/unsigned char". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 183 25 августа, 2018 Опубликовано 25 августа, 2018 (изменено) · Жалоба Загляните как-нить в листинг Cortex-M3/4 кода и сравните команды LDRB и LDRSB например. Поймёте почему. Для этого имхо и ввели дополнительный чекбокс в IAR "signed/unsigned char". Сходу не получилось заставить компилятор сгенерировать LDRSB... Использую armcc в составе Keil. Оптимизация 0. Галка "Plain Char is Signed" сброшена. Код volatile signed char a = 10; volatile signed char b = 20; volatile signed char c; int main(void) { c = a - b; while(1); } формирует следующий листинг 0x080002E0 4805 LDR r0,[pc,#20] 0x080002E2 7800 LDRB r0,[r0,#0x00]; загрузили a 0x080002E4 4905 LDR r1,[pc,#20] 0x080002E6 7809 LDRB r1,[r1,#0x00]; загрузили b 0x080002E8 1A40 SUBS r0,r0,r1 ; вычли 0x080002EA B240 SXTB r0,r0 ; ИМХО, лишнее, т.к. SUBS работает 32-битными числами 0x080002EC 4904 LDR r1,[pc,#16] 0x080002EE 7008 STRB r0,[r1,#0x00]; загружаем результат в переменную c В случае, если переменные объявить без спецификатора signed (то есть с unsigned) то листинг тот же самый, но без SXTB С оптимизацией -O3 для signed/unsigned листинг одинаковый: 0x0800028C 4803 LDR r0,[pc,#12] 0x0800028E 7801 LDRB r1,[r0,#0x00] 0x08000290 7842 LDRB r2,[r0,#0x01] 0x08000292 1A89 SUBS r1,r1,r2 0x08000294 7081 STRB r1,[r0,#0x02] Изменено 25 августа, 2018 пользователем Arlleex Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 241 25 августа, 2018 Опубликовано 25 августа, 2018 · Жалоба Сходу не получилось заставить компилятор сгенерировать LDRSB... Использую armcc в составе Keil. Оптимизация 0. Галка "Plain Char is Signed" сброшена. Всего лишь оптимизация умного компилятора :rolleyes: Вы сами подумайте: раз Вы результат обратно сокращаете до 8 бит, то зачем тогда старшие биты вычислять? А если их вычислять не нужно, то можно ограничиться командами LDRB как более "дешёвыми". :laughing: Тест Ваш построен некорректно. Для корректности теста сделайте int volatile c. Тогда, думаю, увидите LDRSB. Ну и для теста можно одно из a или b сделать отрицательным. 0x080002EA B240 SXTB r0,r0 ; ИМХО, лишнее, т.к. SUBS работает 32-битными числами Хоть это и лишнее, но это был намёк компилятора, что он заметил достаточность использования 8-бит для результата и поэтому не стал заморачиваться с правильным расширением входных аргументов. :rolleyes: PS: Код теста не совсем корректный, так как должен вызвать warning "undefined behavior". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 183 25 августа, 2018 Опубликовано 25 августа, 2018 · Жалоба Тест Ваш построен некорректно. Для корректности теста сделайте int volatile c. Тогда, думаю, увидите LDRSB. Точно! И вправду LDRB заменились на LDRSB... Просто с расширением знака. Все четко по описанию команды загрузки с расширением знака :rolleyes: Единственное, что отмечу. Разницы в количестве тактов выполнения не заметно... То есть по факту выполняются они одинаково по времени, только лишь представление числа в памяти нужным образом расширяется или нет, вот и вся разница, вроде как. PS: Код теста не совсем корректный, так как должен вызвать warning "undefined behavior". Из-за int перед main() и отсутствия возвращаемого результата? Тогда не неопределенное поведение, а что-то типа "недостижимый участок кода" и "отсутствие возвращаемого значения в функции, которая возвращает int"... Но Keil не паникует, кстати... :laughing: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 241 25 августа, 2018 Опубликовано 25 августа, 2018 · Жалоба Единственное, что отмечу. Разницы в количестве тактов выполнения не заметно... То есть по факту выполняются они одинаково по времени, только лишь представление числа в памяти нужным образом расширяется или нет, вот и вся разница, вроде как. Конечно разницы в тактах нет при условии наличия команды в кеше/конвеере CPU. Но в реальном МК команду ещё нужно выбрать из памяти, а ширина шины к памяти программ не бесконечна, как и скорость последней. Так что по времени выполнения - Вы не правы. Из-за int перед main() и отсутствия возвращаемого результата? Нет. Из-за того, что в одном выражении используются две volatile-переменные. Порядок чтения которых внутри выражения неопределён. А volatile подразумевает строгость в порядке доступа. Но Keil не паникует, кстати... :laughing: А зря. IAR реагирует на подобные выражения: "undefined behavior". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 183 25 августа, 2018 Опубликовано 25 августа, 2018 (изменено) · Жалоба Конечно разницы в тактах нет при условии наличия команды в кеше/конвеере CPU. Но в реальном МК команду ещё нужно выбрать из памяти, а ширина шины к памяти программ не бесконечна, как и скорость последней. Так что по времени выполнения - Вы не правы. Открыл TRM на Cortex-M3. Вижу, что CPI на LDRB и на LDRSB одинаковы и составляют 2 такта. Одинакова и их синтаксическая запись. Существуют как 16-битные, так и 32-битные версии обеих команд. При всех прочих равных условиях время выполнения LDRB и LDRSB одинаково. То, что команду нужно выбрать из памяти - это понятно. Но LDRB нужно выбрать точно так же, как и LDRSB в одном и том же коде. Ничем не отличается. Другое дело, если мы говорим о том, что загружать значение как оно есть и лишь потом программно еще расширять знак. Там да, несколько команд нужно: тот же LDRB + расширение знака, если требуется. Нет. Из-за того, что в одном выражении используются две volatile-переменные. Порядок чтения которых внутри выражения неопределён. А volatile подразумевает строгость в порядке доступа. Да, в упор не увидел очевидное... Жаль Keil не ругнулся никак даже при установке "All Warnings" в настройках компилятора :crying: Изменено 25 августа, 2018 пользователем Arlleex Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 241 25 августа, 2018 Опубликовано 25 августа, 2018 · Жалоба Открыл TRM на Cortex-M3. Вижу, что CPI на LDRB и на LDRSB одинаковы и составляют 2 такта. Одинакова и их синтаксическая запись. Существуют как 16-битные, так и 32-битные версии обеих команд. При всех прочих равных условиях время выполнения LDRB и LDRSB одинаково. А Вы когда-нибудь пробовали заглядывать в листинг? И сколько вы там видели LDRB разной длины и сколько LDRSB? :laughing: Формы-то может и есть, тут вопрос в количестве.... Попробуйте в .asm-файле ввести 2 такие команды и скомпилить: LDRB R0, [R0, #0] LDRSB R0, [R0, #0] А потом попробуйте поизменять регистры от R0 до R7 и посмотреть что получается. А теперь загляните в листинги и увидите, что большинство обращений к памяти как раз подобные формы команд: косвенная с константным смещением. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 183 25 августа, 2018 Опубликовано 25 августа, 2018 · Жалоба А Вы когда-нибудь пробовали заглядывать в листинг? И сколько вы там видели LDRB разной длины и сколько LDRSB? :laughing: Формы-то может и есть, тут вопрос в количестве.... Мда, в листинге действительно LDRSB используются всегда 32-битные, очевиден проигрыш... Причем какие бы регистры не использовали - младшие или старшие - все равно берется команда Thumb-2 (32 бит). А вот LDRB, при использовании младших регистров в качестве операндов, компилируется в 16-битной Thumb форме; при использовании старших регистров - законно Thumb-2. P.S. Почитал тут в мануале. Если запись команды LDRSB использует форму с непосредственным смещением от базового регистра, то такая команда существует только 32-битная. Для LDRB такая команда есть в 16 битах, только там непосредственное значение ограничено 5 битами. Теперь все понятно! jcxz, благодарю за полезную информацию :rolleyes: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Obam 38 25 августа, 2018 Опубликовано 25 августа, 2018 (изменено) · Жалоба Во времена настали: раздел про AVR, а тут про приготовление ARMов. Изменено 25 августа, 2018 пользователем Obam Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 241 25 августа, 2018 Опубликовано 25 августа, 2018 · Жалоба Во времена настали: раздел про AVR, а тут про приготовление ARMов. А что - AVR ещё жив? :rolleyes: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Obam 38 27 августа, 2018 Опубликовано 27 августа, 2018 · Жалоба Ну, на фоне 6502 и z80 вполне себе... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться