Forum: Compiler & IDEs Endianess Umwandlung notwendig?


von Le_Q (Gast)


Lesenswert?

Hallo zusammen,

ich hätte mal eine Frage. Ich arbeite mit einem Cortex M3, dieser 
arbeitet im little endian. Jetzt bekomme ich aber externe Daten im Big 
endian in den Speicher gelegt. Wenn ich jetzt mit diesen Daten arbeiten 
möchte, muss ich die zuerst konvertieren, oder? Weil ansonsten 
interpretiert der Cortex einen falschen Wert. Es handelt sich um 16Bit 
Werte. So wie ich es verstehe muss ich quasi "nur" das erste mit dem 
zweiten Byte vertauschen um die Daten in den little endian zu bringen.

Also:
Der Wert 43707 wird im big endian gespeichert, also 0xAABB. Wenn ich 
diesen Wert jetzt vom Cortex interpretieren lasse würde der 0xBBAA also 
48042 lesen.

Ist dem so? Gibt es "standard" Funktionen dafür bzw. irgendwelche 
performanten implementierungen?

Wahrscheinlich lachen sich die meisten über die Frage kaputt... Deshalb 
möge man meine Unkenntnis entschuldigen.

von Sven H. (dsb_sven)


Lesenswert?

Du musst die Reihenfolge der Bytes umdrehen, vollkommen richtig. Die 
Frage ist, bekommst du auch mal 4 Byte Daten? Wenn ja wirds etwas 
komplexer, an sonsten einfach Bytes tauschen.

Da gibts verschiedene Lösungswege. Du könntest den int16_t mit 0xff 
"verUNDen" und in ein int8_t packen, den int16_t acht mal nach rechts 
schieben und dann den int8_t in den oberen Teil deines Wertes packen.

Was auch gehen würde, wäre ein union.
1
union byteToWord
2
{
3
 int8_t byte[2];
4
 int16_t word;
5
};

Oder so ;-) Bin grad nicht ganz Sattelfest mit unions.

Dann hättest du die Möglichkeit davon zwei zu erstellen und könntest mit
1
union2.word = DeinWertAusDemSpeicher;
2
union1.byte[1] = union2.byte[2];
3
union1.byte[2] = union2.byte[1];
4
DeineVariableZurVerarbeitung = union1.word;

Sicherlich gibt es noch viel viel bessere Varianten als meine hier ;)

von Oliver (Gast)


Lesenswert?

Sven H. schrieb:
> Sicherlich gibt es noch viel viel bessere Varianten als meine hier ;)

Eine Zwischenvariable wäre nicht schlecht ;-)

Oliver

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

GCC kennt ein __builtin_bswap32 für diesen Zweck

http://gcc.gnu.org/onlinedocs/gcc-4.4.4/gcc/Other-Builtins.html#Other-Builtins

von Marcus H. (mharnisch) Benutzerseite


Lesenswert?

Le_Q schrieb:
> Gibt es "standard" Funktionen dafür bzw. irgendwelche performanten
> implementierungen?

Assembler: REV16

von Le_Q (Gast)


Lesenswert?

Vielen herzlichen Dank an euch alle!

Ich werde die Varianten mal testen und schauen was für meinen Geschmack 
das beste ist. Aber ich denke es wird auf die REV16 Variante raus 
laufen. Damit ist der Code zwar nicht mehr CPU und Compiler independent, 
aber wenn man auf gute Performance aus ist, gestalltet sich das ohnehin 
schwer.

Nochmal Danke an alle. :o)

von Rolf Magnus (Gast)


Lesenswert?

> GCC kennt ein __builtin_bswap32 für diesen Zweck

Interessanterweise gibt es da eins für 32 und eins für 64 Bit, aber 
anscheinend keins für 16 Bit.

von Le_Q (Gast)


Lesenswert?

Sorry noch ne Frage. Ich habe mal geschaut wie die REV16 im Thumb2 
Instruction Set (Cortex-m3) implementiert ist.

Bytes in both halfwords
REV16 Rd, Rm
Rd[15:8] := Rm[7:0],
Rd[7:0] := Rm[15:8],
Rd[31:24] := Rm[23:16],
Rd[23:16] := Rm[31:24]

Der tauscht hier quasi alle 4 Byte eines 32 Bit Registers. Das macht 
insofern Sinn, also dass der Cortex 32Bit Register verwendet. Wieso 
heißt dann aber der Befehel REV16? Das Ergebnis stimmt natürlich wenn 
ich in beide Register 16 Bit Werte lade, allerdings werden hier 2 
Befehle ausgeführt, die man eigentlich nicht bräuchte. Oder bezieht sich 
das "16" hier allgemein auf die Vertauschung der 2 Bytes in den beiden 
16 bit Worten?

Nun gut, ich teste mal rum... ;)

von (prx) A. K. (prx)


Lesenswert?

Le_Q schrieb:

> ich in beide Register 16 Bit Werte lade, allerdings werden hier 2
> Befehle ausgeführt, die man eigentlich nicht bräuchte.

Nö. Er macht zwar mehr als du für das Vertauschen der beiden unteren 
Bytes benötigst, aber das sind nicht 4 Befehle, sondern ist eine einzige 
Operation, die im Handbuch als 4 Operationen dargestellt wird.

In der gleichen Weise könntest du Shift-Operationen auch als
  d[31] = s[30]
  ...
  d[1] = s[0]
  d[0] = 0
darstellen und es wären dennoch keine 32 Befehle.

> das "16" hier allgemein auf die Vertauschung der 2 Bytes in den beiden
> 16 bit Worten?

Damit wird signalisiert, dass die Bytes innerhalb der 16-Bit Hälften 
vertauscht werden.

von Le_Q (Gast)


Lesenswert?

Ah ich verstehe. Ich dachte, dass REV16 ein Pseudo-OpCode ist, der in 
Wirklichkeit aus den 4 einzelnen besteht.

Danke für die Aufklärung.

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.