Python MaterialInstallationDokumentationPythonKaraGrundlagenNamensräumeFunktionenTestenStringsDictionaryListenZeitmessungenZufallBitsBytesModuleSocketsxmlserielle SchnittstellePython in HTMLTurtlexturtleTkinterOOPThreadsZusicherungenexePatternsGnuPlotGotoMySQLCGIDateienExceptionsGrafikMathematikFischertechnikUnicodefunktionalIteratorSoundCDebuggerregexPfadeDocstringsDjangoBluetoothformatBytecodesignal
Pfad: Startseite/Fächer/Informatik/Python
BitsBytes

Zugriff auf einzelne Bytes

Mit Hilfe des Moduls struct ist es möglich, auf einzelne Bytes einer c-Struktur zuzugreifen. So zeigt folgender Auszug einer Shell-Sitzung, dass der c-Datentyp int ( 'i' ) 4 Byte umfasst und die Zahl 5 durch die Bytes '\x05\x00\x00\x00' dargestellt wird. Python stellt die Byte-Folge als Zeichenkette (String) dar. Kann ein Zeichen nicht dargestellt werden, so weicht Python auf eine hexadezimale Darstellung aus, die durch \x eingeleitet wird und dann zwei Hex-Ziffern enthält. Bei der Darstellung der Zahl 5 fällt auf, dass die Bytes in ihrer Reihenfolge vertauscht wurden. Das ist bei den benutzten Geräten die native little-endian-Darstellung. Eine big-endian-Darstellung erhält man durch den Zusatz von > beim Formatstring. Das Gesagte wird unterstützt durch die Darstellung der Zahl 65. Drei 0-Bytes folgt das 'A', das laut ASCII-Tabelle die Nummer 65 hat, dh. intern als das Bitmuster 0100 0001 dargestellt wird. Die Umwandlung kann auch in der anderen Richtung erfolgen. Angenommen, wir wollen die int-Zahl wissen, die durch 'Esel' in big-endian dargestellt wird. unpack liefert uns ein Tupel mit einem Element, der Zahl 1165190508. Diese dezimale Zahl wird also in big-endian so dargestellt, dass die 4 Bytes als Zeichen interpretiert das Wort 'Esel' ergeben.

>>> from struct import *
>>> calcsize('i')
4
>>> pack('i',5)
'\x05\x00\x00\x00'
>>> pack('>i',5)
'\x00\x00\x00\x05'
>>> pack('>i',65)
'\x00\x00\x00A'
>>> unpack('>i','Esel')
(1165190508,)

So 'lustig' diese Darstellung auch sein kann, zum Lernen will man die Bytes eher in hexadezimaler oder gar in binärer Darstellung sehen. Das erledigen die Funktionen s2h und s2b aus StrToHexBin.py.

def s2h(s):
    H =['0','1','2','3','4','5','6','7',
        '8','9','a','b','c','d','e','f']  # Hex-Ziffern
    i = 0    # Laufvariable
    a = ''   # Ausgabestring
    L = len(s)
    while i < L:
        n = ord(s[i])
        s0 = n%16 # 1 -Stelle
        s1 = n/16 # 16-Stelle
        a = a+' '+H[s1]+H[s0]
        i = i+1
    return a

def s2b(s):
    B =['0000','0001','0010','0011','0100','0101','0110','0111',
        '1000','1001','1010','1011','1100','1101','1110','1111']  # Binär-Muster
    i = 0    # Laufvariable
    a = ''   # Ausgabestring
    L = len(s)
    while i < L:
        n = ord(s[i])
        s0 = n%16 # 1 -Stelle
        s1 = n/16 # 16-Stelle
        a = a+'  '+B[s1]+' '+B[s0]
        i = i+1
    return a

Die Zahlen 1165190508 und 65 sehen dann so aus:

>>> s2h(pack('>i',1165190508))
' 45 73 65 6c'
>>> s2b(pack('>i',1165190508))
'  0100 0101  0111 0011  0110 0101  0110 1100'
>>> s2h(pack('>i',65))
' 00 00 00 41'
>>> s2b(pack('>i',65))
'  0000 0000  0000 0000  0000 0000  0100 0001'

Aufgaben

  • Was ist die kleinste negative und die größte positive int-Zahl?
  • Vollziehe das Zweierkomplement nach, indem du dir 27, dann ~27 und dann ~27+1 darstellen lässt. Lasse dir den String zu ~27+1 ('\xff\xff\xff\xe5') rückwärts mit unpack als Zahl zeigen.
  • Welche int-Zahl hat überall '1'?
  • Wie kann man belegen, dass - zumindest auf x86-Maschinen - Python 4 Byte für den Typ int verwendet? Wie verhält sich Python bei einem int-Überlauf?

4-Bit-MiniInt

# -*- coding: iso-8859-1 -*-
# mk, 15.9.08, 9.11.08

# 4-Bit-Int

# Dictionary Z = { key:wert,.. }
Z = {0:[0,0,0,0],1:[0,0,0,1],2:[0,0,1,0],3:[0,0,1,1],
     4:[0,1,0,0],5:[0,1,0,1],6:[0,1,1,0],7:[0,1,1,1],
     -8:[1,0,0,0],-7:[1,0,0,1],-6:[1,0,1,0],-5:[1,0,1,1],
     -4:[1,1,0,0],-3:[1,1,0,1],-2:[1,1,1,0],-1:[1,1,1,1]}

def Itoi(a):
    """
    Int a wird in ein MiniInt umgewandelt
    """
    return Z[a]   # lesender Zugriff auf globale Variable Z

def itoI(b):
    """
    MiniInt b  wird in Int umgewandelt
    """
    for k in Z.keys():
        if Z[k]==b:
            return k

def ha(a,b):
    """
    Halbaddierer, a = 0 oder 1, b = 0 oder 1
    """
    s  = a^b
    ue = a&b
    return [s,ue]

def va(a,b,c):
    """
    Volladdierer, a = 0 oder 1, b = 0 oder 1, v = 0 oder 1,
    """
    [s1,ue1] = ha(a,b)
    [s,ue2] = ha(s1,c)
    ue = ue1|ue2
    return [s,ue]

def gl(a,b):
    """
    die beiden Listen a und b werden dadurch auf gleiche Länge gebracht,
    dass die kürzere von vorne mit Nullen aufgefüllt wird
    die Listen werden als [a,b] zurückgegeben
    """
    na = len(a)
    nb = len(b)
    if na < nb:
        n = nb
        while len(a) < n:
            a = [0]+a
    else:
        n = na
        while len(b) < n:
            b = [0]+b
    return [a,b]

def addbin(a,b):
    """
    die beiden 'Binär-Listen' a und b werden addiert
    """
    [a,b] = gl(a,b)
    n = len(a)
    ue = 0
    s = []
    for i in range(n-1,-1,-1):
        [si,ue] = va(a[i],b[i],ue)
        s = [si]+s
    return s

def add1(a):
    """
    zur 'Binär-Liste' a wird 1 addiert,
    dabei wird ein Übertrag nicht berücksichtigt
    """
    n = len(a)
    s = []
    ue = 1
    for i in range(n-1,-1,-1):
        [si,ue] = ha(a[i],ue)
        s = [si]+s
    return s

def sub1(a):
    """
    von der 'Binär-Liste' a wird 1 subtrahiert,
    dabei wird ein Übertrag nicht berücksichtigt
    """
    n = len(a)
    s = []
    ue = 0
    for i in range(n-1,-1,-1):
        [si,ue] = va(a[i],1,ue)
        s = [si]+s
    return s

def zweierkomplement(a):
    """
    zur 'Binär-Liste' a wird das Zweierkomplement gebildet
    """
    a = a[:]       # erst kopieren, damit es keine Seiteneffekte gibt
    n = len(a)
    for i in range(n):
        a[i] = 1-a[i]
    return add1(a)

def subbin(a,b):
    """
    die 'Binär-Liste' b wird von der 'Binär-Liste' a subtrahiert
    """
    b2 = zweierkomplement(b)
    return addbin(a,b2)

def testadd(a,b):
    return itoI(addbin(Itoi(a),Itoi(b)))

def testsub(a,b):
    return itoI(subbin(Itoi(a),Itoi(b)))

miniint.py

Aufgabe

Baue mit Hades nach dem Vorbild einen 4-Bit-Serienaddierer mit den Eingängen a und b und dem Ausgang c.

Links

Valid XHTML 1.0!