bit invertieren

Moderator (Firma: Titel) Persönliche Seite #2254274
Lesenswert?

hugo schrieb:
> Wie kann man am besten so "mal eben" ein Bit invertieren, um es so an
> einem Port auszugeben?!
> Also aus 11101010 mach 01010111
Das ist ein invertiertes BYTE... :-o

Und das gabs schon oft hier im Forum. Die Suche wird dir helfen...
http://www.mikrocontroller.net/search?query=Byte+spiegeln&forums[]=1&forums[]=2

EDIT: Mist, Fenster zu lang offen... :-/
Moderator (Firma: Titel) Persönliche Seite #2254475
Lesenswert?

J.-u. G. schrieb:
> Offensichtlich weiß er selbst nicht was er will und weiß auch nicht was
> ein Bit und was ein Byte ist.
Das geht offenbar vielen so, die das nicht wissen... ;-)
Nochmal der Link zur Suche, da sind auch ein paar solcher Kandidaten:
> Lothar Miller schrieb:
>> Die Suche wird dir helfen...
>> http://www.mikrocontroller.net/search?query=Byte+spiegeln

Und weil er es selbst nicht weiß, was er will, es aber beschreiben kann, 
gilt die Regel:
1
Es gibt 2 Arten von Menschen:
2
1. die, die auf der Basis unzureichender Information extrapolieren können
Gast #2255756
Lesenswert?

Folgender Code auch recht effizient compiliert...
1
#define M1  (uint8_t)0x01
2
#define M2  (uint8_t)0x02
3
#define M3  (uint8_t)0x04
4
#define M4  (uint8_t)0x08
5
#define M5  (uint8_t)0x10
6
#define M6  (uint8_t)0x20
7
#define M7  (uint8_t)0x40
8
#define M8  (uint8_t)0x80
9

10
uint8_t rotate(uint8_t MyVal)
11
{
12
  uint8_t NewVal=0;
13
  if (MyVal & M1) NewVal |= M8;
14
  if (MyVal & M2) NewVal |= M7;
15
  if (MyVal & M3) NewVal |= M6;
16
  if (MyVal & M4) NewVal |= M5;
17
  if (MyVal & M5) NewVal |= M4;
18
  if (MyVal & M6) NewVal |= M3;
19
  if (MyVal & M7) NewVal |= M2;
20
  if (MyVal & M8) NewVal |= M1;
21
  return NewVal;
22
}
Moderator Persönliche Seite #2255796
Lesenswert?

Peter schrieb:
> Folgender Code auch recht effizient compiliert...

Stimmt! Obwohl er recht lang aussieht, sind es nur 178 Byte erzeugter 
Code beim avr-gcc - inkl. leerer main-Funktion:

Program:     178 bytes (1.1% Full)
Data:          0 bytes (0.0% Full)

Da habe ich das mal eben mit einer Tabelle ausprobiert:
1
uint8_t
2
bitsreverse (uint8_t val)
3
{
4
    //                      0000  1000  0100  1100  0010  1010  0110  1110  0001  1001  0101  1101  0011  1011  0111  1111
5
    uint8_t reverse[16] = { 0x00, 0x08, 0x04, 0x0C, 0x02, 0x0A, 0x06, 0x0E, 0x01, 0x09, 0x05, 0x0D, 0x03, 0x0B, 0x07, 0x0F };
6
    return (reverse[val & 0x0F] << 4) | reverse[val >> 4];
7
}

Ergebnis:

Program:     266 bytes (1.6% Full)
Data:         16 bytes (1.6% Full)

Das Programm "sieht" zwar kürzer aus, kostet aber doch einiges mehr an 
Speicherplatz...

Zuallerletzt habe ich Volkers Version getestet (mit kleinen 
Modifikationen, z.B. int -> uint8_t):
1
uint8_t
2
bitsreverse (uint8_t in)
3
{
4
    uint8_t out = 0;
5
    uint8_t loop;
6

7
    for (loop = 0; loop < 8; loop++)
8
    {
9
       if (in & 0x01)
10
       {
11
           out |= 0x01;
12
       }
13
       in  = in >> 1;
14
       out = out << 1;
15
    }
16
    return (out);
17
}

Ergebnis:

Program:     162 bytes (1.0% Full)
Data:          0 bytes (0.0% Full)

Damit liegt Volkers Version derzeit an der Spitze, was die Sparsamkeit 
an Speicherplatz angeht.
Moderator Persönliche Seite #2255820
Lesenswert?

Beim Austesten stellte ich fest, dass Volkers Version einen Fehler hat. 
Es fehlte das unterste Bit im Ergebnis.

Hier die korrigierte Version:
1
uint8_t
2
bitsreverse (uint8_t in)
3
{
4
    uint8_t out = 0;
5
    uint8_t loop;
6

7
    for (loop = 0; loop < 8; loop++)
8
    {
9
       out <<= 1;
10

11
       if (in & 0x01)
12
       {
13
           out |= 0x01;
14
       }
15

16
       in  >>= 1;
17
    }
18
    return (out);
19
}

Die Zeile "out <<= 1" musste lediglich vor das if-Statment gezogen 
werden.

Es bleibt aber bei 162 Bytes an Code.
Moderator (Firma: Titel) Persönliche Seite #2255893
Lesenswert?

Hier mal ein Zwischenstand. Der Speicherbedarf wurde ermittelt, indem 
vorneweg alles mit mirror auskommentiert wurde, und danach der 
Speicherplatzzuwachs festgestellt wurde (Atmega32, -Os, avr-gcc 4.3.2):
1
#include <avr/io.h>
2

3
volatile uint8_t cnt;
4

5
unsigned char mirror( unsigned char a ) // 90 Bytes
6
{
7
  a = ((a >> 4) & 0x0F) | ((a << 4) & 0xF0);
8
  a = ((a >> 2) & 0x33) | ((a << 2) & 0xCC);
9
  a = ((a >> 1) & 0x55) | ((a << 1) & 0xAA);
10
  return a;
11
}
12

13

14
#define M1  (uint8_t)0x01
15
#define M2  (uint8_t)0x02
16
#define M3  (uint8_t)0x04
17
#define M4  (uint8_t)0x08
18
#define M5  (uint8_t)0x10
19
#define M6  (uint8_t)0x20
20
#define M7  (uint8_t)0x40
21
#define M8  (uint8_t)0x80
22

23
unsigned char mirror( unsigned char MyVal ) // 52 Bytes
24
{
25
  uint8_t NewVal=0;
26
  if (MyVal & M1) NewVal |= M8;
27
  if (MyVal & M2) NewVal |= M7;
28
  if (MyVal & M3) NewVal |= M6;
29
  if (MyVal & M4) NewVal |= M5;
30
  if (MyVal & M5) NewVal |= M4;
31
  if (MyVal & M6) NewVal |= M3;
32
  if (MyVal & M7) NewVal |= M2;
33
  if (MyVal & M8) NewVal |= M1;
34
  return NewVal;
35
}
36

37
unsigned char mirror( unsigned char in ) // 52 Bytes
38
{
39
    uint8_t out = 0;
40
    uint8_t loop;
41
    for (loop = 0; loop < 8; loop++) {
42
       out <<= 1;
43
       if (in & 0x01) out |= 0x01;
44
       in  >>= 1;
45
    }
46
    return out;
47
}
48

49
uint8_t mirror (uint8_t val) // 208 Bytes
50
{
51
    uint8_t out;
52
    //                      0000  1000  0100  1100  0010  1010  0110  1110  0001  1001  0101  1101  0011  1011  0111  1111
53
    uint8_t reverse[16] = { 0x00, 0x88, 0x44, 0xCC, 0x22, 0xAA, 0x66, 0xEE, 0x11, 0x99, 0x55, 0xDD, 0x33, 0xBB, 0x77, 0xFF };
54
    out  = reverse[val&0x0F] & 0xF0;
55
    out |= reverse[val>>4]   & 0x0F;
56
    return out;
57
}
58

59
/*****************************************************************/
60
int main (void)
61
{
62
    while (1)
63
    {
64
      cnt = cnt+1;
65
      cnt = mirror(cnt);
66
    } 
67
}

Komisch schrieb:
> Es geht doch nichts über einen passenden Titel. Warum sagt er dann nicht
> gleich "Byte spiegeln" oder Bitfolge invertieren.
Vielleicht, weil ihm der Begriff nicht geläufig war...
Moderator Persönliche Seite #2255895
Lesenswert?

Michael K. schrieb:
> Und noch ne Funktion:
>
>
1
> uint8_t ByteMirror (uint8_t n)
2
> {
3
>   n = ((n >> 1) & 0x55) | ((n << 1) & 0xaa);
4
>   n = ((n >> 2) & 0x33) | ((n << 2) & 0xcc);
5
>   n = ((n >> 4) & 0x0f) | ((n << 4) & 0xf0);
6
>   return n;
7
> }
8
>

Stimmt, die habe ich hier auf µC.net auch schon öfters rumschwirren 
sehen.

Ergebnis:

Program:     180 bytes (1.1% Full)
Data:          0 bytes (0.0% Full)

Das ist dann der 3. Platz... aber knapp :-)
Moderator Persönliche Seite #2255906
Lesenswert?

Lothar Miller schrieb:
> Lothar Miller schrieb:
>> uint8_t mirror (uint8_t val) // 208 Bytes
> Frank M. schrieb:
>> Program:     180 bytes (1.1% Full)
> Ich muß mal meinen Compiler updaten... ;-)

Da ist ein leeres main() auch mit drin. Das halte ich für legitim, da 
der Compiler auch bei Nicht-Aufruf die Funktionen NICHT wegoptimieren 
kann, da sie nicht als static deklariert sind. Wie ist das bei Dir? 
Zählst Du Deine (aufwendigere) main-Funktion mit?

EDIT: Bei mir frisst die leere main-Funktion 138 Byte, die müsste man 
also von meinen Werten abziehen. Dann sieht der 4.3.3er Compiler um 
einiges besser aus als Dein 4.3.2er.
Gast #2256714
Lesenswert?

Das ist ja echt der Wahnsinn xD
Ihr ward echt seeehr krass...
Naja das ganze ist so: Ich hab ein Display und das hängt direkt an einem 
Port. Aus Layout technischen Gründen müsste ich ALLE Leitungen kreuzen, 
was natürlich ziemlich dumm ist. Jetzt habe ich überlegt einfach immer 
das Byte zu spiegeln, damit ich es so übertragen kann. Ich denke aber 
bei einem Grafik LCD ist das totaler Quatsch, da der AVR ja 2/3 seiner 
Zeit nur damit verbringt Daten zu spiegeln. Da er später noch andere 
Dinger erledigen soll wäre das also dumm.
Nun bin ich am Überlegen einen SMD-Stecker zu nehmen, dann kann ich die 
Leiterbahnen von oben anfahren (kann Zuhause nur einseitige Platinen mit 
min. 8mil Leiterbahnen).

Aber ich finde diesen Thread echt klasse! Wenn wir nun vielleicht alles 
zusammenstellen und irgendwo festhalten wär das schonmal toll!

Danke euch!
Gast #2256850
Lesenswert?

Anbei die reine Codegrösse für die Funktionen und die Anzahl CPU-Zyklen 
für die Verarbeitung (Function Call bis Return)

Bei mirror4() habe ich den Array auf static gesetzt, dann werden dessen 
Werte nur einmal im StartUpCode initialisiert und nicht bei jedem 
Funktions-Aufruf. (Codesize und CPU-Zyklen für diese Initialisierung 
sind nicht dabei)
1
#include <avr/io.h>
2

3
volatile uint8_t cnt;
4

5
unsigned char mirror1(unsigned char a ) // 42 Bytes, 28 Cycles
6
{
7
  a = ((a >> 4) & 0x0F) | ((a << 4) & 0xF0);
8
  a = ((a >> 2) & 0x33) | ((a << 2) & 0xCC);
9
  a = ((a >> 1) & 0x55) | ((a << 1) & 0xAA);
10
  return a;
11
}
12

13

14
#define M1  (uint8_t)0x01
15
#define M2  (uint8_t)0x02
16
#define M3  (uint8_t)0x04
17
#define M4  (uint8_t)0x08
18
#define M5  (uint8_t)0x10
19
#define M6  (uint8_t)0x20
20
#define M7  (uint8_t)0x40
21
#define M8  (uint8_t)0x80
22

23
unsigned char mirror2(unsigned char MyVal ) // 40 Bytes, 27 Cycles
24
{
25
  uint8_t NewVal=0;
26
  if (MyVal & M1) NewVal |= M8;
27
  if (MyVal & M2) NewVal |= M7;
28
  if (MyVal & M3) NewVal |= M6;
29
  if (MyVal & M4) NewVal |= M5;
30
  if (MyVal & M5) NewVal |= M4;
31
  if (MyVal & M6) NewVal |= M3;
32
  if (MyVal & M7) NewVal |= M2;
33
  if (MyVal & M8) NewVal |= M1;
34
  return NewVal;
35
}
36

37
unsigned char mirror3(unsigned char in ) // 24 Bytes, 81 Cycles
38
{
39
    uint8_t out = 0;
40
    uint8_t loop;
41
    for (loop = 0; loop < 8; loop++) {
42
       out <<= 1;
43
       if (in & 0x01) out |= 0x01;
44
       in  >>= 1;
45
    }
46
    return out;
47
}
48

49

50
uint8_t mirror4(uint8_t val)  // 34 Bytes, 26 Cycles
51
{
52
    //                             0000  1000  0100  1100  0010  1010  0110  1110  0001  1001  0101  1101  0011  1011  0111  1111
53
    static uint8_t reverse[16] = { 0x00, 0x88, 0x44, 0xCC, 0x22, 0xAA, 0x66, 0xEE, 0x11, 0x99, 0x55, 0xDD, 0x33, 0xBB, 0x77, 0xFF };
54
    uint8_t out;
55
    out  = reverse[val&0x0F] & 0xF0;
56
    out |= reverse[val>>4]   & 0x0F;
57
    return out;
58
}
59

60
/*****************************************************************/
61
int main (void)
62
{
63
    while (1)
64
    {
65
      //------------------------------
66
      cnt = 0xA5;
67
      cnt = mirror1(cnt);
68
      //------------------------------
69
      cnt = 0xA5;
70
      cnt = mirror2(cnt);
71
      //------------------------------
72
      cnt = 0xA5;
73
      cnt = mirror3(cnt);
74
      //------------------------------
75
      cnt = 0xA5;
76
      cnt = mirror4(cnt);
77
      //------------------------------
78
    }
79
}
Moderator Persönliche Seite #2256969
Lesenswert?

Peter schrieb:
> Anbei die reine Codegrösse für die Funktionen und die Anzahl CPU-Zyklen
> für die Verarbeitung (Function Call bis Return)

Welche avr-gcc-Version? Welche Optimierungsstufe? Wie wir gestern 
gesehen haben, gibt es allein bei der Version erhebliche Unterschiede im 
Ergebnis.

> Bei mirror4() habe ich den Array auf static gesetzt, dann werden dessen
> Werte nur einmal im StartUpCode initialisiert und nicht bei jedem
> Funktions-Aufruf.

Ohja, das hatte ich doch glatt übersehen. Damit liegt mirror4 mit der 
Ausführungszeit an erster Stelle und vom Speicherplatz immerhin noch an 
2. Stelle.

Interessant, dass mirror3() als kleinste Funktion auch die langsamste 
ist.

Danke für die Aufstellung.

Gruß,

Frank
Gast #2257086
Lesenswert?

hugo schrieb:
> Also ich will das Byte natürlich Spiegeln. Und das am besten in C.

Na, wenn nicht ausschließlich C, dann hat auch noch 'ne Bascom-Version 
Platz ;D
1
$Regfile = "m32def.dat"
2
$Crystal = 8000000
3
$hwstack = 32
4
$swstack = 32
5
$framesize = 32
6

7
Dim Var_In As Byte , Var_Out As Byte
8

9
Var_In = &B11011001
10
Print Bin(Var_In)
11

12
  !LDS  R16, {Var_In}
13
  !BST  R16, 0
14
  !BLD  R17, 7
15
  !BST  R16, 1
16
  !BLD  R17, 6
17
  !BST  R16, 2
18
  !BLD  R17, 5
19
  !BST  R16, 3
20
  !BLD  R17, 4
21
  !BST  R16, 4
22
  !BLD  R17, 3
23
  !BST  R16, 5
24
  !BLD  R17, 2
25
  !BST  R16, 6
26
  !BLD  R17, 1
27
  !BST  R16, 7
28
  !BLD  R17, 0
29
  !STS  {Var_Out}, R17
30

31
Print Bin(Var_Out)
32

33
End

40Bytes, 20 Cycles.
Moderator (Firma: Titel) Persönliche Seite #2257113
Lesenswert?

MWS schrieb:
> dann hat auch noch 'ne Bascom-Version Platz ;D
>   !LDS  R16, {Var_In}
>   !BST  R16, 0
Naja. Ich würde sagen, das fällt fast schon unter "Assembler-Doping"...

> 40Bytes, 20 Cycles.
Das ist jetzt aber noch keine richtige Unterroutine...
>> Peter schrieb:
>>> Anbei die reine Codegrösse für die Funktionen und die Anzahl CPU-Zyklen
>>> für die Verarbeitung (Function Call bis Return)
#2257145
Lesenswert?

hugo schrieb:
> Das ist ja echt der Wahnsinn xD
> Ihr ward echt seeehr krass...
> Naja das ganze ist so: Ich hab ein Display und das hängt direkt an einem
> Port. Aus Layout technischen Gründen müsste ich ALLE Leitungen kreuzen,
> was natürlich ziemlich dumm ist. Jetzt habe ich überlegt einfach immer
> das Byte zu spiegeln, damit ich es so übertragen kann. Ich denke aber
> bei einem Grafik LCD ist das totaler Quatsch, da der AVR ja 2/3 seiner
> Zeit nur damit verbringt Daten zu spiegeln. Da er später noch andere
> Dinger erledigen soll wäre das also dumm.

Bei der Initialisierung des GLCD kann man auch entsprechende Konstante 
nehmen (und das kommentieren), die Fonts zur Textausgabe lassen sich 
auch vorher spiegeln/passend generieren und die Routinen zum 
Pixel-Setzen/Linien-Zeichnen kann man auch passend schreiben...
Gast #2257179
Lesenswert?

Lothar Miller schrieb:
> Naja. Ich würde sagen, das fällt fast schon unter "Assembler-Doping"...

Da hast Du natürlich recht, da sich aber Assembler bei Bascom äußerst 
problemlos in Basic-Code einbetten lässt, so ist das legitim.

> Das ist jetzt aber noch keine richtige Unterroutine...

Das sind sie im C-Beispiel auch nicht. Nur mirror2 wird über einen CALL 
aufgerufen, alles andere wird vom Compiler Inline eingebaut (mit -Os).
Und zwar wiederholt, zweimal mirror1 aufgerufen wird auch zweimal als 
Inline compiliert. Wahrscheinlich weil bei der kleinen Codegröße der 
Funktion der Overhead unrentabel ist.

>>>> Anbei die reine Codegrösse für die Funktionen und die Anzahl CPU-Zyklen
>>>> für die Verarbeitung (Function Call bis Return)

Eine Bascom-Sub, die auch tatsächlich als Sub eingebunden ist, benötigt 
dann 39 Cycles, liegt daran, daß die Variablenzeiger auf den Frame 
gehen/von dort geholt werden müssen.
Gast #2257231
Lesenswert?

