Summary: | Не правильная трансляция оператора if | ||
---|---|---|---|
Product: | Sisyphus | Reporter: | Dmitry A. Kharitonov <kharpost> |
Component: | avr-gcc | Assignee: | Grigory Milev <week> |
Status: | CLOSED FIXED | QA Contact: | qa-sisyphus |
Severity: | blocker | ||
Priority: | P3 | CC: | erthad, iv, kharpost, lex, vip0, viy, week |
Version: | unstable | ||
Hardware: | all | ||
OS: | Linux |
Description
Dmitry A. Kharitonov
2010-02-03 19:55:09 MSK
А для двухбайтовых чисел эта же проблема присутствует? (В ответ на комментарий №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; (В ответ на комментарий №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 |