задача была помигать светодиодами, если вы считаете что в данной ситуации несколько тиков процессора важнее универсальности, то
vitalik_1984 писал(а):
просто вспоминается мысль о говнокоде
можете считать меня говнокодером, генерирующим абстрактный код и не имеющим возможности его проверить в работе
ЗЫ. для справки - задачи бывают разные, в одной важен размер кода, в другой скорость, так что делать выводы о том использовать свитч или отдельные функции, можно только ознакомившись с конкретным ТЗ
_________________ Коктейль "Рекурсивный": 20% спирта, 30% воды, 50% коктейля "Рекурсивный"...
Ога, и еще писать переносимый код, хаить CV и восхвалять ассемблер. Вроде ничего не забыл из основных тем форума?! А по делу, желания нет гадать в чем проблема, смотря на одну строчку кода.
Да хоть листинг, хоть строчку..... как я понял компилятор (пользуюсь AVRStudio4) в подобных случаях чего то не понимает..... толи нескольких указателей в сравнении, толи префиксы ++/-- к указателям, толи еще чего..... Вот простенький пример (свой код не стал показывать, т.к. сложнее разобраться будет)
Код:
#include <avr/io.h> char massiv [10];
int main (void) { char* pMassiv = massiv; for (char i=0; i<10; i++) *pMassiv++= i;
if (*(--pMassiv)==*(--pMassiv)) PORTB = 0xff; else PORTB = 0x00;
while (1){} }
Сравниваем последние 2 элемента массива, и хотя там у нас разные данные, компиль просто (молча) вырезает сравнение, и выполняет действие PORTB = 0xff, как будто у нас положительный результат сравнения.....
Код:
6:{ +00000024: E6E0 LDI R30,0x60 Load immediate +00000025: E0F0 LDI R31,0x00 Load immediate +00000026: E080 LDI R24,0x00 Load immediate 10:*pMassiv++= i; +00000027: 9381 ST Z+,R24 Store indirect and postincrement 9: for (char i=0; i<10; i++) +00000028: 5F8F SUBI R24,0xFF Subtract immediate +00000029: 308A CPI R24,0x0A Compare with immediate +0000002A: F7E1 BRNE PC-0x03 Branch if not equal 13: PORTB = 0xff; +0000002B: EF8F SER R24 Set Register +0000002C: BB88 OUT 0x18,R24 Out to I/O location +0000002D: CFFF RJMP PC-0x0000 Relative jump 13: PORTB = 0xff; +0000002E: 94F8 CLI Global Interrupt Disable +0000002F: CFFF RJMP PC-0x0000 Relative jump
А вот так, работает..... Но уперто не хочет применять индексный регистр, хотя казалось бы - адрес в нем уже имеется..... так нет же тратит лишний флэш на загрузку обоих байтов командой LDS.....
Код:
#include <avr/io.h> char massiv [10];
int main (void) { char* pMassiv = massiv; for (char i=0; i<10; i++) *pMassiv++= i;
в общем, поскольку в условии if используется одна переменная (указатель) и в составе условия есть математические операции пред/пост декремента/инкремента, то они выполняются до проверки условия. т.е в случае
Код:
if (*pIrNecData ==*(--pIrNecData)) {.....}
сначала происходит преддекремент pIrNecData, а потом уже сравнение двух выражений *(pIrNecData), которые равны. Аналогично во всех остальных случаях.
объявить дополнительную переменную как volatile и часть преобразований вести через неё...
Тока можно и без volatile.
ЗЫ Просто у программиста логика - человеческая, а у компа - машинная.....
ЗЫЗЫ В общем вывод: нельзя в сравнении использовать один указатель больше одного раза..... правильный вывод?
ЗЫЗЫЗЫ Интересно, а почему тогда компилятор ни гугу.... хотябы ругнулся на лишний (недостающий) префикс. Ведь с человеческой точки зрения, все должно произойти именно так как я изначально ожидал..... Наверное упущение программеров создавших компилятор. Надо еще в 6-ке проверить, как себя вести будет такое построение.....
char massiv [10]; volatile char *pMassiv = massiv; int main (void) { for (char i=0; i<10; i++) *pMassiv++ = i; if (*(--pMassiv) == *(--pMassiv)) PORTB = 0xff; else PORTB = 0x00;
while (1){}
Дизассемблер
Код:
{ for (char i=0; i<10; i++) 00000024 LDI R24,0x00 Load immediate *pMassiv++ = i; 00000025 LDS R30,0x0060 Load direct from data space 00000027 LDS R31,0x0061 Load direct from data space 00000029 MOVW R26,R30 Copy register pair 0000002A ST X+,R24 Store indirect and postincrement 0000002B STS 0x0061,R27 Store direct to data space 0000002D STS 0x0060,R26 Store direct to data space for (char i=0; i<10; i++) 0000002F SUBI R24,0xFF Subtract immediate 00000030 CPI R24,0x0A Compare with immediate 00000031 BRNE PC-0x0C Branch if not equal if (*(--pMassiv) == *(--pMassiv)) 00000032 STS 0x0061,R31 Store direct to data space 00000034 STS 0x0060,R30 Store direct to data space 00000036 LDD R25,Z+0 Load indirect with displacement 00000037 SBIW R30,0x01 Subtract immediate from word 00000038 STS 0x0061,R31 Store direct to data space 0000003A STS 0x0060,R30 Store direct to data space 0000003C LDD R24,Z+0 Load indirect with displacement 0000003D CP R25,R24 Compare 0000003E BRNE PC+0x04 Branch if not equal PORTB = 0xff; 0000003F SER R24 Set Register 00000040 OUT 0x18,R24 Out to I/O location 00000041 RJMP PC+0x0002 Relative jump PORTB = 0x00; 00000042 OUT 0x18,R1 Out to I/O location 00000043 RJMP PC-0x0000 Relative jump
бред! зачем объявлять указатель на массив volatile? он что, у Вас в прерывании меняется? естественно volatile будет работать в этом случае, поскольку при каждом обращении к указателю будет производиться его преддекремент. Но это равносильно отключению оптимизации этого указателя. Так делать нельзя.
Карма: 90
Рейтинг сообщений: 1443
Зарегистрирован: Чт мар 18, 2010 23:09:57 Сообщений: 4613 Откуда: Планета Земля
Рейтинг сообщения:0 Медали: 1
Цитата:
Так делать нельзя.
Ну почему же нельзя. volatile как раз и нужен для того, что бы сказать компилятору, что он "не прав" и не должен оптимизировать мысли программиста. По поводу инкремента. В строке используется же пред-, а не пост-инкремент. Если бы был постинкремент, то оптимизатор можно было бы понять, т.к. условие будет всегда = true. Вообще не понятно, почему он обрезает эту строку, хотя бы инкремент оставил бы.
По поводу инкремента. В строке используется же пред-, а не пост-инкремент. Если бы был постинкремент, то оптимизатор можно было бы понять, т.к. условие будет всегда = true. Вообще не понятно, почему он обрезает эту строку, хотя бы инкремент оставил бы.
Компилятор это делает потому, что дальше эта переменная нигде не используется. Поставьте вывод её значения в какой-либо порт и компилятор сделает инкремент.
Думаю, что многие будут удивлены результатами этих строк (например для a=5). x = (++a) + (++a); x = (a++) + (a++); Однако всё строго по стандарту.
_________________ Когда уже ничего не помогает - прочтите, наконец, инструкцию. Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII) Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения