Bit im Register setzten ohne andere Bits zuverändern.

Gast #4668039
Lesenswert?

Hey Forum

Ich hab am nächstes Schuljahr Programmierung in c auf den Stundenplan an 
ucs und wollte mich schonmal etwas ein arbeiten. Und muss jetzt mal eine 
ganz doofe Frage stelle. Wie ändere ich Bits in einem Register ohne 
andere zu ändern also aus ein bit von 1 auf 0 oder von 0 auf 1 aber die 
andern sollen unverändert bleiben.
Gast #4668054
Lesenswert?

Hab mir den Beitrag mal durch Gelesen und hab mal 2 Verständnis fragen

Wenn ich ein Port habe nennen wir ihn mal A mit den Wert 0b0000

Jetzt schreibe ich

A|= (1<<1) | (1<<4);

Ist das, dass selbe wie

A|= (1<<1);
A|= (1<<4);

Dann hat A den Wert 0b1001?

Wenn ich jetzt


A&= (1<<1) & (1<<4);

Setzte ist A=0b0000 ?
#4668061
Lesenswert?

Wie bereits gesagt: Beschäftige Dich mit binären Zahlen.

A ist nur zufällig gleich 0

(1<<1) & (1<<4);

ist 0

A &= 0 ist Null.

Du hattest aber den Sonderwunsch: "Wie ändere ich Bits in einem Register 
ohne andere zu ändern"

Das stimmt aber nicht.

Ist A vorher 1101, so ist A &= 0 ebenfalls 0.
#4668069
Lesenswert?

Vorsicht bissiger Hund:
(1<<1) & (1<<4) ist Null

0000.0010    0000.0010
    &            |
0001.0000    0001.0000
    =            =
0000.0000    0001.0010


0000.0000    0001.0010
    !            !
1111.1111    1110.1101


0001.0010    0001.0010
    &            &
1111.1111    1110.1101
    =            =
0001.0010    0000.0000

oder so

TO hier kannst Du auch "sehen" warum etwas binäre Zahlen nicht schaden 
können.

A guats Nächtlie
Gast #4668119
Lesenswert?

avr schrieb:
> Auweia. Bitte nicht die logische mit der bitweisen Negation verwecheln.
> Richtig wäre hier '~' statt '!'.

Autsch! Sorry und danke!
Meine Muttersprache ist Pascal.
Da Schreibt man einfach Not
und der Compiler ist schlau genug zu erkennen ob binär oder logisch.
Bei C habe ich immer wieder Probleme.

MfG
Gast #4668122
Lesenswert?

wieder ein sehr schönes beispiel für die C hater Seite :-)
Die ich übrigens super finde, auch wenn man C lernen will!! da man 
versucht die Beispiele zu verstehen auch wenn manche Flach sind, so sind 
die für Anfänger supe, da man sieht ob man darauf reingefallen wäre..
Zeigt aber auch wieder die Vorteile von Pascal...!
Gast #4668143
Lesenswert?

Ok mit der 0 war ein Flüchtigkeitsfehler. Natürlich meinte ich 1<<0 und 
1<<3.

Zu der atomaren Sache mal ne frage. Wenn ich im Register A die Bits 0-7 
mit den Buchstaben a-h versehe mit #define

Muss ich beim zuweisen der Bits dann immer das Register mit angeben, 
oder weiß der Compiler automatisch das es sich bei b immer um das 1. bit 
aus Register A handelt?

Dann könnte man doch, wenn man zur ausgangsfrage zurückkehrt einfach 
schreiben

b=1 und A hat den Wert 0b00000010 = dez 2

Und dann bei b=0 hat A den Wert 0
Gast #4668180
Lesenswert?

also probier gerade mit den bit Operationen etwas rum jetzt steh ich 
gerade vor einem Problem und find nicht die richtige Operation.

ich hab in A= entwerder 0b001 oder 0b011 stehen

jetzt will ich sicher gehen das dort egal welcher zustand von den beiden 
gegeben ist in A= 0b011 steht aber ich find nicht die richtige 
Operation.
#4668183
Lesenswert?

Anfänger schrieb:
> Zu der atomaren Sache mal ne frage. Wenn ich im Register A die Bits 0-7
> mit den Buchstaben a-h versehe mit #define
>
> Muss ich beim zuweisen der Bits dann immer das Register mit angeben,
> oder weiß der Compiler automatisch das es sich bei b immer um das 1. bit
> aus Register A handelt?

Nein, sowas geht (in C) nur, wenn die Hardware es kann und der Compiler 
entsprechende Erweiterungen hat.
8051 z.B. hat P0 als einen 8-Bit-Port und P0_0..P0_7 als mit speziellen 
Befehlen direkt addressierbare Bits, die HW-seitig die Bits des P0 sind. 
Typische 8051-C-Compiler kennen den Datentyp __bit und erlauben mit "at 
0x80" die Adresse einer Variable festzulegen. Damit kann man dann deine 
Vorstellung verwirklichen.
 ARM hat dafür "Bitbanding", aber das ist für die Zeit nach den 
Grundlagen ;-)

Allgemein ist ein Port eine 8..32-Bit-Variable und die einzelnen Bits 
müssen durch AND und OR manipuliert werden.
HW-Ports sind übrigens (fast immer) "volatile" deklariert, was bedeutet, 
der Compiler muß jederzeit mit einer Änderung rechnen, die er nicht 
selbst verursacht hat. Wenn man dann 2 Statements benutzt um 2 Bits zu 
manipulieren,
1
 // ASM in handübersetzt AVR-like 
2
PORT |= (1<<2);   // in r24,PORT; ori r24,0x04; out PORT,r24
3
PORT |= (1<<4);   // in r24,PORT; ori r24,0x10; out PORT,r24
dann werden da garantiert 2 (Schreib)Zugriffe auf den Port draus.
Bei nur einen Statement
1
PORT |= ((1<<2) | (1<<4)); // in r24,PORT; ori r24,0x14; out PORT,r24
passieren dagegen beide Änderungen aus Port-Sicht gleichzeitig.
Gast #4668316
Lesenswert?

Anfänger schrieb:
> ich hab in A= entwerder 0b001 oder 0b011 stehen
>
> jetzt will ich sicher gehen das dort egal welcher zustand von den beiden
> gegeben ist in A= 0b011 steht aber ich find nicht die richtige
> Operation.

einfach zuweisen, da muss man ja gar nicht rechnen

a = 0b011;
Gast #4668428
Lesenswert?

Anfänger schrieb:
> A|= (1<<1) | (1<<4);
>
> Ist das, dass selbe wie
>
> A|= (1<<1);
> A|= (1<<4);

Nein, das ist nicht immer dasselbe. Typischerweise wird sowas nämlich 
gebraucht, wenn A ein Register ist. Das wird dann als volatile 
deklariert. Variante 1 setzt beide Bits auf einmal, bei Variante 2 sind 
es zwei Schreibzugriffe, zwischen denen auch noch ein Interrupt 
passieren kann.

Ist A hingegen nicht das eigentliche Register, sondern eine normale, 
lokale Variable (Schattenregister), also nicht volatile, dann wid der 
Compiler den Code aus Variante 2 zu dem aus Variante 1 zusammenfassen.

Daß die Bitzählung bei 0 losgeht und nicht bei 1, wurde ja schon 
erwähnt.
Gast #4668510
Lesenswert?

Carl D. schrieb:
> ARM hat dafür "Bitbanding", aber das ist für die Zeit nach den Grundlagen

Bitbanding ist nicht vollständig atomar, da ja intern doch wieder ein 
READ-MODIFY-WRITE ausgeführt wird. Aktuelle ARM haben tatsächlich wie 
ein 8051 Bit-adressierbare Peripherie-Register d.h. z.B. jedes Pin eines 
Ports wird in ein Byte im Speicher gemappt. Im C Include sieht das dann 
z.B. für LPC810 so aus:

#define PIN0BASE 0xA0000000
__IO_REG8(P0_0, PIN0BASE    , __READ_WRITE);
__IO_REG8(P0_1, PIN0BASE + 1, __READ_WRITE);
...

Somit geht dann in C:

#define LED P0_1
LED = 1;

Und daraus wird dann in ASM:

STRB TRUE, [PIN0BASE, #1]

Zudem haben aktuelle ARM auch noch eine AND-NOT-Logik zum atomaren 
Toggeln, das ist aber eher was für Inline ASM:

MOVS R0, #10B
STR  R0, [NOT0]
Gast #4668540
Lesenswert?

icke schrieb:
> Da Schreibt man einfach Not
> und der Compiler ist schlau genug zu erkennen ob binär oder logisch.
> Bei C habe ich immer wieder Probleme.

Tanja schrieb:
> wieder ein sehr schönes beispiel für die C hater Seite :-)
> Die ich übrigens super finde, auch wenn man C lernen will!! da man
> versucht die Beispiele zu verstehen auch wenn manche Flach sind, so sind
> die für Anfänger supe, da man sieht ob man darauf reingefallen wäre..
> Zeigt aber auch wieder die Vorteile von Pascal...!
1
c = not(a and b)

Woher weiß man da jetzt, ob gemeint ist
1
c = !(a && b);
oder
1
c = ~(a && b);
oder
1
c = !(a & b);
oder
1
c = ~(a & b);
Gast #4668612
Lesenswert?

Für mich besonders elegant zur Bitmanipulation erschien mir die Variante 
mit sbit.h - ich glaube, sie war von Peter Dannegger und ist sicher mit 
der Suchfunktion zu finden.
Dann sieht der entsprechende Teil im Programm z.B. so aus:
1
#include "sbit.h"
2

3
#define EIN     1
4
#define AUS     0
5
#define HIGH    1
6
#define LOW     0
7

8
#define OUTPUT  1
9
#define INPUT   0
10

11
#define KEY      PORT_C6  
12
#define KEY_DIR  DDR_C6
13
#define KEY_IN   PIN_C6
14

15
#define FET      PORT_B2
16
#define FET_DIR  DDR_B2
17

18
int main ()
19
{
20
  KEY = HIGH;      // Pullup on
21
  KEY_DIR = INPUT;
22
  FET_DIR = OUTPUT;
23
  FET = AUS;
24

25
  if (KEY_IN==HIGH)
26
    {
27
      FET = EIN;
28
    }
29
  else
30
    {
31
      FET = AUS; 
32
    }
33
.
34
.
35
.
36
}
Das soll nur ein anschauliches Beispiel sein - hier ohne 
Tastaturentprellung und Endlosschleife ...
Man hat am Kopf eben etwas mehr 'defines', erhält dafür aber auch einen 
deutlich besser lesbaren Code.

Ich hoffe, ich trete ihm nicht zu nahe, wenn ich die 'sbit.h' hier mit 
anhänge.
Angehängte Dateien:
Gast #4668643
Lesenswert?

icke schrieb:
> Meine Muttersprache ist Pascal.
> Da Schreibt man einfach Not
> und der Compiler ist schlau genug zu erkennen ob binär oder logisch.

Dürfte daran liegen, daß Boolean in Pascal immer schon ein ganz eigener 
Datentyp war und somit And, Not usw. angewandt auf Datentyp Bool, immer 
eine logische Operation sein muß. Hingegen dieselben Operationen, 
angewandt auf Integer, werden dann wohl binäre Operationen sein.

In C gab es bis C99 keinen Datentyp Boolean. Man konnte sich das mit 
Makros nachahmen, aber das ergab dann wieder eigene Fallstricke. Es gilt 
in C, daß jede ganzzahlige Variable logisch TRUE ist, die ungleich 0 
ist. 0 ist dann FALSE.

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