Nick_Shl 0 17 апреля, 2008 Опубликовано 17 апреля, 2008 · Жалоба Вобщем проблемка такая: есть код отрисовки линии. Он должен работать так: А получается так: Опытным путем было выяснено, что если в объявлении переменных добавить в начале три не используемых - всё работает. Бегло глянув на asm'овский код стало понятно - эти три переменные ложатся в регистры. Поскольку я AVR'овского asm'а совсем не знаю, решил спросить: кто виноват? Неправильно генерящий код CodeVision или не проавильно эмулирующий Proteus? Работающий код: ;>>> 2661 //****************************************************************************** ;>>> 2662 //*** Вывод линии ********************************************************** ;>>> 2663 //****************************************************************************** ;>>> 2664 void GRAPH_Line(char x1, char y1, char x2, char y2, char mode) ;>>> 2665 { _GRAPH_Line: ;>>> 2666 int a,b,c, dx, dy, fraction, stepx, stepy; ;>>> 2667 ;>>> 2668 // Вычисляем dx ;>>> 2669 dx = x2 - x1; SBIW R28,10 CALL __SAVELOCR6 ; x1 -> Y+20 ; y1 -> Y+19 ; x2 -> Y+18 ; y2 -> Y+17 ; mode -> Y+16 ; a -> R16,R17 ; b -> R18,R19 ; c -> R20,R21 ; dx -> Y+14 ; dy -> Y+12 ; fraction -> Y+10 ; stepx -> Y+8 ; stepy -> Y+6 LDD R26,Y+20 LDD R30,Y+18 SUB R30,R26 LDI R31,0 SBRC R30,7 SER R31 STD Y+14,R30 STD Y+14+1,R31 ;>>> 2670 // Вычисляем dx ;>>> 2671 dy = y2 - y1; LDD R26,Y+19 LDD R30,Y+17 SUB R30,R26 LDI R31,0 SBRC R30,7 SER R31 STD Y+12,R30 STD Y+12+1,R31 ;>>> 2672 ;>>> 2673 if(dx < 0) LDD R26,Y+14 LDD R27,Y+14+1 SBIW R26,0 BRGE _0x2C7 ;>>> 2674 { ;>>> 2675 dx = -dx; LDD R30,Y+14 LDD R31,Y+14+1 CALL __ANEGW1 STD Y+14,R30 STD Y+14+1,R31 ;>>> 2676 stepx = -1; LDI R30,LOW(65535) LDI R31,HIGH(65535) RJMP _0x4F5 ;>>> 2677 } ;>>> 2678 else stepx = 1; _0x2C7: LDI R30,LOW(1) LDI R31,HIGH(1) _0x4F5: STD Y+8,R30 STD Y+8+1,R31 ;>>> 2679 ;>>> 2680 if(dy < 0) LDD R26,Y+12 LDD R27,Y+12+1 SBIW R26,0 BRGE _0x2C9 ;>>> 2681 { ;>>> 2682 dy = -dy; LDD R30,Y+12 LDD R31,Y+12+1 CALL __ANEGW1 STD Y+12,R30 STD Y+12+1,R31 ;>>> 2683 stepy = -1; LDI R30,LOW(65535) LDI R31,HIGH(65535) RJMP _0x4F6 ;>>> 2684 } ;>>> 2685 else stepy = 1; _0x2C9: LDI R30,LOW(1) LDI R31,HIGH(1) _0x4F6: STD Y+6,R30 STD Y+6+1,R31 ;>>> 2686 ;>>> 2687 dx <<= 1; LDD R30,Y+14 LDD R31,Y+14+1 LSL R30 ROL R31 STD Y+14,R30 STD Y+14+1,R31 ;>>> 2688 dy <<= 1; LDD R30,Y+12 LDD R31,Y+12+1 LSL R30 ROL R31 STD Y+12,R30 STD Y+12+1,R31 ;>>> 2689 GRAPH_PutPixel(x1, y1, mode); LDD R30,Y+20 ST -Y,R30 LDD R30,Y+20 ST -Y,R30 LDD R30,Y+18 ST -Y,R30 CALL _GRAPH_PutPixel ;>>> 2690 if(dx > dy) LDD R30,Y+12 LDD R31,Y+12+1 LDD R26,Y+14 LDD R27,Y+14+1 CP R30,R26 CPC R31,R27 BRGE _0x2CB ;>>> 2691 { ;>>> 2692 fraction = dy - (dx >> 1); LDD R30,Y+14 LDD R31,Y+14+1 ASR R31 ROR R30 LDD R26,Y+12 LDD R27,Y+12+1 SUB R26,R30 SBC R27,R31 STD Y+10,R26 STD Y+10+1,R27 ;>>> 2693 while(x1 != x2) _0x2CC: LDD R30,Y+18 LDD R26,Y+20 CP R30,R26 BREQ _0x2CE ;>>> 2694 { ;>>> 2695 if((fraction > 0) || (fraction == 0)) // FIX ME: Need use >=, but this make error LDD R26,Y+10 LDD R27,Y+10+1 CALL __CPW02 BRLT _0x2D0 CALL __CPW02 BRNE _0x2CF _0x2D0: ;>>> 2696 { ;>>> 2697 y1 += stepy; LDD R30,Y+6 LDD R31,Y+6+1 LDD R26,Y+19 ADD R30,R26 STD Y+19,R30 ;>>> 2698 fraction -= dx; LDD R26,Y+14 LDD R27,Y+14+1 LDD R30,Y+10 LDD R31,Y+10+1 SUB R30,R26 SBC R31,R27 STD Y+10,R30 STD Y+10+1,R31 ;>>> 2699 } ;>>> 2700 x1 += stepx; _0x2CF: LDD R30,Y+8 LDD R31,Y+8+1 LDD R26,Y+20 ADD R30,R26 STD Y+20,R30 ;>>> 2701 fraction += dy; LDD R30,Y+12 LDD R31,Y+12+1 LDD R26,Y+10 LDD R27,Y+10+1 ADD R30,R26 ADC R31,R27 STD Y+10,R30 STD Y+10+1,R31 ;>>> 2702 GRAPH_PutPixel(x1, y1, mode); LDD R30,Y+20 ST -Y,R30 LDD R30,Y+20 ST -Y,R30 LDD R30,Y+18 ST -Y,R30 CALL _GRAPH_PutPixel ;>>> 2703 } RJMP _0x2CC _0x2CE: ;>>> 2704 } ;>>> 2705 else RJMP _0x2D2 _0x2CB: ;>>> 2706 { ;>>> 2707 fraction = dx - (dy >> 1); LDD R30,Y+12 LDD R31,Y+12+1 ASR R31 ROR R30 LDD R26,Y+14 LDD R27,Y+14+1 SUB R26,R30 SBC R27,R31 STD Y+10,R26 STD Y+10+1,R27 ;>>> 2708 while(y1 != y2) _0x2D3: LDD R30,Y+17 LDD R26,Y+19 CP R30,R26 BREQ _0x2D5 ;>>> 2709 { ;>>> 2710 if((fraction > 0) || (fraction == 0)) // FIX ME: Need use >=, but this make error LDD R26,Y+10 LDD R27,Y+10+1 CALL __CPW02 BRLT _0x2D7 CALL __CPW02 BRNE _0x2D6 _0x2D7: ;>>> 2711 { ;>>> 2712 x1 += stepx; LDD R30,Y+8 LDD R31,Y+8+1 LDD R26,Y+20 ADD R30,R26 STD Y+20,R30 ;>>> 2713 fraction -= dy; LDD R26,Y+12 LDD R27,Y+12+1 LDD R30,Y+10 LDD R31,Y+10+1 SUB R30,R26 SBC R31,R27 STD Y+10,R30 STD Y+10+1,R31 ;>>> 2714 } ;>>> 2715 y1 += stepy; _0x2D6: LDD R30,Y+6 LDD R31,Y+6+1 LDD R26,Y+19 ADD R30,R26 STD Y+19,R30 ;>>> 2716 fraction += dx; LDD R30,Y+14 LDD R31,Y+14+1 LDD R26,Y+10 LDD R27,Y+10+1 ADD R30,R26 ADC R31,R27 STD Y+10,R30 STD Y+10+1,R31 ;>>> 2717 GRAPH_PutPixel(x1, y1, mode); LDD R30,Y+20 ST -Y,R30 LDD R30,Y+20 ST -Y,R30 LDD R30,Y+18 ST -Y,R30 CALL _GRAPH_PutPixel ;>>> 2718 } RJMP _0x2D3 _0x2D5: ;>>> 2719 } _0x2D2: ;>>> 2720 } CALL __LOADLOCR6 ADIW R28,21 RET Не работающий код: ;>>> 2661 //****************************************************************************** ;>>> 2662 //*** Вывод линии ********************************************************** ;>>> 2663 //****************************************************************************** ;>>> 2664 void GRAPH_Line(char x1, char y1, char x2, char y2, char mode) ;>>> 2665 { _GRAPH_Line: ;>>> 2666 int dx, dy, fraction, stepx, stepy; ;>>> 2667 ;>>> 2668 // Вычисляем dx ;>>> 2669 dx = x2 - x1; SBIW R28,4 CALL __SAVELOCR6 ; x1 -> Y+14 ; y1 -> Y+13 ; x2 -> Y+12 ; y2 -> Y+11 ; mode -> Y+10 ; dx -> R16,R17 ; dy -> R18,R19 ; fraction -> R20,R21 ; stepx -> Y+8 ; stepy -> Y+6 LDD R26,Y+14 LDD R30,Y+12 SUB R30,R26 LDI R31,0 SBRC R30,7 SER R31 MOVW R16,R30 ;>>> 2670 // Вычисляем dx ;>>> 2671 dy = y2 - y1; LDD R26,Y+13 LDD R30,Y+11 SUB R30,R26 LDI R31,0 SBRC R30,7 SER R31 MOVW R18,R30 ;>>> 2672 ;>>> 2673 if(dx < 0) SUBI R16,0 SBCI R17,0 BRGE _0x2C7 ;>>> 2674 { ;>>> 2675 dx = -dx; MOVW R30,R16 CALL __ANEGW1 MOVW R16,R30 ;>>> 2676 stepx = -1; LDI R30,LOW(65535) LDI R31,HIGH(65535) RJMP _0x4F5 ;>>> 2677 } ;>>> 2678 else stepx = 1; _0x2C7: LDI R30,LOW(1) LDI R31,HIGH(1) _0x4F5: STD Y+8,R30 STD Y+8+1,R31 ;>>> 2679 ;>>> 2680 if(dy < 0) SUBI R18,0 SBCI R19,0 BRGE _0x2C9 ;>>> 2681 { ;>>> 2682 dy = -dy; MOVW R30,R18 CALL __ANEGW1 MOVW R18,R30 ;>>> 2683 stepy = -1; LDI R30,LOW(65535) LDI R31,HIGH(65535) RJMP _0x4F6 ;>>> 2684 } ;>>> 2685 else stepy = 1; _0x2C9: LDI R30,LOW(1) LDI R31,HIGH(1) _0x4F6: STD Y+6,R30 STD Y+6+1,R31 ;>>> 2686 ;>>> 2687 dx <<= 1; LSL R16 ROL R17 ;>>> 2688 dy <<= 1; LSL R18 ROL R19 ;>>> 2689 GRAPH_PutPixel(x1, y1, mode); LDD R30,Y+14 ST -Y,R30 LDD R30,Y+14 ST -Y,R30 LDD R30,Y+12 ST -Y,R30 CALL _GRAPH_PutPixel ;>>> 2690 if(dx > dy) __CPWRR 18,19,16,17 BRGE _0x2CB ;>>> 2691 { ;>>> 2692 fraction = dy - (dx >> 1); MOVW R30,R16 ASR R31 ROR R30 MOVW R26,R30 MOVW R30,R18 SUB R30,R26 SBC R31,R27 MOVW R20,R30 ;>>> 2693 while(x1 != x2) _0x2CC: LDD R30,Y+12 LDD R26,Y+14 CP R30,R26 BREQ _0x2CE ;>>> 2694 { ;>>> 2695 if((fraction > 0) || (fraction == 0)) // FIX ME: Need use >=, but this make error CLR R0 CP R0,R20 CPC R0,R21 BRLT _0x2D0 CLR R0 CP R0,R20 CPC R0,R21 BRNE _0x2CF _0x2D0: ;>>> 2696 { ;>>> 2697 y1 += stepy; LDD R30,Y+6 LDD R31,Y+6+1 LDD R26,Y+13 ADD R30,R26 STD Y+13,R30 ;>>> 2698 fraction -= dx; __SUBWRR 20,21,16,17 ;>>> 2699 } ;>>> 2700 x1 += stepx; _0x2CF: LDD R30,Y+8 LDD R31,Y+8+1 LDD R26,Y+14 ADD R30,R26 STD Y+14,R30 ;>>> 2701 fraction += dy; __ADDWRR 20,21,18,19 ;>>> 2702 GRAPH_PutPixel(x1, y1, mode); ST -Y,R30 LDD R30,Y+14 ST -Y,R30 LDD R30,Y+12 ST -Y,R30 CALL _GRAPH_PutPixel ;>>> 2703 } RJMP _0x2CC _0x2CE: ;>>> 2704 } ;>>> 2705 else RJMP _0x2D2 _0x2CB: ;>>> 2706 { ;>>> 2707 fraction = dx - (dy >> 1); MOVW R30,R18 ASR R31 ROR R30 MOVW R26,R30 MOVW R30,R16 SUB R30,R26 SBC R31,R27 MOVW R20,R30 ;>>> 2708 while(y1 != y2) _0x2D3: LDD R30,Y+11 LDD R26,Y+13 CP R30,R26 BREQ _0x2D5 ;>>> 2709 { ;>>> 2710 if((fraction > 0) || (fraction == 0)) // FIX ME: Need use >=, but this make error CLR R0 CP R0,R20 CPC R0,R21 BRLT _0x2D7 CLR R0 CP R0,R20 CPC R0,R21 BRNE _0x2D6 _0x2D7: ;>>> 2711 { ;>>> 2712 x1 += stepx; LDD R30,Y+8 LDD R31,Y+8+1 LDD R26,Y+14 ADD R30,R26 STD Y+14,R30 ;>>> 2713 fraction -= dy; __SUBWRR 20,21,18,19 ;>>> 2714 } ;>>> 2715 y1 += stepy; _0x2D6: LDD R30,Y+6 LDD R31,Y+6+1 LDD R26,Y+13 ADD R30,R26 STD Y+13,R30 ;>>> 2716 fraction += dx; __ADDWRR 20,21,16,17 ;>>> 2717 GRAPH_PutPixel(x1, y1, mode); LDD R30,Y+14 ST -Y,R30 LDD R30,Y+14 ST -Y,R30 LDD R30,Y+12 ST -Y,R30 CALL _GRAPH_PutPixel ;>>> 2718 } RJMP _0x2D3 _0x2D5: ;>>> 2719 } _0x2D2: ;>>> 2720 } CALL __LOADLOCR6 ADIW R28,15 RET Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GDI 0 18 апреля, 2008 Опубликовано 18 апреля, 2008 · Жалоба Дело скорее всего в том, что эти регистры еще гдето используются, например в прерывании и переменные из прерывания затирают переменные из вашей функции, это можно проверить при пошаговом выполнении программы, например, в AVR Studio. Путей решения, на вскидку, видно 2: 1 путь сделать сохранение регистров в подпрограмме прерывания, что можно сделать при помощи ассемблерных вставок (ранние версии CV это делали сами, если прерывания создавались проджект визардом), 2й путь - это обьявление локальных переменных dx и dy с префиксом static, или, как еще вариант, сделать их глобальными. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Nick_Shl 0 18 апреля, 2008 Опубликовано 18 апреля, 2008 · Жалоба 1 путь сделать сохранение регистров в подпрограмме прерывания, что можно сделать при помощи ассемблерных вставок (ранние версии CV это делали сами, если прерывания создавались проджект визардом), 2й путь - это обьявление локальных переменных dx и dy с префиксом static, или, как еще вариант, сделать их глобальными.Попробовал ставить cli и sei - не помогло. Попробовал вместо GRAPH_PutPixel() поставить код - не помогло. static конечно хорошо, но не хочется гадать, что и где упадет в следующий раз. Хочется знать наверняка в чем дело... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GDI 0 18 апреля, 2008 Опубликовано 18 апреля, 2008 · Жалоба cli и sei да, но может и сама функция напортачить, например в цикле, если есть таковой, в общем затирание регистровых переменных встречается, я такое на ИАРе встречал, static вам поможет гарантированно разместить переменную в СРАМ, а не в регистре. А понять что у вас затирает переменные поможет только дебаггер и пошаговая отладка. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Nick_Shl 0 18 апреля, 2008 Опубликовано 18 апреля, 2008 (изменено) · Жалоба cli и sei да, но может и сама функция напортачить, например в цикле, если есть таковой, в общем затирание регистровых переменных встречается, я такое на ИАРе встречал, static вам поможет гарантированно разместить переменную в СРАМ, а не в регистре. А понять что у вас затирает переменные поможет только дебаггер и пошаговая отладка.В том-то и дело, что ничего их не затирает. Проблема в сравнении. А именно if(dx < 0). Стоило написать if(x1 > x2) (для y аналогично) и все заработало. Значит дело в сравнении. И соответственно if(dx < 0) не эквивалентно: SUBI R16,0 SBCI R17,0 BRGE _0x2C7 Знатоки ассемблера, подскажите, код правильный? Или нет? И что значит "Rd ← Rd - K - C"? K в данном случае равно 0, а что такое С и чему оно будет равно? Конечно вычитание может и оптимально, но лучше бы использовались специально предназначенные для этого CP и CPC... В случае же если переменная не регистровая сравнение происходит так: LDD R26,Y+14 LDD R27,Y+14+1 SBIW R26,0 BRGE _0x2C7 Таже самая проблема и с fraction. Если написать if(fraction >= 0), код получается таким: SUBI R20,0 SBCI R21,0 BRLT _0x2CF и ничего не работает... А если написать if((fraction > 0) || (fraction == 0)) то таким: CLR R0 CP R0,R20 CPC R0,R21 BRLT _0x2D7 CLR R0 CP R0,R20 CPC R0,R21 BRNE _0x2D6 и все ок... Изменено 18 апреля, 2008 пользователем Nick_Shl Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vet 0 19 апреля, 2008 Опубликовано 19 апреля, 2008 · Жалоба Протеус чудит, вероятно. Отлаживайтесь лучше на железе. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
tazik 0 20 апреля, 2008 Опубликовано 20 апреля, 2008 · Жалоба Nick_Shl, а Вы не могли бы выложить: 1) файлик Протеуса *.dsn 2) Работающий код *.с 3) Неработающий код *.с Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Obama 0 20 апреля, 2008 Опубликовано 20 апреля, 2008 · Жалоба я AVR'овского asm'а совсем не знаю, решил спросить: кто виноват? Неправильно генерящий код CodeVision или не проавильно эмулирующий Proteus? Прицепи архив с проектом CVAVR и PROTEUS. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Nick_Shl 0 21 апреля, 2008 Опубликовано 21 апреля, 2008 · Жалоба Вот демонстрация этого глючка... Версия Proteus 7.2SP2, "бесплатная"... Error.zip Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться