Hallo, ich teste gerade die Codequalität der Demoversion von Imagecraft C v6.29. Hier ein Resultat: /////////////////////////////////// // PORTB bit constants #define LED_GREEN 4 #define LED_YELLOW 5 #define LED_RED 6 #pragma interrupt_handler uart0_rx_isr:iv_UART_RX void uart0_rx_isr(void) { char data = UDR; switch(data) { case LED_GREEN_ON: PORTD &= ~BIT(LED_GREEN); break; case LED_GREEN_OFF: PORTD |= BIT(LED_GREEN); break; case LED_YELLOW_ON: PORTD &= ~BIT(LED_YELLOW); break; case LED_YELLOW_OFF: PORTD |= BIT(LED_YELLOW); break; case LED_RED_ON: PORTD &= ~BIT(LED_RED); break; case LED_RED_OFF: PORTD |= BIT(LED_RED); break; } if(data == LED_GREEN_ON) PORTD &= ~BIT(LED_GREEN); } /////////////////////////////////// *00000043:uart0_rx_isr +00000043: 930A ST -Y,R16 +00000044: 932A ST -Y,R18 +00000045: 933A ST -Y,R19 +00000046: 93EA ST -Y,R30 +00000047: B70F IN R16,0x3F +00000048: 930A ST -Y,R16 +00000049: B10C IN R16,0xC +0000004A: 2F20 MOV R18,R16 +0000004B: 2733 CLR R19 +0000004C: 3021 CPI R18,0x01 ; 0x01 = 0b00000001 = 1 +0000004D: E0E0 LDI R30,0x00 ; 0x00 = 0b00000000 = 0 +0000004E: 073E CPC R19,R30 +0000004F: F0A9 BREQ +0x15 ; Destination: 0x000065 +00000050: 3022 CPI R18,0x02 ; 0x02 = 0b00000010 = 2 +00000051: E0E0 LDI R30,0x00 ; 0x00 = 0b00000000 = 0 +00000052: 073E CPC R19,R30 +00000053: F099 BREQ +0x13 ; Destination: 0x000067 +00000054: 3023 CPI R18,0x03 ; 0x03 = 0b00000011 = 3 +00000055: E0E0 LDI R30,0x00 ; 0x00 = 0b00000000 = 0 +00000056: 073E CPC R19,R30 +00000057: F089 BREQ +0x11 ; Destination: 0x000069 +00000058: 3024 CPI R18,0x04 ; 0x04 = 0b00000100 = 4 +00000059: E0E0 LDI R30,0x00 ; 0x00 = 0b00000000 = 0 +0000005A: 073E CPC R19,R30 +0000005B: F079 BREQ +0x0F ; Destination: 0x00006B +0000005C: 3025 CPI R18,0x05 ; 0x05 = 0b00000101 = 5 +0000005D: E0E0 LDI R30,0x00 ; 0x00 = 0b00000000 = 0 +0000005E: 073E CPC R19,R30 +0000005F: F069 BREQ +0x0D ; Destination: 0x00006D +00000060: 3026 CPI R18,0x06 ; 0x06 = 0b00000110 = 6 +00000061: E0E0 LDI R30,0x00 ; 0x00 = 0b00000000 = 0 +00000062: 073E CPC R19,R30 +00000063: F059 BREQ +0x0B ; Destination: 0x00006F +00000064: C00B RJMP +0x000B ; Destination: 0x000070 +00000065: 9894 CBI 0x12,4 +00000066: C009 RJMP +0x0009 ; Destination: 0x000070 +00000067: 9A94 SBI 0x12,4 +00000068: C007 RJMP +0x0007 ; Destination: 0x000070 +00000069: 9895 CBI 0x12,5 +0000006A: C005 RJMP +0x0005 ; Destination: 0x000070 +0000006B: 9A95 SBI 0x12,5 +0000006C: C003 RJMP +0x0003 ; Destination: 0x000070 +0000006D: 9896 CBI 0x12,6 +0000006E: C001 RJMP +0x0001 ; Destination: 0x000070 +0000006F: 9A96 SBI 0x12,6 +00000070: 3001 CPI R16,0x01 ; 0x01 = 0b00000001 = 1 +00000071: F409 BRNE +0x01 ; Destination: 0x000073 +00000072: 9894 CBI 0x12,4 +00000073: 9109 LD R16,Y+ +00000074: BF0F OUT 0x3F,R16 +00000075: 91E9 LD R30,Y+ +00000076: 9139 LD R19,Y+ +00000077: 9129 LD R18,Y+ +00000078: 9109 LD R16,Y+ +00000079: 9518 RETI /////////////////////////////////// Das Setzen/Rücksetzen der Port-Bits hat er richtig übersetzt. Aber die switch() Anweisung ?: +00000050: 3022 CPI R18,0x02 ; 0x02 = 0b00000010 = 2 +00000051: E0E0 LDI R30,0x00 ; 0x00 = 0b00000000 = 0 +00000052: 073E CPC R19,R30 +00000053: F099 BREQ +0x13 ; Destination: 0x000067 Die If Anweisung hat er auch richtig übersetzt, warum dann nicht bei der switch() Anweisung ?: +00000070: 3001 CPI R16,0x01 ; 0x01 = 0b00000001 = 1 +00000071: F409 BRNE +0x01 ; Destination: 0x000073 +00000072: 9894 CBI 0x12,4 Habt ihr ähnliche Erfahrungen ?
Ohne einen vollständigen Code kann das keiner sagen: error: `LED_GREEN_ON' undeclared (first use in this function) error: (Each undeclared identifier is reported only once error: for each function it appears in.) warning: implicit declaration of function `BIT' error: `LED_GREEN_OFF' undeclared (first use in this function) error: `LED_YELLOW_ON' undeclared (first use in this function) error: `LED_YELLOW_OFF' undeclared (first use in this function) error: `LED_RED_ON' undeclared (first use in this function) error: `LED_RED_OFF' undeclared (first use in this function) Peter
Hallo Peter, entschuldige bitte, hier sind die defines: #define LED_GREEN_ON 1 #define LED_GREEN_OFF 2 #define LED_YELLOW_ON 3 #define LED_YELLOW_OFF 4 #define LED_RED_ON 5 #define LED_RED_OFF 6
Hallo, der von AVRGCC 20030913 erzeugte Code sieht auch nicht besser aus: INTERRUPT(SIG_UART_RECV) { 76: 78 94 sei 78: 1f 92 push r1 7a: 0f 92 push r0 7c: 0f b6 in r0, 0x3f ; 63 7e: 0f 92 push r0 80: 11 24 eor r1, r1 82: 2f 93 push r18 84: 8f 93 push r24 86: 9f 93 push r25 char data = UDR; 88: 2c b1 in r18, 0x0c ; 12 switch(data) 8a: 82 2f mov r24, r18 8c: 99 27 eor r25, r25 8e: 83 30 cpi r24, 0x03 ; 3 90: 91 05 cpc r25, r1 92: b1 f0 breq .+44 ; 0xc0 94: 84 30 cpi r24, 0x04 ; 4 96: 91 05 cpc r25, r1 98: 34 f4 brge .+12 ; 0xa6 9a: 81 30 cpi r24, 0x01 ; 1 9c: 91 05 cpc r25, r1 9e: 61 f0 breq .+24 ; 0xb8 a0: 02 97 sbiw r24, 0x02 ; 2 a2: 61 f0 breq .+24 ; 0xbc a4: 15 c0 rjmp .+42 ; 0xd0 a6: 85 30 cpi r24, 0x05 ; 5 a8: 91 05 cpc r25, r1 aa: 79 f0 breq .+30 ; 0xca ac: 85 30 cpi r24, 0x05 ; 5 ae: 91 05 cpc r25, r1 b0: 4c f0 brlt .+18 ; 0xc4 b2: 06 97 sbiw r24, 0x06 ; 6 b4: 61 f0 breq .+24 ; 0xce b6: 0c c0 rjmp .+24 ; 0xd0 { case LED_GREEN_ON: PORTD &= ~_BV(LED_GREEN); b8: 94 98 cbi 0x12, 4 ; 18 break; ba: 0a c0 rjmp .+20 ; 0xd0 case LED_GREEN_OFF: PORTD |= _BV(LED_GREEN); bc: 94 9a sbi 0x12, 4 ; 18 break; be: 08 c0 rjmp .+16 ; 0xd0 case LED_YELLOW_ON: PORTD &= ~_BV(LED_YELLOW); c0: 95 98 cbi 0x12, 5 ; 18 break; c2: 06 c0 rjmp .+12 ; 0xd0 case LED_YELLOW_OFF: PORTD |= _BV(LED_YELLOW); c4: 95 9a sbi 0x12, 5 ; 18 PORTD |= 0x04; c6: 92 9a sbi 0x12, 2 ; 18 break; c8: 03 c0 rjmp .+6 ; 0xd0 case LED_RED_ON: PORTD &= ~_BV(LED_RED); ca: 96 98 cbi 0x12, 6 ; 18 break; cc: 01 c0 rjmp .+2 ; 0xd0 case LED_RED_OFF: PORTD |= _BV(LED_RED); ce: 96 9a sbi 0x12, 6 ; 18 break; } if(data == LED_GREEN_ON) d0: 21 30 cpi r18, 0x01 ; 1 d2: 09 f4 brne .+2 ; 0xd6 PORTD &= ~_BV(LED_GREEN); d4: 94 98 cbi 0x12, 4 ; 18 } d6: 9f 91 pop r25 d8: 8f 91 pop r24 da: 2f 91 pop r18 dc: 0f 90 pop r0 de: 0f be out 0x3f, r0 ; 63 e0: 0f 90 pop r0 e2: 1f 90 pop r1 e4: 18 95 reti
Gemäß dem C-Standard berechnen viele Compiler die switch()-Ausdrücke als Typ `int'. if then else könnte ggf. besseren Code erzeugen.
Ich habe Deine Quelle mit IAR übersetzt. Ich hoffe, es fehlt nichts. 45 __interrupt void uart0_rx_isr(void) 46 { \ __nearfunc __interrupt void uart0_rx_isr(); \ uart0_rx_isr: \ 00000000 932A ST -Y,R18 \ 00000002 931A ST -Y,R17 \ 00000004 930A ST -Y,R16 \ 00000006 B72F IN R18,0x3F 47 char data = UDR; \ 00000008 B10C IN R16,0x0C 48 49 switch(data) \ 0000000A 2F10 MOV R17,R16 \ 0000000C 951A DEC R17 \ 0000000E F059 BREQ ??uart0_rx_isr_0 \ 00000010 951A DEC R17 \ 00000012 F059 BREQ ??uart0_rx_isr_1 \ 00000014 951A DEC R17 \ 00000016 F059 BREQ ??uart0_rx_isr_2 \ 00000018 951A DEC R17 \ 0000001A F059 BREQ ??uart0_rx_isr_3 \ 0000001C 951A DEC R17 \ 0000001E F059 BREQ ??uart0_rx_isr_4 \ 00000020 951A DEC R17 \ 00000022 F059 BREQ ??uart0_rx_isr_5 \ 00000024 C00B RJMP ??uart0_rx_isr_6 50 { 51 case LED_GREEN_ON: 52 PORTD &= ~BIT(LED_GREEN); \ ??uart0_rx_isr_0: \ 00000026 9894 CBI 0x12,0x04 \ 00000028 C009 RJMP ??uart0_rx_isr_6 53 break; 54 case LED_GREEN_OFF: 55 PORTD |= BIT(LED_GREEN); \ ??uart0_rx_isr_1: \ 0000002A 9A94 SBI 0x12,0x04 \ 0000002C C007 RJMP ??uart0_rx_isr_6 56 break; 57 case LED_YELLOW_ON: 58 PORTD &= ~BIT(LED_YELLOW); \ ??uart0_rx_isr_2: \ 0000002E 9895 CBI 0x12,0x05 \ 00000030 C005 RJMP ??uart0_rx_isr_6 59 break; 60 case LED_YELLOW_OFF: 61 PORTD |= BIT(LED_YELLOW); \ ??uart0_rx_isr_3: \ 00000032 9A95 SBI 0x12,0x05 \ 00000034 C003 RJMP ??uart0_rx_isr_6 62 break; 63 case LED_RED_ON: 64 PORTD &= ~BIT(LED_RED); \ ??uart0_rx_isr_4: \ 00000036 9896 CBI 0x12,0x06 \ 00000038 C001 RJMP ??uart0_rx_isr_6 65 break; 66 case LED_RED_OFF: 67 PORTD |= BIT(LED_RED); \ ??uart0_rx_isr_5: \ 0000003A 9A96 SBI 0x12,0x06 68 break; 69 } 70 71 if(data == LED_GREEN_ON) \ ??uart0_rx_isr_6: \ 0000003C 3001 CPI R16,1 \ 0000003E F409 BRNE ??uart0_rx_isr_7 72 PORTD &= ~BIT(LED_GREEN); \ 00000040 9894 CBI 0x12,0x04 73 } \ ??uart0_rx_isr_7: \ 00000042 BF2F OUT 0x3F,R18 \ 00000044 9109 LD R16,Y+ \ 00000046 9119 LD R17,Y+ \ 00000048 9129 LD R18,Y+ \ 0000004A 9518 RETI
Hallo Michael, vielen Dank, daß du den Code mit IAR übersetzt hast. Das Ergebnis ist beeindruckend !
Wenn die Compiler ineffizient sind, programmiert man halt gleich in Assembler. Man kann eben nicht alles haben ;)
Hallo, ich habe nun eine ganze Datei unter den verschiedenen Compilern compiliert. Diese habe ich ein wenig optimiert (if() anstatt switch() ...). Das Ergebnis (Codegröße): WinAVR 20030913: 302 Byte Codevision Demoversion 1.23.9: 348 Byte Imagecraft Demoversion 6.29: 382 Byte @Michael Ich wäre dir dankbar, wenn du die Datei mal an IAR anpassen und compilieren könnte.
Hallo Fiffi, anbei das 'Compilatius' tastatur.lst, ohne es gelinkt zu haben. Es müßte auch nur der Stackpointer gesetzt werden, wenn ich nicht etwas übersehen habe. Optimierung auf höchste Ausführungsgeschwindigkeit '-s9'; 220 Byte sind angesagt. Wenn man schnelle Interrupts braucht, ist es vorteilhafter, dort keine Calls zu machen, da sonst viele Register gerettet werden müssen.
Beim gcc ist die Initialisierung (Memory nullsetzen etc) bereits mit drin, das fehlt beim IAR-Listing. Ohne die Initialisierung komme ich bei gcc auf 240 Bytes. Ohne die Funktionsaufrufe im IR wirds sowohl bei IAR als auch bei gcc noch ein gutes Stück weniger. Die switch-Anweisung hast Du Dir totoptimiert, jetzt werden jedesmal alle 6 ifs getestet. Nimmst Du if ... else, dann sparst Du viel Zeit zur Laufzeit. Stefan
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.