Forum: Mikrocontroller und Digitale Elektronik mehrer Bits verschieben


von auf_den_Schlauch_steher (Gast)


Lesenswert?

Hallo,

hab eine einfache Frage, komme aber gerade nicht selber drauf.

Ich möchte die ersten 4 Bit eines 8 Bitsignales um 4 nach links 
verschieben.

Einzelne Bits in C kann man ja wie folgt verschieben:

Signal[0] << 4; // 1.Bit um 4 nach links verschoben

Nun möchte ich aber die 4.Bit mit einmal verschieben, gibts da eine 
einfache Möglichkeit oder muss ich jedes Bit einzeln verschieben?

Danke

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Die restlichn bits werden "mit" verschoben...
allso aus 01010 << 3 wir 01000

Oder meisnt du was anderes?

von Johannes M. (johnny-m)


Lesenswert?

Mit einem Shift werden immer alle Bits in der betreffenden Variable 
verschoben. Die Shift-Operatoren besitzen 2 Argumente: dasjenige links 
vom Operator ist die Variable, die geschoben werden soll und rechts 
steht die Anzahl der Stellen, um die geschoben werden soll.

von Johannes M. (johnny-m)


Lesenswert?

Ach ja, wenn Du meinen solltest, mit Signal[0] würdest Du auf ein Bit 
einer Variablen namens Signal zugreifen, dann täuschst Du Dich! 
Signal[0] liefert das erste Element eines Arrays (von Variablen des Typs 
XXX). Wenn Signal ein Array von int ist (also z.B.
1
 int Signal[Array_Laenge];
), dann ist Signal[0] auch ein int mit mindestens 16 Bit. 
Dementsprechend werden z.B. bei
1
Irgendwas = Signal[0] << 4;
auch alle 16 Bit geschoben.

von auf_den_Schlauch_steher (Gast)


Lesenswert?

Ok,

dann ist es doch nicht so einfach.

Wie kann ich denn die ersten 4 Bit aus dem Signal extrahieren, um diese 
zu verschieben?

Ich muss nur, die ersten 4 verschieben und nicht alle.

von Christian R. (supachris)


Lesenswert?

variable_2 = variable_1;

variable_2 = variable_2 << 4;

In Variable_2 stehen dann die 4 unteren Bits aus Variable_1, verschoben 
um 4 Stellen.

Innerhalb der gleichen Variable geht das natürlich nicht.

von Peter D. (peda)


Lesenswert?

auf_den_Schlauch_steher wrote:

> Ich muss nur, die ersten 4 verschieben und nicht alle.

Dann mußt Du die maskieren (AND):
1
variable = (variable & 0x0F) << n;


Peter

von Falk B. (falk)


Lesenswert?


von auf_den_Schlauch_steher (Gast)


Lesenswert?

Wenn ich das richtig mit der Bitmanipulation verstanden habe müsste nach
1
variable = (variable & 0x0F) << 4;
 z.B. aus 1001 0110 => 1111 0110 werden?

von Sven P. (Gast)


Lesenswert?

Je nach Variablentypus ist die Maskiererei auch Käse, weil, wenn ich in 
nem Byte die unteren vier Bits um vier Stellen nach links verschiebe...

Achso, und Schiebereien um mehrere Positionen mag der GCC+AVR im Übrigen 
garnicht, und erst recht nicht, wenn die Anzahl der zu verschiebenden 
Stellen noch variabel ist:
1
uint8_t a, b, i;
2
3
a = b << 1; /* schnell */
4
a = b << 4; /* auch noch schnell, weil swap+and in Assembler */
5
a = b << 3; /* nich-sooooo-gut, aber immer noch schnell */
6
a = b << i; /* Bullshit, weil Schleife in Assembler */

von Falk B. (falk)


Lesenswert?

@auf_den_Schlauch_steher (Gast)

>Wenn ich das richtig mit der Bitmanipulation verstanden habe müsste

>nachvariable = (variable & 0x0F) << 4;

> z.B. aus 1001 0110 => 1111 0110 werden?

Nö.

Erster Schritt, Maskieren in der Klammer

(variable & 0x0F) = 1001 0110 & 0000 1111 = 0000 0110

Zweiter Schritt, nach Links verschieben, es wird mit Null aufgefüllt

() <<4 = 0000 0110 << 4 = 0110 0000

MFG
Falk

von Peter D. (peda)


Lesenswert?

auf_den_Schlauch_steher wrote:
> Wenn ich das richtig mit der Bitmanipulation verstanden habe müsste nach
>
1
variable = (variable & 0x0F) << 4;
 z.B. aus 1001 0110 =>
> 1111 0110 werden?

Natürlich nicht.

Nach dem Maskieren ist es 0000 0110 und dann nach dem Schieben um 4
0110 0000.


Peter

von meister lampe (Gast)


Lesenswert?

> Nach dem Maskieren ist es 0000 0110 und dann nach dem Schieben um 4 0110 0000.

richtig.
warum also die maskiererei?

variable <<= 4;

macht das gleiche.

von Michael (Gast)


Lesenswert?

In dem Fall.... . Schieb doch mal mit 3.

von Eddy C. (chrisi)


Lesenswert?

Mein Gott, Michael, das ist doch der Gag, dass man bei 4 Bits schieben 
eben nicht maskieren muss. Und sag jetzt nicht: "Dann mach' das mal mit 
ner 16-Bit-Variable". Dann gibt's eins auf die Nüsse.

von Christian R. (supachris)


Lesenswert?

Das ist aber dann Compiler-abhängig, oder? Also ich meine, der MSPGCC 
maskiert bei Bedarf selbst, bevor er rotiert....hab das mal im Listung 
gesehn.

von Sven P. (Gast)


Lesenswert?

Christian R. wrote:
> Das ist aber dann Compiler-abhängig, oder? Also ich meine, der MSPGCC
> maskiert bei Bedarf selbst, bevor er rotiert....hab das mal im Listung
> gesehn.

Rotieren geht in C nicht direkt. Und beim Schieben ists im Standard 
festgelegt, dass links bzw. rechts Nullen nachgeschoben werden.

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Sven Pauli wrote:
> Rotieren geht in C nicht direkt. Und beim Schieben ists im Standard
> festgelegt, dass links bzw. rechts Nullen nachgeschoben werden.
Sicher??
Also "mein" Standard (C99) sagt:
links shift: es wird IMMER mit 0 aufegführt.
rechts shift: unsinged wird mit 0 aufgefüllt, signed wird mit dem 
sign-bit (negativ = 1, postiv = 0) aufgefüllt!

von Sven P. (Gast)


Lesenswert?

Läubi Mail@laeubi.de wrote:
> Sven Pauli wrote:
>> Rotieren geht in C nicht direkt. Und beim Schieben ists im Standard
>> festgelegt, dass links bzw. rechts Nullen nachgeschoben werden.
> Sicher??
Ja, sicher...wobei ich jetzt unsigned vorausgesetzt hab :-/ Ansonsten 
sinds halt VZ-Bits, jubb.

von meister lampe (Gast)


Lesenswert?

> Hallo, hab eine einfache Frage, komme aber gerade nicht selber drauf.
> Ich möchte die ersten 4 Bit eines 8 Bitsignales um 4 nach links verschieben.

die lösung heisst

unsigned char signal;
signal <<= 4;

over and out.

von Matthias L. (matze88)


Lesenswert?

ich habe das gefühl, dass der OP genau das erreichen will, was er in der 
Zwischenfrage gestellt hat:
0100 1001     solll nach der operation zu 1101 ?(0000)? werden.
Das funktioniert wie folgt:

uint8_t a = 0b01001001;
a |= (a << 4);

(falls gewünscht low nibble auf 0 setzen:)
a &= 0xF0;

Ich weiß nicht, was der Compiler daraus macht. aber im Assembler würde 
ich das so lösen:
rE -> Eingangsregister (high register)
rT -> temporäres register

mov rT, rE
swap rT
or rE, rT
andi rE, 0xF0

das gewünschte Ergebnis liegt dann wieder in rE.
Matze

von auf_den_Schlauch_steher (Gast)


Lesenswert?

Hi,

das von Matze scheint das zu seien was ich brauche. Denn nachdem ich die 
ersten 4 Bit verschoben habe, muss ich sie wieder mit den letzten 4.Bit 
addieren. Sry, dass ich das nicht gleich geschrieben habe, dachte nicht 
das es bei der schiebe Operation von belangen ist.

Ich werde das ganze mal testen und schauen ob es das gewünschte Ergebnis 
liefert.

von Matthias L. (matze88)


Lesenswert?

Du musst dich mal bitte auch weiterhin etwas genauer ausdrücken. In 
deinem letzten Post schreibst du:
Denn nachdem ich die
ersten 4 Bit verschoben habe, muss ich sie wieder mit den letzten 4.Bit
addieren.

2 Sachen: a) "den letzten 4. bit" gibt es nicht. der Punkt hinter der 4 
bedeuted VIERTES Bit und bezieht sich somit auf 1 Bit. Kann eventuell in 
anderer Formulierung zu Unklarheiten führen.

b) Die lieben Grundrechenarten eines Prozessors. Du sprichst hier von 
"addieren". Da besteht ein kleiner aber feiner Unterschied zum Oder:

0b011001011
0b101000101 seien unsere 2 Bytes. Verodert ergibt sich:

0b111001111    addiert ergibt sich aber:
0b000010000 + carry bit set -> 9 bit ergebnis 0b1000010000

wahh ich seh gerade ich hab versehtnlich 9 statt 8 Bits aufgeschrieben, 
aber das Additionsbeispiel ist gerade so toll, ich belasse es einfach 
mal dabei.

Matze (Der eigentlich gerade an seinem Artikel arbeiten sollte, da in 
nichtmal mehr 10 Stunden die Deadline vorbei ist...)

von Tommy (Gast)


Lesenswert?

Hallo.
Ich hab auch mal eine Frage zum Bitshifting.

Hab eine 16Bit-Variable aus der ein 12Bit-Wert extrahiert werden 
soll.Dieser Wert setzt sich aus den Bits 0 bis 11 zusammen.Wie bekomme 
ich da den Wert nun aus den 16Bit heraus,mit Vorzeichen?!
D.h. in der Spanne von -2046 bis 2045?

hier der Code (beispielhaft):

signed int variable1 = 0x2DAA;

variable1 <<= 4; // Schiebe um 4 Stellen nach links

Der Wert von variable1 bewegt sich aber nun nicht im Bereich von -2046 
bis 2045. Wie bekomm ich das hin?

von Peter D. (peda)


Lesenswert?

1
uint16_t sign12( uint16_t i )
2
{
3
  if( i & 0x0800 )
4
    i |= 0xF000;
5
  return i;
6
}


Peter

von Denny S. (nightstorm99)


Lesenswert?

Hallo!

Ich habe gerade auch ein paar Probleme mit dem Bit bestimmen.

Ich habe ein uint16_t und will nun nur die unteren 3 Bits wissen.
Wie mache ich das?


Gruß Denny

von Karl H. (kbuchegg)


Lesenswert?

Denny S. schrieb:
> Hallo!
>
> Ich habe gerade auch ein paar Probleme mit dem Bit bestimmen.
>
> Ich habe ein uint16_t und will nun nur die unteren 3 Bits wissen.
> Wie mache ich das?

Indem du eine Maske benutzt, in der die unteren 3 Bits 1 sind und alle 
anderen 0.


  Ergebnis = Variable & 0x0007;

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.