2xBytes - Bitweise alternierend zusammenfügen

Gast #6439032
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.
#6439034
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;
}
#6439051
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
}
Gast #6439150
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
}
Gast #6439585
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
   }
(Firma: Funkenflug Industries) #6442285
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren