Forum: PC-Programmierung Bit an Stelle x


von stefan (Gast)


Lesenswert?

hey zusammen...

wie bekomme ich den Wert eines Bits an der Stelle x? hat da irgendwer 
eine idee?

z.B.
0001001010101

Stelle 0 = 1
Stelle 1 = 0
Stelle 2 = 1
usw.

lg
stefan

von Sam .. (sam1994)


Lesenswert?

Das ergibt nicht 0 wenn die Stelle 1 ist, 0 wenn sie 0 ist:
1
wert & (1 << stelle)

Wenn wirklich nach 1/0 gefragt ist:
1
wert & (1 << stelle) ? 1 : 0

Bitmanipulation

von stefan (Gast)


Lesenswert?

hab auch von hinten begonnen :D

der rest funktioniert so, vielen dank!

von d'oh (Gast)


Lesenswert?

"1 & (wert >> stelle)" ergibt direkt den wert, ohne short-if

von Sam .. (sam1994)


Lesenswert?

d'oh schrieb:
> "1 & (wert >> stelle)" ergibt direkt den wert, ohne short-if

ist zwar kürzer in C dürfte jdeoch mehr Flash und CPU kosten.

von einfachasm (Gast)


Lesenswert?

Bei Intelprozessortypen gibt es seit dem 386er den Befehl BT. Man gibt 
die Position an, und der Wert wird ins Carryflag übertragen.

Oder man setzt ein paar And-Befehle und tests hintereinander.
0101
and
0001
----
0001
cmp xyz,1
jz
...

oder von links: nach links rotieren und gucken, ob carryflag gesetzt.
auf diese Weise könnte man nebenbei auch gleich nach ASCII konvertieren:
rcl ebx,1
adc Ausgabebyte,30h

von STK500-Besitzer (Gast)


Lesenswert?

d'oh schrieb:
> "1 & (wert >> stelle)" ergibt direkt den wert, ohne short-if

Diese "Abfrage" liefert nicht das Ergebnis "0" oder "1", sondern "0" und 
irgedwas verschieden von "0".

Wenn man der Reihe nach die die Stellen abfragen will, nimmt man eine 
Schleife in der eine Variable bei jedem Durchlauf verdoppelt wird 
(Linksschieben ist nichts anderes als ein Multiplikation mit 2; 
Rechtschieben eine Division).

Diese Variable vergleicht mal dann artihmetisch ("&", einfaches 
Undzeichen) mit der Quellvariablen.

von Karl H. (kbuchegg)


Lesenswert?

STK500-Besitzer schrieb:
> d'oh schrieb:
>> "1 & (wert >> stelle)" ergibt direkt den wert, ohne short-if
>
> Diese "Abfrage" liefert nicht das Ergebnis "0" oder "1", sondern "0" und
> irgedwas verschieden von "0".

Wie das?

(Das 1 & übersehen?)

von d'oh (Gast)


Lesenswert?

Samuel K. schrieb:
> d'oh schrieb:
>> "1 & (wert >> stelle)" ergibt direkt den wert, ohne short-if
>
> ist zwar kürzer in C dürfte jdeoch mehr Flash und CPU kosten.

9:          ergebnis = wert & (1 << stelle) ? 1 : 0;
8189        LDD       R24,Y+1        //Load $(wert)
812A        LDD       R18,Y+2        //Load $(stelle)
E090        LDI       R25,0x00       //Load zero for carry reset
C002        RJMP      PC+0x0003      //Enter loop
9595        ASR       R25            //Clear carry
9587        ROR       R24            //Rotate right $(wert)
952A        DEC       R18            //Decrement $(stelle)
F7E2        BRPL      PC-0x03        //Loop while $(stelle) >= 0
7081        ANDI      R24,0x01       //Mask LSB
838B        STD       Y+3,R24        //Store $(ergebnis)

9:          ergebnis = 1&(wert >> stelle);
8189        LDD       R24,Y+1        Load indirect with displacement
812A        LDD       R18,Y+2        Load indirect with displacement
E090        LDI       R25,0x00       Load immediate
C002        RJMP      PC+0x0003      Relative jump
9595        ASR       R25            Arithmetic shift right
9587        ROR       R24            Rotate right through carry
952A        DEC       R18            Decrement
F7E2        BRPL      PC-0x03        Branch if plus
7081        ANDI      R24,0x01       Logical AND with immediate
838B        STD       Y+3,R24        Store indirect with displacement

Hab's gerade mal auf 'nem xmega kompiliert. Es ist schlichtweg Jacke wie 
Hose, ob man es nun so oder so schreibt. Der Compiler ist pfiffig genug 
und optimiert beide Varianten. Das Ergebnis ist exakt das selbe, wobei 
meine Schreibweise eher die Vorgehensweise des Codes widergespiegelt :-p

von Sam .. (sam1994)


Lesenswert?

Pfiffig ist der Compiler nicht - das ist ja purer Schrott. Selbst mit 
konstanter Stelle produziert er aufgeblähten Code, obwohl 3 Befehle 
reichen würden. Ich würde es in Assembler so schreiben:
1
bst r24, stelle
2
clr r24
3
bld r24, 0

Folgendes in Assembler übersetzt geht ebenfalls in 3 Befehlen:
1
wert & (1 << stelle) ? 1 : 0
1
clr r24
2
sbrc r24, stelle
3
inc r24

von d'oh (Gast)


Lesenswert?

