www.mikrocontroller.net

Forum: Compiler & IDEs Nach entfernen von Redundanz größer?


Autor: Manuel Kasten (draradech)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe versucht, folgenden Codeschnipsel zu vereinfachen.

Obwohl in Variante 2 die zweite while-minDigits Schleife eingespart 
wurde, ist der erzeugte Code 12 Byte größer.

OK, ist nicht viel, aber ich möchte gerne wissen, was hier geschieht.

Ich bin kein Assembler-Experte, aber die zweite Variante sieht beim 
auswerten der Ziffernanzahl (digits = ...) deutlich suboptimal aus.
Und was sollen die beiden pop r0 gegen Ende? Ich sehe kein dazugehöriges 
push...

edit: Compilerversion ist "avr-gcc (AVR_Toolchain_3.0_149) 4.4.3"

Vorher:
void lcdNumberPad(uint16_t num, uint8_t minDigits, char pad)
{
   uint8_t digits;
   
   if(num)
   {
      digits = ((num >= 10000) ? 5 : ((num >= 1000) ? 4 : ((num >= 100) ? 3 : ((num >= 10) ? 2 : 1))));
      while(minDigits-- > digits)
      {
         lcdData(pad);
      }
      lcdDigits(num);
   }
   else
   {
      while(minDigits-- > 1)
      {
         lcdData(pad);
      }
      lcdData('0');
   }  
}

Nachher:
void lcdNumberPad(uint16_t num, uint8_t minDigits, char pad)
{
   uint8_t digits;
   
   digits = ((num >= 10000) ? 5 : ((num >= 1000) ? 4 : ((num >= 100) ? 3 : ((num >= 10) ? 2 : 1))));
   while(minDigits-- > digits)
   {
      lcdData(pad);
   }

   if(num)
   {
      lcdDigits(num);
   }
   else
   {
      lcdData('0');
   }  
}

Vorher:
0000009c <lcdNumberPad>:
  9c:  ff 92         push  r15
  9e:  0f 93         push  r16
  a0:  1f 93         push  r17
  a2:  cf 93         push  r28
  a4:  df 93         push  r29
  a6:  ec 01         movw  r28, r24
  a8:  16 2f         mov  r17, r22
  aa:  f4 2e         mov  r15, r20
  ac:  00 97         sbiw  r24, 0x00  ; 0
  ae:  31 f1         breq  .+76       ; 0xfc <lcdNumberPad+0x60>
  b0:  87 e2         ldi  r24, 0x27  ; 39
  b2:  c0 31         cpi  r28, 0x10  ; 16
  b4:  d8 07         cpc  r29, r24
  b6:  10 f0         brcs  .+4        ; 0xbc <lcdNumberPad+0x20>
  b8:  05 e0         ldi  r16, 0x05  ; 5
  ba:  16 c0         rjmp  .+44       ; 0xe8 <lcdNumberPad+0x4c>
  bc:  83 e0         ldi  r24, 0x03  ; 3
  be:  c8 3e         cpi  r28, 0xE8  ; 232
  c0:  d8 07         cpc  r29, r24
  c2:  10 f0         brcs  .+4        ; 0xc8 <lcdNumberPad+0x2c>
  c4:  04 e0         ldi  r16, 0x04  ; 4
  c6:  10 c0         rjmp  .+32       ; 0xe8 <lcdNumberPad+0x4c>
  c8:  c4 36         cpi  r28, 0x64  ; 100
  ca:  d1 05         cpc  r29, r1
  cc:  10 f0         brcs  .+4        ; 0xd2 <lcdNumberPad+0x36>
  ce:  03 e0         ldi  r16, 0x03  ; 3
  d0:  0b c0         rjmp  .+22       ; 0xe8 <lcdNumberPad+0x4c>
  d2:  ca 30         cpi  r28, 0x0A  ; 10
  d4:  d1 05         cpc  r29, r1
  d6:  10 f4         brcc  .+4        ; 0xdc <lcdNumberPad+0x40>
  d8:  01 e0         ldi  r16, 0x01  ; 1
  da:  06 c0         rjmp  .+12       ; 0xe8 <lcdNumberPad+0x4c>
  dc:  02 e0         ldi  r16, 0x02  ; 2
  de:  04 c0         rjmp  .+8        ; 0xe8 <lcdNumberPad+0x4c>
  e0:  8f 2d         mov  r24, r15
  e2:  0e 94 48 00   call  0x90  ; 0x90 <lcdData>
  e6:  11 50         subi  r17, 0x01  ; 1
  e8:  01 17         cp  r16, r17
  ea:  d0 f3         brcs  .-12       ; 0xe0 <lcdNumberPad+0x44>
  ec:  ce 01         movw  r24, r28
  ee:  0e 94 4b 00   call  0x96  ; 0x96 <lcdDigits>
  f2:  09 c0         rjmp  .+18       ; 0x106 <lcdNumberPad+0x6a>
  f4:  8f 2d         mov  r24, r15
  f6:  0e 94 48 00   call  0x90  ; 0x90 <lcdData>
  fa:  11 50         subi  r17, 0x01  ; 1
  fc:  12 30         cpi  r17, 0x02  ; 2
  fe:  d0 f7         brcc  .-12       ; 0xf4 <lcdNumberPad+0x58>
 100:  80 e3         ldi  r24, 0x30  ; 48
 102:  0e 94 48 00   call  0x90  ; 0x90 <lcdData>
 106:  df 91         pop  r29
 108:  cf 91         pop  r28
 10a:  1f 91         pop  r17
 10c:  0f 91         pop  r16
 10e:  ff 90         pop  r15
 110:  08 95         ret

Nachher:
0000009c <lcdNumberPad>:
  9c:  ef 92         push  r14
  9e:  ff 92         push  r15
  a0:  1f 93         push  r17
  a2:  df 93         push  r29
  a4:  cf 93         push  r28
  a6:  00 d0         rcall  .+0        ; 0xa8 <lcdNumberPad+0xc>
  a8:  cd b7         in  r28, 0x3d  ; 61
  aa:  de b7         in  r29, 0x3e  ; 62
  ac:  7c 01         movw  r14, r24
  ae:  80 e1         ldi  r24, 0x10  ; 16
  b0:  e8 16         cp  r14, r24
  b2:  87 e2         ldi  r24, 0x27  ; 39
  b4:  f8 06         cpc  r15, r24
  b6:  10 f0         brcs  .+4        ; 0xbc <lcdNumberPad+0x20>
  b8:  15 e0         ldi  r17, 0x05  ; 5
  ba:  1d c0         rjmp  .+58       ; 0xf6 <lcdNumberPad+0x5a>
  bc:  e8 ee         ldi  r30, 0xE8  ; 232
  be:  ee 16         cp  r14, r30
  c0:  e3 e0         ldi  r30, 0x03  ; 3
  c2:  fe 06         cpc  r15, r30
  c4:  10 f0         brcs  .+4        ; 0xca <lcdNumberPad+0x2e>
  c6:  14 e0         ldi  r17, 0x04  ; 4
  c8:  16 c0         rjmp  .+44       ; 0xf6 <lcdNumberPad+0x5a>
  ca:  f4 e6         ldi  r31, 0x64  ; 100
  cc:  ef 16         cp  r14, r31
  ce:  f1 04         cpc  r15, r1
  d0:  10 f0         brcs  .+4        ; 0xd6 <lcdNumberPad+0x3a>
  d2:  13 e0         ldi  r17, 0x03  ; 3
  d4:  10 c0         rjmp  .+32       ; 0xf6 <lcdNumberPad+0x5a>
  d6:  8a e0         ldi  r24, 0x0A  ; 10
  d8:  e8 16         cp  r14, r24
  da:  f1 04         cpc  r15, r1
  dc:  10 f4         brcc  .+4        ; 0xe2 <lcdNumberPad+0x46>
  de:  11 e0         ldi  r17, 0x01  ; 1
  e0:  0a c0         rjmp  .+20       ; 0xf6 <lcdNumberPad+0x5a>
  e2:  12 e0         ldi  r17, 0x02  ; 2
  e4:  08 c0         rjmp  .+16       ; 0xf6 <lcdNumberPad+0x5a>
  e6:  84 2f         mov  r24, r20
  e8:  4a 83         std  Y+2, r20  ; 0x02
  ea:  69 83         std  Y+1, r22  ; 0x01
  ec:  0e 94 48 00   call  0x90  ; 0x90 <lcdData>
  f0:  69 81         ldd  r22, Y+1  ; 0x01
  f2:  61 50         subi  r22, 0x01  ; 1
  f4:  4a 81         ldd  r20, Y+2  ; 0x02
  f6:  16 17         cp  r17, r22
  f8:  b0 f3         brcs  .-20       ; 0xe6 <lcdNumberPad+0x4a>
  fa:  e1 14         cp  r14, r1
  fc:  f1 04         cpc  r15, r1
  fe:  21 f0         breq  .+8        ; 0x108 <lcdNumberPad+0x6c>
 100:  c7 01         movw  r24, r14
 102:  0e 94 4b 00   call  0x96  ; 0x96 <lcdDigits>
 106:  03 c0         rjmp  .+6        ; 0x10e <lcdNumberPad+0x72>
 108:  80 e3         ldi  r24, 0x30  ; 48
 10a:  0e 94 48 00   call  0x90  ; 0x90 <lcdData>
 10e:  0f 90         pop  r0
 110:  0f 90         pop  r0
 112:  cf 91         pop  r28
 114:  df 91         pop  r29
 116:  1f 91         pop  r17
 118:  ff 90         pop  r15
 11a:  ef 90         pop  r14
 11c:  08 95         ret

Autor: reversengineer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ich bin kein Assembler-Experte, aber die zweite Variante sieht beim
> auswerten der Ziffernanzahl (digits = ...) deutlich suboptimal aus.

Sieht für mich praktisch identisch aus.

> Und was sollen die beiden pop r0 gegen Ende? Ich sehe kein dazugehöriges
> push...

Aber ein rcall bei 0xa6. Der Zweck erschliesst sich mir gerade nicht.

Wozu eigentlich das Post-increment an "minDigits"?

In welchem Fall ist "num" false?

Autor: klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die "optimierte" Variante ist langsamer, da sie "digits" immer 
berechnet.

Schreib mal was deine Funktion tun soll, dann wird man dir eine 
optimierte Variante sagen können.

Autor: Manuel Kasten (draradech)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
reversengineer schrieb:
> Sieht für mich praktisch identisch aus.

Die erste Variante nutzt cpi und spart sich damit pro Vergleich ein ldi. 
Warum die zweite nicht?

> Aber ein rcall bei 0xa6. Der Zweck erschliesst sich mir gerade nicht.

Ahh. Was auch immer das soll...

> Wozu eigentlich das Post-increment an "minDigits"?

post-decrement? Um die Anzahl der padding Zeichen herunterzuzählen, die 
noch ausgegeben werden müssen.

> In welchem Fall ist "num" false?

Wenn der User 0 ausgeben möchte? Ich geb ja zu, wenn ich nicht dazusage, 
was das ganze tun soll, ist das nicht gleich offensichtlich. (Siehe 
nächster Beitrag)

Autor: Manuel Kasten (draradech)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
klaus schrieb:
> Die "optimierte" Variante ist langsamer, da sie "digits" immer
> berechnet.
>
> Schreib mal was deine Funktion tun soll, dann wird man dir eine
> optimierte Variante sagen können.

Von Laufzeit hab ich auch nicht geredet, sondern von Codegröße.

Die Funktion soll einfach nur eine Zahl (num) ausgeben, rechtsbündig auf 
(minDigit)s Zeichen, aufgefüllt mit einem padding Zeichen (pad).

lcdDigits gibt mir eine Zahl linksbündig aus (und kann keine 0 
ausgeben).

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Unterschied ist, daß die zweite Variante einen Frame-Pointer 
benötige -- warum auch immer. Irgendwie gehen dem Compiler die Register 
aus, und er legt (mindestend) eine Variable im Frame an bzw. speichert 
sie dort zwischen. Das kostet natürlich Platz und Zeit.

Die POP R0 korrespondieren mit dem RCALL .+0, welches 2 Bytes im Frame 
schafft beziehungsweise ein SP -= 2 implementiert. Das ist billiger, als 
SP zu leden, zu vermindern, und wieder zurückschreiben.

Die benötigte FRame-Größe sieht man am besten in der Assembler-Ausgebe 
des Compilers nicht es Assemblers oder von objdump.

avr-gcc verwendet "ungünstige" Register der Registerklasse "l", warum 
auch immer. avr-gcc-4.5.0 und WinAVR-20100110 (4.3.3) brauchen beide 5 
Bytes Stack und keinen Frame, zudem nutzen sie R16, anstatt wie oben 
R14.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.