Bitpopelei


Erstellt: 2008-10-25Letzte Änderung: 2008-10-25 [vor 15 Jahren, 5 Monaten, 26 Tagen]

Bitpopelei Der Name ist Programm; hier dreht sich alles um Binär- und Hexadezimalzahlen, um Verknüpfungen und Konvertierungen, um Logikgatter und Ähnliches.

Unentbehrlich für Entwickler, die hardwarenah - sei es auf dem Mikrocontroller oder dem PC - programmieren und sich mit solchen Dingen herumschlagen müssen.

Beispielcodes gibt es in AVR-Asm, x86-Asm, C, FreeBASIC und PHP.

Dez, Hex und Bin

Darstellungsweisen von Dez, Hex und Bin:

Dez Hex Bin
AVR-Asm 23 0x17 / 0h17 0b10111
x86-Asm 23 0x17 / 0h17 0b10111
C 23 0x17 0b10111
FreeBASIC 23 &H17 &B10111
PHP 23 0x17 bindec('10111')
(Keine Angst; ich gehöre nicht zu den Illuminaten. Ich mag einfach nur Primzahlen! xD)

Die Zahlen 0 bis 47 in Dezimal, Hexadezimal und Binär:

Dez Hex Bin
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
00
01
02
03
04
05
06
07
08
09
0A
0B
0C
0D
0E
0F
0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101
1110
1111
Dez Hex Bin
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
10
11
12
13
14
15
16
17
18
19
1A
1B
1C
1D
1E
1F
10000
10001
10010
10011
10100
10101
10110
10111
11000
11001
11010
11011
11100
11101
11110
11111
Dez Hex Bin
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
20
21
22
23
24
25
26
27
28
29
2A
2B
2C
2D
2E
2F
100000
100001
100010
100011
100100
100101
100110
100111
101000
101001
101010
101011
101100
101101
101110
101111

Nach oben

Bits und Bytes

Tabelle der Byte-Vielfachen:

Nibble 4 Bits1/2 Byte
Byte 8 Bits  1 Byte
Word16 Bits  2 Bytes
DWord32 Bits  4 Bytes
QWord64 Bits  8 Bytes


Bits in einem Byte:

76543210
MSBLSB
MSB = Most Significant Bit
LSB = Least Significant Bit

Nach oben

Endianness

Als Endianness bezeichnet man die Reihenfolge der Bytes in einem Word bzw. in Word-Vielfachen.

Little Endian:

Intel-Format. Kleines Ende zuerst. Das niederwertige Byte steht am Anfang.

Byte 1Byte 0
7654321076543210
MSBLSB
MSB = Most Significant Byte
LSB = Least Significant Byte

Big Endian:

Motorola-Format. Großes Ende zuerst. Das höherwertige Byte steht am Anfang.

Byte 1Byte 0
7654321076543210
LSBMSB
MSB = Most Significant Byte
LSB = Least Significant Byte

Nach oben

Logikgatter

Wahrheitstabellen für die gebräuchlichsten Logikgatter.

List of 7400 series integrated circuits - Wikipedia

NOT
NOT AY
01
10
 
 

AND
AND ABY
000
010
100
111
NAND
NAND ABY
001
011
101
110

OR
OR ABY
000
011
101
111
NOR
NOR ABY
001
010
100
110

XOR
XOR ABY
000
011
101
110
XNOR
XNOR ABY
001
010
100
111

Nach oben

Bitoperationen

Einzelnes Bit setzen

Das im Byte zu setzende Bit wird in der Maske gesetzt.

Die Maske entspricht dem Wert 2 ^ bit.

Dann wird die Maske mit dem Byte OR-verknüpft.

AVR-Asm Nur für Register:
ldi	r16, 0b00001000 ; Das Byte
sbr	r16, (1 << 7) ; Das Bit Nr. 7 wird im Byte gesetzt

Nur für Ports:
sbi	PORTA, 7 ; Das Bit Nr. 7 wird im Port PORTA gesetzt
x86-Asm
mov	al, 7 ; Das zu setzende Bit
mov	ah, 0b00001000 ; Das Byte
or	al, ah ; Das Bit wird im Byte gesetzt
C
unsigned char bit = 7; // Das zu setzende Bit
unsigned char x = 0b00001000 | (1 << bit); // Das Bit wird im Byte gesetzt

oder alternativ

unsigned char bit = 7; // Das zu setzende Bit
unsigned char x = 0b00001000; // Das Byte
x |= (1 << bit); // Das Bit wird im Byte gesetzt
FreeBASIC
DIM AS INTEGER bit = 7 ' Das zu setzende Bit
DIM AS INTEGER x = &B00001000 OR (bit ^ 2) ' Das Bit wird im Byte gesetzt
PHP
$bit = 7; // Das zu setzende Bit
$x = 0b00001000 | (1 << $bit); // Das Bit wird im Byte gesetzt

oder alternativ

$bit = 7; // Das zu setzende Bit
$x = 0b00001000; // Das Byte
$x |= (1 << $bit); // Das Bit wird im Byte gesetzt

In C ist folgendes Makro hilfreich:
#define set_bit(var, bit)	((var) |= (1 << (bit)))

Einzelnes Bit löschen

Das zu löschende Bit wird in der Maske gelöscht.
Alle übrigen Bits in der Maske werden gesetzt.

Die Maske entspricht dem negierten Wert 2 ^ bit, also 255 - (2 ^ bit).

Dann wird die Maske mit dem Byte AND-verknüpft.

AVR-Asm Nur für Register:
ldi	r16, 0b00001000 ; Das Byte
cbr	r16, (1 << 7) ; Das Bit Nr. 7 wird im Byte gelöscht

Nur für Ports:
cbi	PORTA, 7 ; Das Bit Nr. 7 wird im Port PORTA gelöscht
x86-Asm
mov	al, !(7) ; Aus dem zu löschenden Bit (in Klammern) die Maske erstellen
mov	ah, 0b00001000 ; Das Byte
and	al, ah ; Das Bit wird im Byte gesetzt
C
unsigned char bit = 7; // Das zu löschende Bit
unsigned char x = 0b00001000 & ~(1 << bit); // Das Bit wird im Byte gelöscht

oder alternativ

unsigned char bit = 7; // Das zu löschende Bit
unsigned char x = 0b00001000; // Das Byte
x &= ~(1 << bit); // Das Bit wird im Byte gelöscht
FreeBASIC
DIM AS INTEGER bit = 7 ' Das zu löschende Bit
DIM AS INTEGER x = &B00001000 AND NOT (bit ^ 2) ' Das Bit wird im Byte gelöscht
PHP
$bit = 7; // Das zu löschende Bit
$x = 0b00001000 & ~(1 << $bit); // Das Bit wird im Byte gelöscht

oder alternativ

$bit = 7; // Das zu löschende Bit
$x = 0b00001000; // Das Byte
$x &= ~(1 << $bit); // Das Bit wird im Byte gelöscht

In C ist folgendes Makro hilfreich:
#define clear_bit(var, bit)	((var) &= (unsigned)~(1 << (bit)))

Mehrere Bits setzen

Alle im Byte zu setzenden Bits werden in der Maske gesetzt.
Dann wird die Maske mit dem Byte OR-verknüpft.

Byte 0b10001000
OR 0b10101010 Ergebnis
Maske 0b00100010

AVR-Asm
ldi r16, 0b10001000	; Das Byte wird in r16 geladen
ori r16, 0b00100010	; Das Byte wird mit der Maske OR-verknüpft
x86-Asm
mov al, 0b10001000 ; Das Byte in al laden
or al, 0b00100010 ; Das Byte wird mit der Maske OR-verknüpft
C
unsigned char x = 0b10001000 & 0b00100010; // Das Byte wird mit der Maske OR-verknüpft

