Hallo Leute Brauche wieder mal dringend Eure Hilfe. Muss in einer long Variable (32Bit) alle Bits vertauschen. Bit31 Bit0 Alt: 11110001 11110001 11110001 11110001 Neu: 10001111 10001111 10001111 10001111 Wer kennt die effizienteste Variante? Danke im Voraus.
eventuell mit Schiebebefehlen unter Benutzung des Carry Bit edit: zb r10 - 14 und hilfregister r17 clc ;clear carry lsr r14 rol r17
Auf einen Rutsch wohl blöd zu machen. In einzelnen Byte besser. Ein Byte drehen:
1 | unsigned char umkehr(unsigned char n){ |
2 | n=((n>>1)&0x55)|((n<<1)&0xaa); |
3 | n=((n>>2)&0x33)|((n<<2)&0xcc); |
4 | return (n>>4)|(n<<4); |
5 | }
|
Byte 1 mit 4 und 2 mit 3 tauschen. fertig avr
Hallo Leute Danke für die Info. Hab's jetzt so gelöst:
1 | unsigned char i; |
2 | unsigned long mask; |
3 | unsigned long tmp_data; |
4 | unsigned long reverse_data; |
5 | |
6 | mask = 0x00000001; |
7 | reverse_data = 0; |
8 | |
9 | //Longwert spiegeln
|
10 | for (i=0;i<32;i++) |
11 | {
|
12 | if((tmp_data & 0x80000000) == 0x80000000) |
13 | {
|
14 | reverse_data |= mask << (unsigned long)i; |
15 | tmp_data = tmp_data << 1; |
16 | }
|
17 | else
|
18 | {
|
19 | reverse_data &= ~(mask << (unsigned long)i); |
20 | tmp_data = tmp_data << 1; |
21 | }
|
22 | }
|
Ist vielleicht nicht die beste Lösung, aber es tut.
Andreas Häusler schrieb:
> Muss in einer long Variable (32Bit) alle Bits vertauschen.
Welcher Prozessor?
bei 4 Bit macht man Nibbletausch. Warum nicht auf 8 Bit Ebene ? 0 Problem in ASM: Sonst hilft wohl nur Ringelpietz mit Anfassen :-)) Oder ein Tauschbuffer.
Hintergrund meiner Frage: Es gibt Prozessoren, die für sowas nur einen Takt benötigen. Weil entsprechender Befehl vorhanden. Ausserdem wurde anfangs explizit nach der effizientesten Variante gesucht, nicht - wie später - nach irgendeiner.
A. K. schrieb: > Ausserdem wurde > anfangs explizit nach der effizientesten Variante gesucht, nicht - wie > später - nach irgendeiner. Leider hast Du die Plattform nicht erwähnt. Daher nur Antworten aus der Glaskugel. Sorry. Oder wäre die Antwort SWAP A hilfreicher ?
Hallo zusammen Ich möchte dieses Thema nochmals ein wenig aufwärmen... Ich portiere gerade ein Programm von einem STM32 auf einen Stellaris uC. Dabei ist mir aufgefallen, dass ich bei der SPI-Schnittstelle die Wahl von LSB-First nicht mehr habe. Bei den Stellaris ist halt einfach MSB-First fix einprogrammiert. @A.K. könntest du mir vielleicht den Befehl zum drehen eines 16 Bit Wortes nennen? Ich stehe da gerade ziemlich auf dem Schlauch. Besten Dank im Voraus
Ich würde es mal der Suche versuchen... Und fände dann ganz leicht den 8 Jahre alten Beitrag "Re: Bitreihenfolge ändern" Und den 3 Jahre alten Beitrag "Wie drehe ich eine Bitreihenfolge um??" Und noch einige mehr... > R. K. schrieb: > Bei den Stellaris ist halt einfach MSB-First fix einprogrammiert. Ja, weil das der Rest der Welt auch so macht...
>> R. K. schrieb: >> Bei den Stellaris ist halt einfach MSB-First fix einprogrammiert. > Ja, weil das der Rest der Welt auch so macht... Doch genau damit habe ich ein Problem. Ich empfange einen kontinuielichen Datenstrom. Ich clocke dabei die SPI selbst und speichere einfach alle empfangenen Bits in einem grossen Buffer. Danach suche ich in diesem Buffer nach meinem Sync-Wort und decodiere die Daten. Da ich asynchron arbeite kann ein Daten-Byte auch über mehre Bytes im Speicher verteilt sein. Durch die LittleEndian eigenschaft des Cortex ergeben sich dann deutliche Unschönheiten. Der DMA füllt beispielsweise den Buffer an der stelle [1] mit dem ersten Byte. Danach füllt er den Buffer an der stelle [2] mit dem nächsten Byte... Wenn ich die Daten für eine effiziente Verarbeitung mit 32-Bit-Variablen verarbeiten will krieg ich ein riisen Problem wegen dem little Endian. Könnte ich die Daten mit LSB first im Speicher ablegen, so würde das ganze zwar vedreht, jedoch gibt es keine Fehler im Speicher. Vielleicht kennst du auch eine Möglickeit, damit der DMA meine Byte-Daten so in den Speicher schreibt, damit ich die Daten später als 32-Bit interpretieren kann?
R. K. schrieb: > Ich clocke dabei die SPI selbst und speichere einfach alle empfangenen > Bits in einem grossen Buffer. Danach suche ich in diesem Buffer nach > meinem Sync-Wort und decodiere die Daten. Und warum suchst du nicht während der Übertragung nach dem Sync-Wort und speicherst ab dann die Daten? Dann hast du nuch nicht irgendwo mitten drin einen Byte- bzw. Wortumbruch, und du weißt sofort wo die relevante Information im Speicher liegt.
> Wer kennt die effizienteste Variante?
Tabellenzugriff.
Als speed/space tradeoff wohl byteweise.
union
{
long longvalue;
unsigned char bytevalue[3];
}
value,newvalue;
unsigned char table[256]={0x00,0x80,0x40,0xC0,...};
newvalue.bytevalue[0]=table[value.bytevalue[3]];
newvalue.bytevalue[1]=table[value.bytevalue[2]];
newvalue.bytevalue[2]=table[value.bytevalue[1]];
newvalue.bytevalue[3]=table[value.bytevalue[0]];
Zumindest auf Prozessoren ohne barrel shifter.
Cortex M3/4 kennt den RBIT Befehl: RBIT: Reverse the bit order in a 32-bit word Und dazu noch verschiedene REV Befehle, um Bytes zu tauschen. Ist das nicht was hier benoetigt wird?
for (i=0;i<32;i++) { if((tmp_data & 0x80000000) == 0x80000000) { reverse_data |= mask << (unsigned long)i; tmp_data = tmp_data << 1; } else { reverse_data &= ~(mask << (unsigned long)i); tmp_data = tmp_data << 1; } } Das geht aber eleganter (mask ist Maske und Zähler in einem): data_out=0;mask=0x80000000;do{data_out<<=1; if((data&mask)!=0)data_out |= 1;}while((mask>>=1)!=0);
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.