Forum: PC-Programmierung 2xBytes - Bitweise alternierend zusammenfügen


von superb (Gast)


Lesenswert?

Hallo zusammen,

hat jemand einen Tipp wie zwei Bytes bitweise-alternierend 
zusammengefügt werden können.

first Byte:  [a b c d e f g h]
second Byte: [1 2 3 4 5 6 7 8]

->   Word(16Bit): [a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8]

Danke.

von Faulpelz (Gast)


Lesenswert?

Hausaufgabe?
Oder wes ist der Zweck des Ganzen?

von Ben S. (bensch123)


Lesenswert?

1
uint16_t u16Result = 0;
2
uint8_t u8A = 0b10101010;
3
uint8_t u8B = 0b01010101;
4
5
for(uint8_t i = 0; i < 8; i++){
6
  if(u8A & (1<<i)) u16Result  |= (1<<(i*2));
7
  if(u8B & (1<<i)) u16Result  |= (1<<(i*2+1));
8
}

von vllt so? (Gast)


Lesenswert?

for i= 0 bis 7

Word(16Bit) = Word(16Bit) | ((firstByte>>(7-i))&1)
Word(16Bit) = Word(16Bit)<<1

Word(16Bit) = Word(16Bit) | ((secondByte>>(7-i))&1)
Word(16Bit) = Word(16Bit)<<1

EndFor

von Faulpelz (Gast)


Lesenswert?

So als Lösungsansatz (mein Assembler ist etwas eingestaubt).
Eine Schiebeoperation sorgt dafür, dass das rausgeschobene Bit im Carry 
landet. Dann kann man ein "AddWithCarry" mit 0 machen, und das Ergebnis 
entsprechend weiterschieben.
Das Ganze in einer kleinen Schleife.

von Ben S. (bensch123)


Lesenswert?

vllt so? schrieb:
> for i= 0 bis 7
>
> Word(16Bit) = Word(16Bit) | ((firstByte>>(7-i))&1)
> Word(16Bit) = Word(16Bit)<<1
>
> Word(16Bit) = Word(16Bit) | ((secondByte>>(7-i))&1)
> Word(16Bit) = Word(16Bit)<<1
>
> EndFor

uint16_t u16Result = 0;
uint8_t u8A = 0b10101010;
uint8_t u8B = 0b01010101;

for(uint8_t i = 0; i < 8; i++){
  u16Result |= u8A & 1;
  u8A >> 1;
  u16Result << 1;

  u16Result |= u8B & 1;
  u8B >> 1;
  u16Result << 1;
}

von Theor (Gast)


Lesenswert?

result = fb[7] sb[7] fb[6] sb[6] fb[5] sb[5] fb[4] sb[4] fb[3] sb[3] 
fb[2] sb[2] fb[1] sb[1] fb[0] sb[0];

[] ist der Bit-Indizierungsoperator.

von Ben S. (bensch123)


Lesenswert?

Ben S. schrieb:
> uint16_t u16Result = 0;
> uint8_t u8A = 0b10101010;
> uint8_t u8B = 0b01010101;
>
> for(uint8_t i = 0; i < 8; i++){
>   u16Result |= u8A & 1;
>   u8A >> 1;
>   u16Result << 1;
>
>   u16Result |= u8B & 1;
>   u8B >> 1;
>   u16Result << 1;
> }

Fehler, dies getestet:
1
uint16_t combine (uint8_t u8A, uint8_t u8B) {
2
  uint16_t u16Result = 0;
3
4
  for (uint8_t i = 0; i < 8; i++) {
5
    u16Result |= u8A & 1;
6
    u8A >>= 1;
7
    u16Result <<= 1;
8
9
    u16Result |= u8B & 1;
10
    u8B >>= 1;
11
    u16Result <<= 1;
12
  }
13
14
  return u16Result;
15
}

von superb (Gast)


Lesenswert?

Alles klar.
Damit kann ich etwas anfangen.

Mir ging es primär um die Logik.
Programmieren müsste ich das in SCL (SPS).

Danke.

von Caligulaminus (Gast)


Lesenswert?

Ohne Schleife:
1
int16_t shuffle16(std::uint8_t a, std::uint8_t b)
2
{
3
  uint16_t val = static_cast<uint16_t>(a) << 8 | b;
4
  uint16_t mask;
5
  mask = (val ^ (val >> 4)) & 0x00f0;
6
  val = val ^ mask ^ (mask << 4);
7
  mask = (val ^ (val >> 2)) & 0x0c0c;
8
  val = val ^ mask ^ (mask << 2);
9
  mask = (val ^ (val >> 1)) & 0x2222;
10
  val = val ^ mask ^ (mask << 1);
11
12
  return val;
13
}

von Ben S. (bensch123)


Lesenswert?

Caligulaminus schrieb:
> Ohne Schleife:

Auch schön, jedoch sollte man manchmal eine lesbare Version vorziehen. 
Zumindest finde ich deine Lösung nicht intuitiv - ist aber nur meine 
Meinung.

von voll der google checker (Gast)


Lesenswert?

Ben S. schrieb:
> uint16_t combine (uint8_t u8A, uint8_t u8B) {
>   uint16_t u16Result = 0;
>
>   for (uint8_t i = 0; i < 8; i++) {
>     u16Result |= u8A & 1;
>     u8A >>= 1;
>     u16Result <<= 1;
>
>     u16Result |= u8B & 1;
>     u8B >>= 1;
>     u16Result <<= 1;
>   }
>
>   return u16Result;
> }

Die Schieberei am Ende liefert falsches Ergebnis.
1
   for (uint8_t i = 0; i < 8; i++) {                                    
2
      u16Result <<= 1;                                                  
3
      u16Result |= u8A & 1;                                             
4
      u8A >>= 1;  
5
                                                      
6
      u16Result <<= 1;                                                                                                           
7
      u16Result |= u8B & 1;                                             
8
      u8B >>= 1;                                                        
9
   }

von Ben B. (Firma: Funkenflug Industries) (stromkraft)


Lesenswert?

In Assembler würde ich das angesichts heutiger Prozessoren
"Speedcode-Style" schreiben, also 32 einfache Bitshifts
über Carry, fertig. Vielleicht nicht ganz so elegant wie mit
einer Schleife, aber moderne Prozessoren mit ihren großen
Caches und Optimierungen dürften das in wenigen Takten
erledigt haben und die paar Byte mehr Speicherplatzbedarf
fallen heute nicht mehr auf.

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.