Mittlerweile bin ich schon soweit, anstelle eines NE555 einen AVR zu
verwenden, nur um eine PWM zu erzeugen. Daher ist das Programm auch
extrem kurz. Das Listung des erzeugten Codes ist aber dennoch etwas
merkwürdig.
Und zwar geht es um die Zeile
OCR0A=adcval/128;
adcval ist unsigned int. Die Division durch 128 macht der Compiler
intelligent indem er das High Byte nach links schiebt und das Low Byte
verwirft. Dass der Compiler wieder einen 16bit Wert erzeugt, wo doch nur
8bit benötigt werden, daran habe ich mich schon gewöhnt, aber wiso macht
der Compiler hier eine sign extension (das ist doch eine, oder ?) ?
Nicht dass es mich in diesem Fall stören würde, aber ich möchte dennoch
gerne wissen, was der Compiler sich dabei denkt, sowas zu machen...
47 .L2:
48 .LM9:
49 001a 85B7 in r24,85-0x20
50 001c 8062 ori r24,lo8(32)
51 001e 85BF out 85-0x20,r24
52 /* #APP */
53 0020 8895 sleep
54
55 /* #NOAPP */
56 0022 85B7 in r24,85-0x20
57 0024 8F7D andi r24,lo8(-33)
58 0026 85BF out 85-0x20,r24
59 .LM10:
60 0028 8091 0000 lds r24,adcval
61 002c 9091 0000 lds r25,(adcval)+1
62 0030 880F lsl r24
63 0032 892F mov r24,r25
64 0034 881F rol r24
65 0036 990B sbc r25,r25
66 0038 9195 neg r25
67 003a 86BF out 86-0x20,r24
68 003c 00C0 rjmp .L2
Das ist keine sign extension. Das ist der Weg, das bei ROL
rausgeschobene Bit an der richtigen Stelle zu plazieren.
Bei
unsigned int temp = adcval >> 7;
ergibt sich ja ein für temp ein Wertebereich von 0..511, für R25 also 0
oder 1. Und genau so kommt's auch raus. Eine sign extension sieht anders
aus.
Stimmt, das ist ja echt tricky. Ich habe eine Weile gebraucht bis ich
das verstanden habe:
Gibt es bei der Multiplikation mit 2 einen Überlauf (also das Carry ist
nach dem Schieben gesetzt), wird r25 auf 255 gesetzt (und das in einem
Befehl, echt genial gelöst). Anschließend wird die 255 noch negiert um
daraus eine 1 zu gewinnen.
Wenn jetzt der Compiler auch noch merken würde, dass diese geniale
Lösung sinnlos ist, da das Highbyte nicht gebraucht wird, dann käme das
schon an eine Assembler Lösung ran...
Benedikt K. wrote:
> Wenn jetzt der Compiler auch noch merken würde, dass diese geniale> Lösung sinnlos ist, da das Highbyte nicht gebraucht wird, dann käme das> schon an eine Assembler Lösung ran...
Ich habe nicht nachgeguckt, aber ich fürchte, die entsprechende
Befehlsfolge ist im Compiler einfach als Muster ,,handoptimiert''
abgelegt. Damit kann der Compiler nicht einfach einen Teil davon
weglassen. (Das ist also beinahe so, als wäre es in inline asm
geschrieben, da kann der Compiler auch nicht ,,reinsehen''.)
Ja, es hatte mich gerade interessiert, hier ist die Stelle im
Compiler:
1
/* 16bit logic shift right ((unsigned short)x >> i) */