Wie du schon richtig sagst... Wenn die Stelle konstant ist, mag das 
stimmen. Wenn nicht, funktioniert dein Code nicht, da die Bitoperationen 
neben dem Register einen konstanten Bit Wert erwarten.

Und eigentlich wollte ich nur zum Ausdruck bringen, dass es egal ist 
wie man es in diesem Fall in C ausdrückt, das Endprodukt ist das 
selbe. Ob es nun per Hand im Assembler besser geht oder nicht sei 
mal dahingestellt.

^
|

Vergiss das! Ich hab mir nochmal die Mühe gemacht und einen Vergleich 
zwischen deinem und meinem Code gemacht, für den Fall, dass die Stelle 
konstant ist...
Mein Fazit: Gib dem Compiler lesbaren Code und er belohnt dich mit 
besserem Kompilat.

Und insgesamt finde ich schon, dass der Compiler einen guten Job macht 
und der Code ist auch bei konstanten Werten nicht aufgebläht. (Zumindet 
mit meinem Code) Für konstante Werte erzeugt er hier auch nur 2-4 
Instruktionen(Ohne den ld/st overhead) Für deine Schreibweise sieht der 
Code zum Teil so aus als sei die Stelle variabel mit zum Teil 3 Register 
Loads wie oben.
1
9:          ergebnis = 1&(wert >> 1);
2
LSR       R24            Logical shift right
3
ANDI      R24,0x01       Logical AND with immediate
4
9:          ergebnis = wert & (1 << 1) ? 1 : 0;
5
LSR       R25            Logical shift right
6
ROR       R24            Rotate right through carry
7
ANDI      R24,0x01       Logical AND with immediate
8
9
9:          ergebnis = 1&(wert >> 2);
10
LSR       R24            Logical shift right
11
LSR       R24            Logical shift right
12
ANDI      R24,0x01       Logical AND with immediate
13
9:          ergebnis = wert & (1 << 2) ? 1 : 0;
14
LSR       R25            Logical shift right
15
ROR       R24            Rotate right through carry
16
LSR       R25            Logical shift right
17
ROR       R24            Rotate right through carry
18
ANDI      R24,0x01       Logical AND with immediate
19
20
9:          ergebnis = 1&(wert >> 3);
21
LSR       R24            Logical shift right
22
LSR       R24            Logical shift right
23
LSR       R24            Logical shift right
24
ANDI      R24,0x01       Logical AND with immediate
25
9:          ergebnis = wert & (1 << 3) ? 1 : 0;
26
LSR       R25            Logical shift right
27
ROR       R24            Rotate right through carry
28
DEC       R18            Decrement
29
BRNE      PC-0x03        Branch if not equal
30
ANDI      R24,0x01       Logical AND with immediate
31
32
9:          ergebnis = 1&(wert >> 4);
33
SWAP      R24            Swap nibbles
34
ANDI      R24,0x01       Logical AND with immediate
35
9:          ergebnis = wert & (1 << 4) ? 1 : 0;
36
LSR       R25            Logical shift right
37
ROR       R24            Rotate right through carry
38
DEC       R18            Decrement
39
BRNE      PC-0x03        Branch if not equal
40
ANDI      R24,0x01       Logical AND with immediate
41
42
9:          ergebnis = 1&(wert >> 5);
43
SWAP      R24            Swap nibbles
44
LSR       R24            Logical shift right
45
ANDI      R24,0x01       Logical AND with immediate
46
9:          ergebnis = wert & (1 << 5) ? 1 : 0;
47
LSR       R25            Logical shift right
48
ROR       R24            Rotate right through carry
49
DEC       R18            Decrement
50
BRNE      PC-0x03        Branch if not equal
51
ANDI      R24,0x01       Logical AND with immediate
52
53
9:          ergebnis = 1&(wert >> 6);
54
SWAP      R24            Swap nibbles
55
LSR       R24            Logical shift right
56
LSR       R24            Logical shift right
57
ANDI      R24,0x01       Logical AND with immediate
58
9:          ergebnis = wert & (1 << 6) ? 1 : 0;
59
LSR       R25            Logical shift right
60
ROR       R24            Rotate right through carry
61
DEC       R18            Decrement
62
BRNE      PC-0x03        Branch if not equal
63
ANDI      R24,0x01       Logical AND with immediate
64
65
9:          ergebnis = 1&(wert >> 7);
66
ROL       R24            Rotate Left Through Carry
67
CLR       R24            Clear Register
68
ROL       R24            Rotate Left Through Carry
69
9:          ergebnis = wert & (1 << 7) ? 1 : 0;
70
ROL       R24            Rotate Left Through Carry
71
CLR       R24            Clear Register
72
ROL       R24            Rotate Left Through Carry

von written with vi on xmega running µclinux (Gast)


Lesenswert?

Samuel K. schrieb:
> ist zwar kürzer in C dürfte jdeoch mehr Flash ... kosten.

welche Version? 11?


Alles andere dürfte in diesem Forum wohl nicht passen, auch wenn die 
Diskussion erquickend ist.

von Sam .. (sam1994)


Lesenswert?

Was mich am Compiler stört ist, das variable schieben bei konstanter 
Stelle. Das kostet nämlich eine Menge CPU.

Ich finde die andi variante besser, da man bei konstanter Stelle nicht 
schieben muss. Wenn man in einer Schleife nacheinander Bits abfragen 
muss ist es sowieso besser die Bits rauszuschieben.

Ich denke man braucht fast nie die 1<<x Schleife.

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.