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:
> 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?
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.
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)
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).
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.