- fchao-Sinus-Wechselrichter AliExpress         
Seite 2 von 2 ErsteErste 12
Ergebnis 11 bis 14 von 14

Thema: Bits in einem Byte vertauschen

  1. #11
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    Anzeige

    Praxistest und DIY Projekte
    hmmm...

    was heisst denn elegent?

    Elegant und korrekt als Inline Asm:
    Code:
    static inline unsigned char 
    swap_2_4_asm (unsigned char a)
    {
    	unsigned char b;
    	
    	asm volatile ("bst %[a],2" "\n\t"
    	              "bld %[b],4" "\n\t"
    	              "bst %[a],4" "\n\t"
    	              "bld %[b],2"
    	              : [b] "=&r" (b) : [a] "r" (a), "0" (a));
    	              
    	return b;	              
    }
    
    uint8_t foo_asm (uint8_t b)
    {
        return swap_2_4_asm (b);
    }
    Bei Inline-Assembler ist unbedingt darauf zu achten, daß der Effekt auf die Maschine dem Compiler korrekt mitgeteilt wird!

    Das Ergebnis nur an einem Beispiel testen genügt nicht. Wenn sich das Programm ändert und der Compiler etwas anderen Code erzeugt, fliegen einem die obigen asm-Schnippsel um die Ohren (bzw. der AVR macht es).

    In C kann man es elegant über Bitfelder lösen, was leider von GCC momentan noch -- gelinde gesagt -- suboptimal übersetzt wird:

    Code:
    typedef union
    {
        struct 
        {
            unsigned b0 :1;
            unsigned b1 :1;
            unsigned b2 :1;
            unsigned b3 :1;
            unsigned b4 :1;
            unsigned b5 :1;
            unsigned b6 :1;
            unsigned b7 :1;
        };
        
        unsigned char val;
    } bit8_t;
    
    static inline unsigned char 
    swap_2_4_c (unsigned char a)
    {
        bit8_t xa = {.val = a};
        bit8_t xb = {.val = a};
        
        xb.b4 = xa.b2;
        xb.b2 = xa.b4;
        
        return xb.val;
    }    
    
    uint8_t foo_c (uint8_t b)
    {
        return swap_2_4_c (b);
    }
    Disclaimer: none. Sue me.

  2. #12
    Erfahrener Benutzer Roboter Experte Avatar von sternst
    Registriert seit
    07.07.2008
    Beiträge
    672
    fliegen einem die obigen asm-Schnippsel um die Ohren
    Kannst du bitte mal erläutern, inwieweit das meinen "Schnipsel" betrifft?
    MfG
    Stefan

  3. #13
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    Zitat Zitat von sternst
    Kannst du bitte mal erläutern, inwieweit das meinen "Schnipsel" betrifft?
    Dessen Beschreibung ist korrekt, allerdings sollte folgendes badacht werden:

    -- Das Register muss nicht in der Klasse "d" liegen, Klasse "r" genügt vollauf. Falls das Register zB in "l" lebt, würden sonst überflüssige Reloads nach "d" fällig.

    -- Wenn man das auf eine lokale Variable anwendet, ist der Code, den GCC zum Erzeugen der Adresse macht, oft mehr als der eigentliche Code des asm. Daher sollte wenn möglich Adressbildungen lokaler Variablen vermieden werden, insbesondere wenn man dichten, flotten Code haben möchte:

    Code:
    char c;
    char foo (char b)
    {
        char a = b;
        bitswp2_4 (&a);
    
        c = a;
    
        return b;
    }
    Das hab ich mal mit avr-gcc 4.4.0 übersetzt; ältere gcc-Versionen machen nicht unbedingt besser...

    Code:
    foo:
    	push r29
    	push r28
    	push __tmp_reg__
    	in r28,__SP_L__
    	in r29,__SP_H__
    /* prologue: function */
    /* frame size = 1 */
    	mov r25,r24
    /* #APP */
     ;  7 "swap.c" 1
    	mov __tmp_reg__, r25
    	bst r25,2
    	bld r25,4
    	bst __tmp_reg__,4
    	bld r25,2
    	
     ;  0 "" 2
    /* #NOAPP */
    	sts c,r25
    /* epilogue start */
    	pop __tmp_reg__
    	pop r28
    	pop r29
    	ret
    Um die Adresse einer lokalen Variablen nehmen zu können, muss diese im Frame (bzw. im Speicher, hier aufm Stack) angelegt werden. Von Maschinenregistern kann nämlich keine Adresse genommen werden.

    Teilweise gelingt es GCC, das wieder halbwegs optimal hinzubiegen, aber welch harte Nuss das ist, wird erst klar, wenn man ein bissl unter die Haube eines Compilers guckt...
    Disclaimer: none. Sue me.

  4. #14
    Erfahrener Benutzer Roboter Experte Avatar von sternst
    Registriert seit
    07.07.2008
    Beiträge
    672
    Das ist mir alles bekannt. Ich habe auch nie den Anspruch auf "optimale Lösung" erhoben, schließlich habe ich nur Freds Variante korrigiert.
    Ich wollte nur wissen, in welcher Hinsicht mir mein Code "um die Ohren fliegt".
    MfG
    Stefan

Seite 2 von 2 ErsteErste 12

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

LiFePO4 Speicher Test