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) */
|
2 | |
3 | const char * |
4 | lshrhi3_out (rtx insn, rtx operands[], int *len) |
5 | {
|
6 | if (GET_CODE (operands[2]) == CONST_INT) |
7 | ...
|
8 | case 7: |
9 | *len = 5; |
10 | return (AS1 (lsl,%A0) CR_TAB |
11 | AS2 (mov,%A0,%B0) CR_TAB |
12 | AS1 (rol,%A0) CR_TAB |
13 | AS2 (sbc,%B0,%B0) CR_TAB |
14 | AS1 (neg,%B0)); |
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.