Сравниваются long и long //Nouse skiped // test for holdkey if(keybuf.keys!=keys.keys) { 20c: 20 91 fa 00 lds r18, 0x00FA 210: 30 91 fb 00 lds r19, 0x00FB 214: 40 91 fc 00 lds r20, 0x00FC 218: 50 91 fd 00 lds r21, 0x00FD 21c: 80 91 04 01 lds r24, 0x0104 220: 90 91 05 01 lds r25, 0x0105 224: a0 91 06 01 lds r26, 0x0106 228: b0 91 07 01 lds r27, 0x0107 22c: 28 17 cp r18, r24 22e: 39 07 cpc r19, r25 230: 4a 07 cpc r20, r26 232: 5b 07 cpc r21, r27 234: e1 f0 breq .+56 ; 0x26e <__stack+0xf> Здесь проверяется результат последнего (старшего байта), а результаты сравнения предыдущих байтов игнорируются Правильно так: 22c: 28 17 cp r18, r24 234: e1 f0 brne ..... 22e: 39 07 cp r19, r25 234: e1 f0 brne ..... 230: 4a 07 cp r20, r26 234: e1 f0 brne ..... 232: 5b 07 cp r21, r27 234: e1 f0 brne ..... и далее проверка на не нулевое значение // test for presskey if(keybuf.keys) { 26e: 80 91 fa 00 lds r24, 0x00FA 272: 90 91 fb 00 lds r25, 0x00FB 276: a0 91 fc 00 lds r26, 0x00FC 27a: b0 91 fd 00 lds r27, 0x00FD 27e: 00 97 sbiw r24, 0x00 ; 0 280: a1 05 cpc r26, r1 282: b1 05 cpc r27, r1 284: 79 f1 breq .+94 ; 0x2e4 <__stack+0x85> // key pressed Тоже самое проверяется равенство нулю только последнего байта Правильно так 27e: 00 97 or r24,r25 280: a1 05 or r24,r26 282: b1 05 or r24,r27 284: 79 f1 breq .+94 ; 0x2e4 <__stack+0x85> В общем, компилятор скорее мёртв, нежели жив. Ставить вопрос об удалении из репозитория -- жалко, а кроме меня наверное никто не пользуется.
А для двухбайтовых чисел эта же проблема присутствует?
(В ответ на комментарий №1) > А для двухбайтовых чисел эта же проблема присутствует? [user@localhost Documents]$ cat bugif.c #include <avr/io.h> int main(void) { volatile uint16_t a=8,b=7; a++; b++; if(a==b) a++; if(b) b++; return 0; } [user@localhost Documents]$ avr-gcc -Wall -Werror -g -Os -o bugif.elf -mint8 -I/usr/include/avr -mmcu=atmega8535 bugif.c; avr-objdump -S -h bugif.elf >bugif.S 8c: 8b 83 std Y+3, r24 ; 0x03 if(a==b) a++; 8e: 29 81 ldd r18, Y+1 ; 0x01 90: 3a 81 ldd r19, Y+2 ; 0x02 92: 8b 81 ldd r24, Y+3 ; 0x03 94: 9c 81 ldd r25, Y+4 ; 0x04 96: 28 17 cp r18, r24 98: 39 07 cpc r19, r25 9a: 29 f4 brne .+10 ; 0xa6 <main+0x44> 9c: 89 81 ldd r24, Y+1 ; 0x01 9e: 9a 81 ldd r25, Y+2 ; 0x02 a0: 01 96 adiw r24, 0x01 ; 1 a2: 9a 83 std Y+2, r25 ; 0x02 a4: 89 83 std Y+1, r24 ; 0x01 if(b) b++; a6: 8b 81 ldd r24, Y+3 ; 0x03 a8: 9c 81 ldd r25, Y+4 ; 0x04 aa: 89 2b or r24, r25 ac: 29 f0 breq .+10 ; 0xb8 <main+0x56> ae: 8b 81 ldd r24, Y+3 ; 0x03 b0: 9c 81 ldd r25, Y+4 ; 0x04 b2: 01 96 adiw r24, 0x01 ; 1 b4: 9c 83 std Y+4, r25 ; 0x04 b6: 8b 83 std Y+3, r24 ; 0x03 return 0; В общем да.
Windowая версия работает так же: if(a==b) a++; 6c: 29 81 ldd r18, Y+1 ; 0x01 6e: 3a 81 ldd r19, Y+2 ; 0x02 70: 8b 81 ldd r24, Y+3 ; 0x03 72: 9c 81 ldd r25, Y+4 ; 0x04 74: 28 17 cp r18, r24 76: 39 07 cpc r19, r25 78: 29 f4 brne .+10 ; 0x84 <__SREG__+0x45> 7a: 89 81 ldd r24, Y+1 ; 0x01 7c: 9a 81 ldd r25, Y+2 ; 0x02 7e: 01 96 adiw r24, 0x01 ; 1 80: 9a 83 std Y+2, r25 ; 0x02 82: 89 83 std Y+1, r24 ; 0x01 if(b) b++; 84: 8b 81 ldd r24, Y+3 ; 0x03 86: 9c 81 ldd r25, Y+4 ; 0x04 88: 89 2b or r24, r25 8a: 29 f0 breq .+10 ; 0x96 <__SREG__+0x57> 8c: 8b 81 ldd r24, Y+3 ; 0x03 8e: 9c 81 ldd r25, Y+4 ; 0x04 90: 01 96 adiw r24, 0x01 ; 1 92: 9c 83 std Y+4, r25 ; 0x04 94: 8b 83 std Y+3, r24 ; 0x03 return 0;
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42976
(В ответ на комментарий №0) > > Ставить вопрос об удалении из репозитория -- жалко, а кроме меня наверное никто > не пользуется. Пользуется. Ну или покрмере, хотелось бы пользоваться.
Тогда рекомендую сразу пользоваться макросами вроде этих #define isnz(a) ((uint8_t)(a)|(uint8_t)((uint16_t)(a)>>8)|(uint8_t)((uint32_t)(a)>>16)|(uint8_t)((uint32_t)(a)>>24)) #define isne(a,b) ((((uint8_t)(a))^((uint8_t)(b)))|(((uint8_t)((uint16_t)(a)>>8))^((uint8_t)((uint16_t)(b)>>8)))|(((uint8_t)((uint32_t)(a)>>16))^((uint8_t)((uint32_t)(b)>>16)))|(((uint8_t)((uint32_t)(a)>>24))^((uint8_t)((uint32_t)(b)>>24))))
ещё отловил: void getparam(uint8_t len) { 15a: 0f 93 push r16 15c: 1f 93 push r17 15e: cf 93 push r28 160: df 93 push r29 162: 08 2f mov r16, r24 164: c8 e6 ldi r28, 0x68 ; 104 166: d0 e0 ldi r29, 0x00 ; 0 168: 0b c0 rjmp .+22 ; 0x180 <getparam+0x26> uint8_t *buf=cmdbuf,tt; // len--; for(;len>0;len--) { 16a: 1a e0 ldi r17, 0x0A ; 10 int16_t t; for(tt=10;tt>0;tt--) { t=uart_getchar(); 16c: 2d d1 rcall .+602 ; 0x3c8 <uart_getchar> if(t>0) break; 16e: 18 16 cp r1, r24 170: 19 06 cpc r1, r25 172: 24 f0 brlt .+8 ; 0x17c <getparam+0x22> void getparam(uint8_t len) { uint8_t *buf=cmdbuf,tt; // len--; for(;len>0;len--) { int16_t t; for(tt=10;tt>0;tt--) { 174: 11 50 subi r17, 0x01 ; 1 176: d1 f7 brne .-12 ; 0x16c <getparam+0x12> t=uart_getchar(); if(t>0) break; } if(t<0) return; 178: 00 97 sbiw r24, 0x00 ; 0 17a: 21 f4 brne .+8 ; 0x184 <getparam+0x2a> *buf++ =t; 17c: 89 93 st Y+, r24 uint8_t cmdbuf[8]; void getparam(uint8_t len) { uint8_t *buf=cmdbuf,tt; // len--; for(;len>0;len--) { 17e: 01 50 subi r16, 0x01 ; 1 180: 00 23 and r16, r16 182: 99 f7 brne .-26 ; 0x16a <getparam+0x10> 184: df 91 pop r29 186: cf 91 pop r28 188: 1f 91 pop r17 18a: 0f 91 pop r16 18c: 08 95 ret по адресу 174-176
вру по адресу 178-17a
Что то я не вижу противоречия, вот пример кода проверки 2х байтных чисел: ; Сравнить r3 : r2 с r1 : r0 cp r2, r0 ; Сравнить старший байт cpc r3, r1 ; Сравнить младший байт brne noteq ; Перейти если не равно (взято вот тут: http://www.gaw.ru/html.cgi/txt/doc/micros/avr/asm/cpc.htm) Чем не устраивает вызов CP и вслед за ним CPC, судя по документации CPC учитывает результат выполнения предыдущей команды. Не вижу в данном коде никаких ошибок!
что будет, если r2=1 r0=2 r3=1 r1=0? Сточки зрения компилятора числа будут равны. Так, как результат последней операции (cpc) будет равен нулю. Я почти день угрохал, когда первый раз пытался понять почему программа работает не правильно. Такая конструкция возможна только при выяснении какое число больше другого без предположения о равенстве.
Честно говоря не совсем понимаю, почему на равенство не отработает: cp cpc cpc ????
видимо многие не понимают. r2=1 r0=2 r3=1 r1=0 cp r2, r0 ; r2-r0 => 1-2=-1 => 0xff : c=1 : z=0 cpc r3, r1 ; r3-r1-c => 1-0-1 => 0x00 : c=0 : z=1 brne noteq ; z==0 ? => перехода не будет
к стати, в ссылке, которую вы привели вообще невозможно понять как эта команда работает.
(In reply to comment #13) > к стати, в ссылке, которую вы привели вообще невозможно понять как эта команда > работает. cpc не трогает флаг z если результат вычетания 0. http://www.atmel.com/dyn/resources/prod_documents/doc0856.pdf страница 61