ViKo 1 28 июня, 2010 Опубликовано 28 июня, 2010 · Жалоба Прежде, чем писать новое, изучил в отладчике работу обеих моих программ - начальной si16toad и измененной itoa, в которой операции % и / были заменены вызовом библиотечной функции div. Напомню: Keil uVision - RealView MDK-ARM 4.10, STM32F103. Результаты оказались интересными. После компиляции в окне Build Ouitput для обеих программ выдаются одинаковые размеры для кода - 548 байтов при оптимизации O0 и 536 байтов при оптимизации O3. Почему они одинаковые, не понимаю (см. ниже)?! Размеры данных всех типов тоже одинаковые вообще всегда, но это, как раз, не удивляет. Посчитал размер обеих функций по листингу C компилятора (есть галочка в настройках генерировать листинг). При O0 для si16toad насчитал 84 байта, для itoa 98 байтов (не считая 14 байтов в самой функции div, это уже в отладчике увидел). При O3 - 80 байтов и 94 байта, соответственно. Причем, при оптимизации O0 в si16toad команда деления использовалась дважды, а при O3 только один раз. В-общем, мой первый вариант оказался компактнее. Посчитал в отладчике количество тактов. Счетчик тактов виден в окне регистров, засекал значение перед вызовом своей функции и после нее. При O0 si16toad выполнялась за 171 такт, itoa за 232 такта. При O3 - 121 такт и 210 тактов, соответственно. Мой первый вариант оказался еще и быстрее. Увидел лишние знаковые и беззнаковые расширения для переменных меньше 32 байтов. Вот здесь буду совершенствовать программу. Массив или указатель - тоже проверю. Заносить пробелы сразу - их, к сожалению, максимум 5 (не 4). Над этим и др. пока думаю. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 28 июня, 2010 Опубликовано 28 июня, 2010 · Жалоба Заносить пробелы сразу - их, к сожалению, максимум 5 (не 4). Над этим и др. пока думаю. Их у Вас четыре. Можете попробовать на пальцах посчитать от X0 (раз-два) до X32768(раз-два-..шесть). Ну и размер должен быть на на уровне 60 байт, ну и тактов заметно менее. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 28 июня, 2010 Опубликовано 28 июня, 2010 · Жалоба Их у Вас четыре. Можете попробовать на пальцах посчитать от X0 (раз-два) до X32768(раз-два-..шесть). Ну и размер должен быть на на уровне 60 байт, ну и тактов заметно менее. Перед "0" я символ + или - не ставлю (считаю, так "красивее" и "правильнее"), потому и обработка такая в начале программ. Итого _ _ _ _ _ 0 \0. По поводу размеров и тактов - могу выдать весь проект в заархивированном виде. В настройках есть какие-то "галочки", которых не трогал. Может, что-то и упустил... Keil_Temp.zip Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 28 июня, 2010 Опубликовано 28 июня, 2010 · Жалоба Перед "0" я символ + или - не ставлю Вы ставите один из 3x символов. Вот и ставьте. Таки 4 :) По поводу размеров и тактов - могу выдать весь проект в заархивированном виде. Я говорю об аккуратно написанном, посему про 80 байтов в Вашем варианте верю. Сделайте 60 :). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 29 июня, 2010 Опубликовано 29 июня, 2010 · Жалоба 2 zltigo Непременно. :) Выставил две "галки" - Use Cross-Module Optimization и Use MicroLIB. Общий размер кода сократился до 212 и 324 байтов для первой и второй программ. Причем, такой размер получается со второго раза компиляции. "Все чудесатее и чудесатее." Что эти параметры делают? А на конкретный размер и состав кода пока не смотрел. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 29 июня, 2010 Опубликовано 29 июня, 2010 · Жалоба void itoad(int number, uint8_t *string) { uint8_t sign; *(int32_t *) string = ' ' | ' ' << 8 | ' ' << 16 | ' ' << 24; *(int32_t *)(string + 4) = ' ' | ' ' << 8 | ' ' << 16 | ' ' << 24; *(int32_t *)(string += 8) = ' ' | ' ' << 8 | '0' << 16 | '\0'<< 24; if (!number) return; if (number > 0) sign = '+'; else { number = -number; sign = '-'; } string += 2; do { *string-- = number % 10 + '0'; } while (number /= 10); *string = sign; } Работает с 32-битовыми числами со знаком. string должна быть 12 байтов для 32-битового числа. 60 байтов (+ 4 байта хранят константу "_ _ 0"). ~207 тактов. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 143 29 июня, 2010 Опубликовано 29 июня, 2010 · Жалоба *(int32_t *) string = Знатная грабля. Исключение при первой же string, начало которой не попадает на границу 4 байт. Или просто порушенные соседние данные. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 29 июня, 2010 Опубликовано 29 июня, 2010 · Жалоба Знатная грабля А для Cortex-M3? А как надо по вашему мнению? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 29 июня, 2010 Опубликовано 29 июня, 2010 · Жалоба Знатная грабля. Исключение при первой же string, начало которой не попадает на границу 4 байт. Или просто порушенные соседние данные. Это гнулось под Cortex - такая вот игра. 60 байтов Чуть симпатичнее и скорее всего еще короче: void itoad(int number, uint8_t *string) { uint8_t sign; *(uint32_t *) string = ' '; *(uint32_t *)(string + 4) = ' '; *(uint32_t *)(string += 10) = (uint32_t )" 0"; if (!number) return; if (number > 0) sign = '+'; else { number = -number; sign = '-'; } // string += 2; do { *string-- = number % 10 + '0'; } while (number /= 10); *string = sign; } Осталось первоначальную 16bit оптимизировать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 29 июня, 2010 Опубликовано 29 июня, 2010 · Жалоба *(uint32_t *) string = ' '; *(uint32_t *)(string + 4) = ' '; Осталось первоначальную 16bit оптимизировать. Кавычки не двойные? Из этой 16-битов автоматически получается, если малое число использовать и буфер соответствующий. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 29 июня, 2010 Опубликовано 29 июня, 2010 · Жалоба Кавычки не двойные? В первых двух - нет. Возможны warnings, правда, поскольку символ wide получается ИЗ 4x ПРОБЕЛОВ. А так нормально. В третьей - три символа в двойных. Из этой 16-битов автоматически получается, если малое число использовать и буфер соответствующий. Автоматически, не значит оптимально. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 29 июня, 2010 Опубликовано 29 июня, 2010 · Жалоба *(uint32_t *)(string += 10) = (uint32_t )" 0"; Так - нельзя, пропускается два байта. С кавычками - понял, но варнинги... как бы удовлетворить требованиям компилятора? #define FOUR_SPACES 0x20202020 *(uint32_t *) string = FOUR_SPACES; Нормально? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 29 июня, 2010 Опубликовано 29 июня, 2010 · Жалоба Так - нельзя, пропускается два байта. А, да. Что-то ошибся. Тогда так: *(uint32_t *)(string += sizeof(int32_t)) = ' '; *(uint32_t *)(string += sizeof(int32_t)) = (uint32_t )" 0"; string += 2; Есть шанс на экономию пары байт. С кавычками - понятно, но варнинги... как бы удовлетворить требованиям компилятора? Ну, например, отключить их локально прагмой, либо таки (long)" ", но константа займет 8 байт. Нормально? Да. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 29 июня, 2010 Опубликовано 29 июня, 2010 · Жалоба *(uint32_t *)(string += sizeof(int32_t)) = ' '; *(uint32_t *)(string += sizeof(int32_t)) = (uint32_t )" 0"; string += 2; Есть шанс на экономию пары байт. В смысле, прилепить string +=2 сразу к предыдущему выражению, использующему указатель? А, заменить +8 +2 на +4 +4 +2? upd. Попробовал и так, и сяк, и +10, лучше не становится. 16-битовую хочу попробовать с применением формата 4.28, как у aaarrr. А с тем, что сделал для 32 битов, и не знаю, куда уж дальше "копать" для 16 битов. Я, собственно, с 16-битовой и возился, пока не увидел, что 32-битовая из нее получается практически "даром":) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 29 июня, 2010 Опубликовано 29 июня, 2010 · Жалоба В смысле, прилепить string +=2 сразу к предыдущему выражению, использующему указатель? Вот как написано, так пробуйте. что 32-битовая из нее получается практически "даром":) Полагаю, что там есть как минимум один нюанс - не ухудшить шестнадцатибитовостью ну и чуть поджать за счет меньшего буфера. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться