HSG |
|
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'
# -*- 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)))
Baue mit Hades nach dem Vorbild einen 4-Bit-Serienaddierer mit den Eingängen a und b und dem Ausgang c.