oder alternativ

unsigned char x = 0b10001000; // Das Byte wird in x geladen
x |= 0b00100010; // Das Byte wird mit der Maske OR-verknüpft
FreeBASIC
DIM AS INTEGER x = &B10001000 OR &B00100010 ' Das Byte wird mit der Maske OR-verknüpft
PHP
$x = 0b10001000 & 0b00100010; // Das Byte wird mit der Maske OR-verknüpft
oder alternativ

$x = 0b10001000; // Das Byte wird in $x geladen
$x |= 0b00100010; // Das Byte wird mit der Maske OR-verknüpft

Mehrere Bits löschen

Alle zu löschenden Bits im Byte werden in der Maske gelöscht.
Alle übrigen Bits in der Maske werden gesetzt.
Dann wird die Maske mit dem Byte AND-verknüpft.

Byte 0b11110010
AND 0b11010010 Ergebnis
Maske 0b11011111

AVR-Asm
ldi r16, 0b11110010 ; Das Byte wird in r16 geladen
andi 16, 0b11011111 ; Das Byte wird mit der Maske AND-verknüpft
x86-Asm
mov al, 0b11110010 ; Das Byte wird in al geladen
and al, 0b11011111 ; Das Byte wird mit der Maske AND-verknüpft
C
unsigned char x = 0b11110010 & 0b11011111; // Das Byte wird mit der Maske AND-verknüpft

oder alternativ

unsigned char x = 0b11110010; // Das Byte wird in x geladen
x &= 0b11011111; // Das Byte wird mit der Maske AND-verknüpft
FreeBASIC
DIM AS INTEGER x = &B11110010 AND &B11011111 ' Das Byte wird mit der Maske AND-verknüpft
PHP
$x = 0b11110010 & 0b11011111; // Das Byte wird mit der Maske AND-verknüpft

oder alternativ

$x = 0b11110010; // Das Byte wird in $x geladen
$x &= 0b11011111; // Das Byte wird mit der Maske AND-verknüpft

Alle Bits Nullsetzen

Ein alter Assembler-Trick: xor al, al - Löscht alle Bits in al.
Funktioniert natürlich mit allen Registergrößen.

Bits Invertieren

Die Bits werden mit dem für die Programmiersprache spezifischen Befehl invertiert.

AVR-Asm Register:
ldi	r16, 0x23 ; Das zu invertierende Byte
com	al ; Byte invertieren

Konstante:
ldi	16, !0x23 ; Den invertierten Wert von 0x23 in r16 schreiben
x86-Asm Register:
mov	al, 0x23 ; Das zu invertierende Byte
not	al ; Byte invertieren

Konstante:
mov	al, !0x23 ; Den invertierten Wert von 0x23 in al schreiben
C
unsigned char x = ~0xff;<br>
FreeBASIC
DIM AS INTEGER x = NOT &HFF
PHP
$x = ~0xff;

Nach oben

Konvertierungen

C / C++

Most Significant Word / Least Significant Word:
#define msw(var)	(((var >> 16) & 0xffff))
#define lsw(var)	((var & 0xffff))

Most Significant Byte / Least Significant Byte:
#define msb(var)	((var >> 8) & 0xff)
#define lsb(var)	((var & 0xff))

Most Significant Nibble / Least Significant Nibble:
#define msn(var)	((var >> 4) & 0xf)
#define lsn(var)	((var & 0xf))

PHP

String zu Hexadezimal:
function str2hex($str)
{
	$hex = "";
	for ($i = 0; $i < strlen($str); $i++)
	{
		$hex .= str_pad(dechex(ord($str[$i])), 2, 0, STR_PAD_LEFT);
	}
	return $hex;
}

Hexadezimal zu String:
function hex2str($hex)
{
	$str = "";
	for ($i = 0; $i < strlen($hex); $i += 2)
	{
		$str .= chr(hexdec(substr($hex, $i, 2)));
	}
	return $str;
}

Nach oben