Hallo, eine kurze Frage, die mir gerade durch den Kopf geistert: Eine Berechnung wird immer in der Breite des größten beteiligten Datentypen durchgeführt. Mindestens aber in INT. Der Datentyp der links vom "=" steht spielt dabei keine Rolle. Deswegen funktinoiert beim ATmega auch: uint8_t a = 5; uint8_t b = 3; uint16_t c = a * b; Ohne dass Casts notwendig sind. (Mal davon abgesehen dass der Compiler hier bei Konstanten eh selber rechnen wird) Aber wieso kann der Compiler dann aus "a + b" einen einfachen "add"-Befehl machen, der ja nur 8 Bit werte addiert?
bal schrieb: > Aber wieso kann der Compiler dann aus "a + b" einen einfachen > "add"-Befehl machen, der ja nur 8 Bit werte addiert? kann er das denn? Woher weisst du das er das macht?
bal schrieb: > Aber wieso kann der Compiler dann aus "a + b" einen einfachen > "add"-Befehl machen, der ja nur 8 Bit werte addiert? Er muss sich so verhalten, als ob entsprechend der Definition gearbeitet wird. Weiss er jedoch, dass in optimierter Form das gleiche Ergebnis raus kommt, dann darf er abkürzen. Also vereinfacht: uint8_t a, b; uint16_t c = a + b; // 16bit Rechnung nötig uint8_t d = a + b; // 8bit Rechnung zulässig
Peter II schrieb: > kann er das denn? Woher weisst du das er das macht? Weil er mir uint8_t test2(uint8_t a, uint8_t b) { return a + b; } in 92: 86 0f add r24, r22 94: 08 95 ret übersetzt. @ A.K.: Macht Sinn. Ich ging bisher davon aus dass nur die an der Berechnung beteiligten Datentypen eine Rolle spielen. Die Zuweisung danach ist wieder ein anderes Thema...
Hm, ohne Optimierung wird der Code viel länger: uint8_t test2(uint8_t a, uint8_t b) { 92: df 93 push r29 94: cf 93 push r28 96: 00 d0 rcall .+0 ; 0x98 <test2+0x6> 98: cd b7 in r28, 0x3d ; 61 9a: de b7 in r29, 0x3e ; 62 9c: 89 83 std Y+1, r24 ; 0x01 9e: 6a 83 std Y+2, r22 ; 0x02 return a + b; a0: 99 81 ldd r25, Y+1 ; 0x01 a2: 8a 81 ldd r24, Y+2 ; 0x02 a4: 89 0f add r24, r25 } a6: 0f 90 pop r0 a8: 0f 90 pop r0 aa: cf 91 pop r28 ac: df 91 pop r29 ae: 08 95 ret Bin ja nicht sooo fit in Assembler, aber die Berechnung ist doch immer noch in 8Bit. Lediglich der Funktionsaufruf macht mehr Arbeit.
bal schrieb: > Macht Sinn. Ich ging bisher davon aus dass nur die an der Berechnung > beteiligten Datentypen eine Rolle spielen. Formal gesehen liegst du richtig. Formal muss er so tun, als ob er in "int" rechnet. Aber wenn er am Kontext erkennt, dass das ausser Aufwand nix einbringt, dann gehts auch eine Nummer kleiner. So darf er bei uint8_t e = (a + b) / 2; nicht in 8 Bits rechnen, weil das Ergebnis nicht durchweg identisch ist.
bal schrieb: > Weil er mir nicht nur dir ;-) > uint8_t test2 (uint8_t a, uint8_t b) > { > return a + b; > } > > in > > 92: 86 0f add r24, r22 > 94: 08 95 ret > > übersetzt. a + b ist ein 16-bit Wert, jedoch wird von test2 nur ein 8-Bit Wert returniert. Dies ist so sein das ABI geändert wurde, irdendwo zwischen GCC Version 4.2 und 4.3 wenn ich mich recht entsinne: Es gibt keine Promotion von 8-Bit Werten zu 16-Bit Werten mehr.
...und es gibt sogar eine AVR-LibC Anforderung die ABI-Doku dahingehend anzupassen: http://savannah.nongnu.org/bugs/?37026
A. K. schrieb: > Weiss er jedoch, dass in optimierter Form das gleiche > Ergebnis raus kommt, dann darf er abkürzen. Also vereinfacht: > uint8_t a, b; > uint8_t d = a + b; // 8bit Rechnung zulässig demnach ist das hier bal schrieb: > uint8_t test2(uint8_t a, uint8_t b) > { > return a + b; > } > 92: 86 0f add r24, r22 > 94: 08 95 ret doch vollkommen in Ordnung?! Oder hab ich nen Knoten im Hirn?
bal schrieb: > Ich ging bisher davon aus dass nur die an der Berechnung beteiligten > Datentypen eine Rolle spielen. Das ist auch so. Teil der C-Norm ist aber auch die sogenannte "as-if"-Regel. Diese besagt, daß der Compiler von deinem Code beliebig abweichen darf, solange das beobachtbare Verhalten ("observable behavior") gleich bleibt. Der Optimizer erkennt, daß eine Rechnung in 8 Bit gegenüber der in 16 Bit am Ergebnis nichts ändert, also darf er die Vereinfachung laut as-if-Regel machen.
Johann L. schrieb: > a + b ist ein 16-bit Wert, jedoch wird von test2 nur ein 8-Bit Wert > returniert. Dies ist so sein das ABI geändert wurde, irdendwo zwischen > GCC Version 4.2 und 4.3 wenn ich mich recht entsinne: Es gibt keine > Promotion von 8-Bit Werten zu 16-Bit Werten mehr. Mal für einen Noob wie mich, weil es mich interessiert: Was ist das ABI und was versteht man unter Promotion bei den Datentypen? Vielen Dank Fabian
Fabian Hoemcke schrieb: > Johann L. schrieb: >> a + b ist ein 16-bit Wert, jedoch wird von test2 nur ein 8-Bit Wert >> returniert. Dies ist so sein das ABI geändert wurde, irdendwo zwischen >> GCC Version 4.2 und 4.3 wenn ich mich recht entsinne: Es gibt keine >> Promotion von 8-Bit Werten zu 16-Bit Werten mehr. > > Mal für einen Noob wie mich, weil es mich interessiert: > Was ist das ABI http://de.wikipedia.org/wiki/Binärschnittstelle > und was versteht man unter Promotion bei den Datentypen? http://de.wikipedia.org/wiki/Promotion_(Typumwandlung)
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.