Forum: Mikrocontroller und Digitale Elektronik Problem bei 32-Bit-Addition


von Enrico. J. (ejoerns)


Lesenswert?

Hi,

ich bin gerade mit meine Latein am Ende. Folgendes Problem:

Ich möchte 2 32bit integer addieren.
Die Funktion, welche die Rechnung enthält soll in einer statischen 
Bibliothek eingebunden werden.
In meinem Hauptprojekt will ich diese verwenden.

Das Problem: Das Ergebnis der Addition ist nonsense.
objdump verrät mir eine Zeile:
1
0e 94 00 00   call  0  ; 0x0 <mulkD>

Wenn ich nur die Funktion kopiere und in meinen Hauptprojekt 
(Contiki-Programm) kompiliere, erhalte ich das für mich sinvollere 
Ergebnis
1
0e 94 79 47   call  0x8ef2  ; 0x8ef2 <__mulsi3>

Was mache ich im ersten Teil falsch? Irgendein compiler-flag?

Vielen Dank schonmal.

von Purzel H. (hacky)


Lesenswert?

Spannend. Controller  ?

von Enrico. J. (ejoerns)


Lesenswert?

Aufrührend. AVR (ATmega1284p)

Vergisst man leider manchmal zu erwähnen, wenn man in seiner kleinen 
Welt gefangen ist.

Das Problem habe ich jetzt gelöst. Der angegebene Auszug ergibt sich 
wohl eher aus dem Linker.
Die Lösung des Problems war ein einfaches
1
-fno-strict-aliasing
 für den avr-gcc.

Die Problemstelle war eine Zuweisung eines long-Wertes an ein 2x-short 
array mittels pointer-casting.

Schematisch:
1
unsigned short xs[2];
2
*((long*)xs) = long_value;

von Sam P. (Gast)


Lesenswert?

Sowas löst man Standardkonform mit einer Union, so dass keine speziellen 
Compiler-Flags mehr nötig sind:
1
union {
2
    long val32;
3
    short val16[2];
4
} result;
5
6
result.val32 = a*b;
7
8
printf("%d, %d\n", result.val16[0], result.val16[1]);

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Sam P. schrieb:
> Sowas löst man Standardkonform mit einer Union, so dass keine speziellen
> Compiler-Flags mehr nötig sind:
>
1
> union {
2
>     long val32;
3
>     short val16[2];
4
> } result;
5
> 
6
> result.val32 = a*b;
7
> 
8
> printf("%d, %d\n", result.val16[0], result.val16[1]);

Was aber auch nicht standardkonform ist :-)

Der Standard sichert nur zu, daß die Komponente, die als letztes 
geschrieben wurde, beim Lesen diesen Wert liefert.

In deinem Fall ist der Wert von result.val16[] undefiniert.

Als Spracherweiterung sichert GCC zu, daß type punning funktioniert. 
Obiger Code geht also mit GCC, aber nicht unbedingt mit anderen 
Compilern.

Siehe auch "Casting does not work as expected when optimization is 
turned on" in http://gcc.gnu.org/bugs/#nonbugs

Neben Type-Punning sind natürlich auch die Aliasing-Regeln von C zu 
beachten: Ein short* ist kein Alias für ein long* oder umgekehrt. Wird 
also über ein long* geschrieben, kann der Compiler davon ausgehen, daß 
alles, was der über ein short* bereits kennt, sich dadurch nicht ändert.

von Peter II (Gast)


Lesenswert?

Sam P. schrieb:
> Sowas löst man Standardkonform mit einer Union, so dass keine speziellen
> Compiler-Flags mehr nötig sind:

dumm nur das denn auf little oder bigendian etwas anders rauskommt.

von Sam P. (Gast)


Lesenswert?

Peter II schrieb:
> dumm nur das denn auf little oder bigendian etwas anders rauskommt.

Das hat man mit type-punning genauso. Endian-unabhängig (und 
Standard-konform -- ich gestehe ein, was ich vorschlug ist nur 
"GCC-konform") geht sowas wohl nur mit Bitmanipulation, also sowas wie
1
val16high = (val32>>16)&0xffff;
2
val16low = val32&0xffff;

(abzüglich Details zu signed/unsigned und so, die man ggf. beachten 
muss)

Wenn der Compiler schlau genug ist, übersetzt er das auch in genau so 
effizienten Maschinencode wie mit type-punning oder union. Es ist nur 
leider etwas weniger offensichtlich, was die Zeilen bezwecken sollen.

von Enrico. J. (ejoerns)


Lesenswert?

Vielen Dank für die zusätzlichen Anmerkungen und Anregungen! :)

Das ganze war ne fertige library, die ich eig. nur kompilieren wollte 
und daher, wenn nicht unbedingt notwendig, nicht im Code rumbasteln.

Für eigene Implementierungen dieser Art bin ich nun aber gerüstet ;)

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
Noch kein Account? Hier anmelden.