Сейчас на форуме: rmn, Magister Yoda, vasilevradislav, tyns777, zombi-vadim (+4 невидимых) |
eXeL@B —› Программирование —› Помогите оптимизировать манипуляцию с битами на Си |
Посл.ответ | Сообщение |
|
Создано: 27 апреля 2008 00:14 · Личное сообщение · #1 |
|
Создано: 27 апреля 2008 01:38 · Личное сообщение · #2 |
|
Создано: 27 апреля 2008 01:49 · Поправил: ToBad · Личное сообщение · #3 |
|
Создано: 27 апреля 2008 06:08 · Личное сообщение · #4 |
|
Создано: 27 апреля 2008 12:08 · Личное сообщение · #5 s0larian пишет: ToBad, я думаю что там будет всего несколько инструкций, и далее оптимизировать нету смысла... в смысле если у тебя что-то медлено, то, думаю, проблема не тут. Кста, есть пара спец инструкций для таких дел: "bt r/m32, bit" и btr, btc Дело в том, что пишу я как упомянул ранее под CodeVisionAVR. Это Си для микроконтроллеров. Там свой ассемблер, свои инструкции. Оптимизация нужна не для скорости, а для сокращения числа команд. Есть там конечно свои инструкции для манипуляции битами (bld и bst), которые копируют указанный бит во флаг и восстанавливают назад. Написать функцию с ассемблерными командами у меня не получилось из за того, что упомянутые команды принимают в параметрах регистр и константу. А в функцию я передаю всё через переменные. |
|
Создано: 27 апреля 2008 20:28 · Личное сообщение · #6 ToBad пишет: ...не получилось из за того, что упомянутые команды принимают в параметрах регистр и константу. Помню еще во времена ZX Spectrum в играх использовалась одна интересная оптимизация для уменьшения числа команд. Оптимизация эта была связана с моджификацией кода процедуры. Может и тут получится, если константу в битовой команде модифицировать на лету. |
|
Создано: 27 апреля 2008 21:00 · Поправил: Fallout · Личное сообщение · #7 reversecode пишет: a = ((x >> d) << n); if (a != 0) y |= a; else y &= ~a; Этот код вообще не к чему... задача установить только тот бит что надо... а с данным примером будут установлены и другие биты которые человеку не нужны ... пример ( переменные скажем 8битные, номер бита с 0 как понимаю ):
Выполняем твой код:
после выполнения 'a' будет 0b10011000 далее твоё условие в if будет true .... так как дейсвительно оно не равно нуля.... хотя и второй бит равен нулю!!!! соотвенно дальше мы установим биты из переменной 'a' в переменую y. То есть мало того что в условии ошибка... так ещё мы и установили лишние биты.... Что же нехватает в коде ? А нехватает маски что отсечет лишние биты.... Например так :
|
|
Создано: 27 апреля 2008 23:07 · Личное сообщение · #8 |
|
Создано: 28 апреля 2008 00:09 · Личное сообщение · #9 egorovshura пишет: Оптимизация эта была связана с моджификацией кода процедуры. Может и тут получится, если константу в битовой команде модифицировать на лету. Трудно сказать, я не настолько знаю Си, да ещё вариант для микроконтроллеров, что бы провернуть такое. Подозреваю, что с асм вставками можно провернуть всё компактно, если знать как и преодолеть проблемы с регистрами и константами. tomac пишет: y=(y&~(1<<n))|(((x>>d)&1)<<n); Тоже 7 битовых операции, но нету условия Хороший примерчик. Без условия мне больше нравится. Жалко, что код не изменился ни на байт. Размер остался тот же как ни странно. У меня это всё записано в #define и что интересно компилятор мой вариант в зависимости от передаваемых параметров превращает в ассемблерный код от двух строчек, до десятка с несколькими подпрограммами ! Нужно будет спросить на каком нибудь форуме у программеров микроконтроллеров. Они должны знать особенности этого ассемблера и его совмещения с Си, и думаю какие нибудь фишки там есть. Вариант с логикой наверное уже более оптимизировать некуда ?... |
|
Создано: 28 апреля 2008 09:17 · Личное сообщение · #10 Зачастую компактная запись и последующая генерация кода мягко говоря не особо связаны.... мало того что надо хранить где то промежуточный вариант так ещё и операций то меньше не стало.... надо смотреть что генерирует компилятор в данных случаях.... /* что интересно компилятор мой вариант в зависимости от передаваемых параметров превращает в ассемблерный код от двух строчек, до десятка с несколькими подпрограммами ! */ Если касаемо именно этого варианта y=(y&~(1<<n))|(((x>>d)&1)<<n); то скорее всего ты в макрос передавал не 8битные переменные... а так как нативно микроконтроллер твой скорее всего (мега или тини небось ? ) 8битный то и переменные большего размера он уже нативно не может поддерживать поэтому может быть и сдвиги и прочие операции над такими переменными он делает через соответствующие подпрограммы.... всё от компилятора конечно зависит и от уровня оптимизации в настройках....
Темболее зачем за такой оптимизацией дикой гнаться ? Ты не успеваешь что то сделать ? |
|
Создано: 28 апреля 2008 14:40 · Личное сообщение · #11 Fallout пишет: скорее всего ты в макрос передавал не 8битные переменные... а так как нативно микроконтроллер твой (мега или тини небось ? ) Ну в конфиге проекта указывал именно что бы 8-ми битные были. Контроллер мега8515. Тем более зачем за такой оптимизацией дикой гнаться ? Ты не успеваешь что то сделать ? Я и сам себе задаю этот вопрос. В общем то успеваю, да и запас есть по кварцу. Впаял 8Mhz, а контроллер на 16 может работать. Вот и оптимизация скорости в два раза. Просто режут глаз конструкции: ...
...и таких много. |
|
Создано: 28 апреля 2008 18:22 · Личное сообщение · #12 |
|
Создано: 28 апреля 2008 19:25 · Личное сообщение · #13 ToBad, стой секунду, ты биты читаешь из memory-mapped регистра какого-то устройства? Если да, то ты бы спросил про "красивый С код" а не оптимизацию. Это делается проще через struct и bit fields:
потом просто объявляешь глобальный volatile указатель этого типа, и пользуешься полями - компилер выплюнет код для выделения конкретного бита. Тебе только надо удостоверится что читаются байты, а не machine word, то есть компилер знает что эти адреса лежат в области с byte достопом (это не RAM). |
|
Создано: 28 апреля 2008 21:50 · Личное сообщение · #14 s0larian пишет: ты биты читаешь из memory-mapped регистра какого-то устройства У него 8битный микроконтроллер ( риск процессор + рам + ром на борту ) фирмы Атмел... там грубо говоря РАМ и представляет из себя кучу регистров общего назначения... тока определенная область их являются регистрами специального назначения такие как регистры портов ввода вывода и тд... Битовые поля как вариант только не всегда компилятор генерит оптимальный код для таких дел Я бы сказал почти никогда... Но интересно To Bad скажешь потом скока получилось по коду ? п.с: вообще заметил тема МК тут появляться уже не раз что радует |
|
Создано: 28 апреля 2008 22:31 · Личное сообщение · #15 |
|
Создано: 29 апреля 2008 09:09 · Личное сообщение · #16 Биты в регистрах.... Тут проблем не будет можно присвоить адрес регистра структуре... но это две доп. переменные... + как он к полям структуры будет обращаться если у него номер бита что надо читать в переменной.... была бы константа можно было бы макрос сделать.... а тут switch/if-else городить п.с: компилятор поддерживает кстати бит ассес к ИО портам... ( см. док 3.13.1 )
Так что вот как вариант... только мало поможет если опять таки номер пина не константа.... ещё поддерживается тип данных bit вот тут можно тоже поэксперементировать
|
|
Создано: 29 апреля 2008 11:19 · Личное сообщение · #17 |
|
Создано: 29 апреля 2008 13:49 · Личное сообщение · #18 Fallout пишет: PORTA.0 = 1; Да, это знаю, но устанавливать нужно не бит порта, а бит в переменной. s0larian пишет: Это делается проще через struct и bit fields Вот как раз из всего Си, (а я писал, что только учу его), со структурами я ничего и не понял... Подчитаю ещё. Спасибо за наводку ! reversecode пишет: проще уже смотреть как компилятор соптимизирует на asm Да жуть что он делает. Он зависим от конкретных значений и констант. Одну из приведенных строчек он делает в две команды, на другой десяток строк и несколько подпрограмм. Я вот уперся в реализацию универсальной и оптимальной функции на Си, которая в итоге должна сделать лишь перетасовку данных с порта в соответствующие биты 2-х байтовых переменных. Если взглянуть на картину целиком, то получается всё очень просто на ассемблере если делать всё скопом: clr zl
Единственное не разобрался ещё как передавать в CodeVision ассемблерным коммандам константы объявленные в #define. Хотя при желании всё можно заменить конкретными цифрами и номерами регистров, но это будет не наглядно. Fallout пишет: п.с: вообще заметил тема МК тут появляться уже не раз что радует Да, творческие идеи рвутся наружу за пределы громоздких PC... Каждая программа хочет жить своей жизнью и не зависеть от Билла... |
|
Создано: 29 апреля 2008 20:19 · Личное сообщение · #19 ToBad, вот тебе целый пример для VC++:
|
|
Создано: 01 мая 2008 00:47 · Личное сообщение · #20 |
|
Создано: 04 мая 2008 04:37 · Личное сообщение · #21 |
|
Создано: 05 мая 2008 16:30 · Личное сообщение · #22 Возможно, есть смысл присомтреться к одной особенности ассемблера. Чисто редположение... В масме например не прокатывает инструкция типа shr eax, edx или eax, dl, потому как типа надо константу указывать Зато прокатывает shr eax, cl Может быть, и в том асме есть подобные особенности... ----- Я медленно снимаю с неё UPX... *FF_User* |
eXeL@B —› Программирование —› Помогите оптимизировать манипуляцию с битами на Си |