Перейти к содержанию
    

Глюки с CodeVision, Proteus и AVR...

Вобщем проблемка такая: есть код отрисовки линии. Он должен работать так:

Line_W.png

А получается так:

Line_NW.png

Опытным путем было выяснено, что если в объявлении переменных добавить в начале три не используемых - всё работает. Бегло глянув на 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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Дело скорее всего в том, что эти регистры еще гдето используются, например в прерывании и переменные из прерывания затирают переменные из вашей функции, это можно проверить при пошаговом выполнении программы, например, в AVR Studio. Путей решения, на вскидку, видно 2: 1 путь сделать сохранение регистров в подпрограмме прерывания, что можно сделать при помощи ассемблерных вставок (ранние версии CV это делали сами, если прерывания создавались проджект визардом), 2й путь - это обьявление локальных переменных dx и dy с префиксом static, или, как еще вариант, сделать их глобальными.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 путь сделать сохранение регистров в подпрограмме прерывания, что можно сделать при помощи ассемблерных вставок (ранние версии CV это делали сами, если прерывания создавались проджект визардом), 2й путь - это обьявление локальных переменных dx и dy с префиксом static, или, как еще вариант, сделать их глобальными.
Попробовал ставить cli и sei - не помогло. Попробовал вместо GRAPH_PutPixel() поставить код - не помогло.

static конечно хорошо, но не хочется гадать, что и где упадет в следующий раз. Хочется знать наверняка в чем дело...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

cli и sei да, но может и сама функция напортачить, например в цикле, если есть таковой, в общем затирание регистровых переменных встречается, я такое на ИАРе встречал, static вам поможет гарантированно разместить переменную в СРАМ, а не в регистре. А понять что у вас затирает переменные поможет только дебаггер и пошаговая отладка.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

и все ок...

Изменено пользователем Nick_Shl

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Nick_Shl, а Вы не могли бы выложить: 1) файлик Протеуса *.dsn 2) Работающий код *.с 3) Неработающий код *.с

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

я AVR'овского asm'а совсем не знаю, решил спросить: кто виноват? Неправильно генерящий код CodeVision или не проавильно эмулирующий Proteus?

 

Прицепи архив с проектом CVAVR и PROTEUS.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...