Also die Bascom Variante von MWS (Gast) gefällt mir doch sehr.
Wie könnte ich das auf C übertragen?
Geht das in C überhaupt, Werte an Assembler zu übergeben und 
zurückzubekommen?
Gast #2257274
Lesenswert?

Räuber Hotzenplotz schrieb:
> Wie könnte ich das auf C übertragen?

Sollte per Inline Assembler gehen, ist aber im Vergleich zu dem 
Gezeigten relativ kompliziert, der C-Compiler hat's nicht gern, wenn man 
sich einmischt.

Vorteil meiner Version ist die völlig freie Bitzuweisung, somit lassen 
sich einfach die Anschlüsse intern "umverdrahten".

So entstand dieser Codeteil auch, wurde in ein Lib eingebunden um 
entsprechend einem anderes Platinenlayout für ein Display mit einem 
I2C-Expander PCF8574 die Pins frei zuweisen zu können.
Moderator (Firma: Titel) Persönliche Seite #2257463
Lesenswert?

MWS schrieb:
> Das sind sie im C-Beispiel auch nicht. Nur mirror2 wird über einen CALL
> aufgerufen, alles andere wird vom Compiler Inline eingebaut (mit -Os).
Das schon. Aber die Aufrufparameter sind frei wählbar.

> Eine Bascom-Sub, die auch tatsächlich als Sub eingebunden ist, benötigt
> dann 39 Cycles
Liegt damit annähernd gleichauf zur Lösung mirror2, wo ja auch beliebige 
Bits zugeordnet werden könnten.
Gast #2257565
Lesenswert?

Lothar Miller schrieb:
> Das schon. Aber die Aufrufparameter sind frei wählbar.

Wenn man Speed braucht, dann ist's egal, ob die Aufrufparameter frei 
wählbar sind. Speziell für den Fall eine Pinbelegung "umzubiegen" wird 
dieser Codeblock in die ausgebende Funktion eingebaut, da brauch' ich 
keinen Call auf eine Funktion machen, und dann sind wir wieder bei 20 
Takten. Da beißt die Maus keinen Faden ab.
Gast #2257661
Lesenswert?

Um auch das noch zu beantworten:

Räuber Hotzenplotz schrieb:
> Wie könnte ich das auf C übertragen?
> Geht das in C überhaupt, Werte an Assembler zu übergeben und
> zurückzubekommen?
1
unsigned char mirror5(unsigned char in ) // 21 Takte
2
{
3
   unsigned char out;
4

5
   asm volatile ( 
6
    "bst  %[in_reg], 0           \n\t"    
7
    "bld  %[out_reg],7           \n\t"    
8
    "bst  %[in_reg], 1           \n\t"    
9
    "bld  %[out_reg],6           \n\t"    
10
    "bst  %[in_reg], 2           \n\t"    
11
    "bld  %[out_reg],5           \n\t"    
12
    "bst  %[in_reg], 3           \n\t"    
13
    "bld  %[out_reg],4           \n\t"    
14
    "bst  %[in_reg], 4           \n\t"    
15
    "bld  %[out_reg],3           \n\t"    
16
    "bst  %[in_reg], 5           \n\t"    
17
    "bld  %[out_reg],2           \n\t"    
18
    "bst  %[in_reg], 6           \n\t"    
19
    "bld  %[out_reg],1           \n\t"    
20
    "bst  %[in_reg], 7           \n\t"    
21
    "bld  %[out_reg],0           \n\t"    
22
         : [out_reg] "=&r" (out), [in_reg] "+r" (in)
23
   );
24
   return out;
25
}
Gast #2258722
Lesenswert?

@MWS (Gast):
Ganz vielen Dank für die Mühe!   :-)
: [out_reg] "=&r" (out), [in_reg] "+r" (in)
verstehe ich nicht so ganz (bin Anfänger in C )
Werde es am Montag testen, wenn ich wieder in der "Firma" bin ;-)
Hoffentlich geht das mit AVRStudio4 und WINAVR...
Ich wär so froh   :-)
Gast #2258730
Lesenswert?

Räuber Hotzenplotz schrieb:
> : [out_reg] "=&r" (out), [in_reg] "+r" (in)
> verstehe ich nicht so ganz

Nennt sich "clobber list". Ich fand's interessant wie's dem Compiler 
beizubringen ist, mach' normalerweise nichts in C-asm. Du kannst 
übrigens auch mirror2 nehmen, da wird sehr schöner und kurzer Code 
erzeugt. Funktional ist's gleich.
#2259654
Lesenswert?

Hallo Räuber, :-)

ich habs mal kurz für Dich getestet, damit Du am Montag beruhigt in die 
Firma fahren kannst:
1
unsigned char mirror5(unsigned char);  // Prototyp
2

3
int main (void)
4
{
5
  mirror5 (234);
6
}
7

8

9
unsigned char mirror5(unsigned char in ) // 21 Takte
10
{
11
   unsigned char out;
12

13
   asm volatile ( 
14
    "bst  %[in_reg], 0           \n\t"    
15
    "bld  %[out_reg],7           \n\t"    
16
    "bst  %[in_reg], 1           \n\t"    
17
    "bld  %[out_reg],6           \n\t"    
18
    "bst  %[in_reg], 2           \n\t"    
19
    "bld  %[out_reg],5           \n\t"    
20
    "bst  %[in_reg], 3           \n\t"    
21
    "bld  %[out_reg],4           \n\t"    
22
    "bst  %[in_reg], 4           \n\t"    
23
    "bld  %[out_reg],3           \n\t"    
24
    "bst  %[in_reg], 5           \n\t"    
25
    "bld  %[out_reg],2           \n\t"    
26
    "bst  %[in_reg], 6           \n\t"    
27
    "bld  %[out_reg],1           \n\t"    
28
    "bst  %[in_reg], 7           \n\t"    
29
    "bld  %[out_reg],0           \n\t"    
30
         : [out_reg] "=&r" (out), [in_reg] "+r" (in)
31
   );
32
   return out;
33
}

Getestet mit AVR-Studio 4.18 (Build 716) / Amtel 8515 Simulator, lässt 
sich einwandfrei compilieren!


Gruß

Markus
Persönliche Seite #2259672
Lesenswert?

Und warum Inline-Assembler???
1
#include <stdint.h>
2

3
uint8_t swap (uint8_t a)
4
{
5
    uint8_t c = a >> 7;
6
    
7
    if (a & (1 << 6))  c |= 1 << 1;
8
    if (a & (1 << 5))  c |= 1 << 2;
9
    if (a & (1 << 4))  c |= 1 << 3;
10
    if (a & (1 << 3))  c |= 1 << 4;
11
    if (a & (1 << 2))  c |= 1 << 5;
12
    if (a & (1 << 1))  c |= 1 << 6;
13
    if (a & (1 << 0))  c |= 1 << 7;
14
    return c;
15
}

Belegt nur 2 Register, das Input-Register bleibt erhalten und braucht 19 
Ticks + RET (deviceabhängig), hier avr-gcc 4.6.1:
1
swap:
2
  mov r25,r24
3
  rol r25
4
  clr r25
5
  rol r25
6
  sbrc r24,6
7
  ori r25,lo8(2)
8
  sbrc r24,5
9
  ori r25,lo8(4)
10
  sbrc r24,4
11
  ori r25,lo8(8)
12
  sbrc r24,3
13
  ori r25,lo8(16)
14
  sbrc r24,2
15
  ori r25,lo8(32)
16
  sbrc r24,1
17
  ori r25,lo8(64)
18
  sbrc r24,0
19
  ori r25,lo8(-128)
20
  mov r24,r25
21
  ret

In Assembler geht auch
1
LSL src  $  ROR dest
2
LSL src  $  ROR dest
3
LSL src  $  ROR dest
4
LSL src  $  ROR dest
5
LSL src  $  ROR dest
6
LSL src  $  ROR dest
7
LSL src  $  ROR dest
8
LSL src  $  ROR dest

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