FB18 - Das Forum für Informatik

fb18.de / Diplom Informatik / Unterbereich Grundstudium / Technische Informatik

T3 Blatt 11

T3 Blatt 11 2003-01-19 12:34
Anonymer User
Hallo!

Bevor ihr die Nerven verliert - die Zahlen im Array sind als im Einerkomplement gegeben zu interpretieren und muessen nicht erst ins Einerkomplement konvertiert werden. Lediglich die Pruefsumme ist ganz am Ende einmal zu "konvertieren".

Gruss, Fred


Re: T3 Blatt 11 2003-01-19 13:17
TriPhoenix
Wenn man nur wüsste worums geht [img]http://www.fb18.de/gfx/25.gif[/img]

Re: T3 Blatt 11 2003-01-19 16:59
Fred
Wenn man nur wüsste worums geht [img]http://www.fb18.de/gfx/25.gif[/img]
Die Elemente eines Array von 16-Bit-Zahlen soll im Einerkomplement zusammenaddiert werden, das Ergebnis soll dann wiederum in normale Darstellung zuruecktransferiert werden.


Re: T3 Blatt 11 2003-01-19 17:59
TriPhoenix
Die Elemente eines Array von 16-Bit-Zahlen soll im Einerkomplement zusammenaddiert werden, das Ergebnis soll dann wiederum in normale Darstellung zuruecktransferiert werden.

Klingt machbar…Pflichtaufgabe?



Re: T3 Blatt 11 2003-01-19 19:10
Anonymer User
Klingt machbar…Pflichtaufgabe?

Es ist eine Pflichtaufgabe.
Aber wenn es machbar klingt, kannst du mir sagen, wie ein Array im Assembler behandelt wird bzw. wo er bei SPARC liegt, sodass ich ihn mir selbst auseinandernehmen kann? Ich kann mir nämlich nicht vorstellen, dass x-mal 16Bit in ein Register passen.

Re: T3 Blatt 11 2003-01-19 19:22
TriPhoenix
Klingt machbar…Pflichtaufgabe?
Es ist eine Pflichtaufgabe.
Aber wenn es machbar klingt, kannst du mir sagen, wie ein Array im Assembler behandelt wird bzw. wo er bei SPARC liegt, sodass ich ihn mir selbst auseinandernehmen kann? Ich kann mir nämlich nicht vorstellen, dass x-mal 16Bit in ein Register passen.

Wenns ein 16-bit-Array ab Adresse xyz ist, dann liegen alle 16-bit Zahlen ab der Adresse xyz rum, also
xyz+0 <16-bit-zahl 1>
xyz+2 <16-bit-zahl 2>


Wenn eine FUnktion von C aus mit nem Array aufgerufen wird, wird in Wirklichkeit die Adresse übergeben. Damit kann man dann aus dem Parameter per ldh (load halfword?) jeweils die Zahlen holen. Um dann an die nächste Zahl zu kommen, erhöht man den Adresszeiger (also das Register in dem die Adresse liegt) um 2.

Re: T3 Blatt 11 2003-01-19 20:03
Fred
Wenn eine FUnktion von C aus mit nem Array aufgerufen wird, wird in Wirklichkeit die Adresse übergeben.
Man kann sogar so weit gehen zu sagen, ein Array IST die Adresse des ersten Arrayelements (jedenfalls in C und Assembler).


Re: T3 Blatt 11 2003-01-20 13:56
Anonymer User
Ich war nicht in der uebung, also noch mal zur Sicherheit:
Die Aufgabe ist, eine Funktion in Assembler zu schreiben, die ein Array aus Integers(?), die Einerkomplemente darstellen, bekommt, und dann das ergebnis in "normaler" Darstellung als
Long(?) zurueckgibt/oder auf der Konsole ausgibt(?).

Re: T3 Blatt 11 2003-01-20 15:45
Fred
Ich war nicht in der uebung, also noch mal zur Sicherheit:
Die Aufgabe ist, eine Funktion in Assembler zu schreiben, die ein Array aus Integers(?), die Einerkomplemente darstellen, bekommt, und dann das ergebnis in "normaler" Darstellung als
Long(?) zurueckgibt/oder auf der Konsole ausgibt(?).
Die Signatur lautet

int pruefsumme(unsigned short a[], int n);

Bzw. der Rueckgabewert ist natuerlich auch unsigned short, aber ich finde int schoener, und da passt ja auch alles rein [img]http://www.fb18.de/gfx/7.gif[/img]




Re: T3 Blatt 11 2003-01-20 16:00
Digital Juhnke
Hmpff ihr seid hier ja alle die Ur-Profis…

Wieso bekomme ich immer ein
Undefined first referenced symbol in file pruefsumme pruefsumme.o ld: fatal: Symbol referencing errors. No output written to a.out
So sieht der Code aus….

pruefsumme.c

/* programm pruefsumme.c */ #include <stdio.h> int pruefsumme(unsigned short a[], int n); int main(void) { unsigned short x[] = {0x866d, 0xc059, 0x866d, 0xc0d7, 0x0006, 0x0018, 0x8cba, 0x0009, 0x847a, 0xfb43, 0x0000, 0x6002, 0x2238, 0x0000, 0x0204, 0x05b4}; int y = 16; printf("Resultat: %0x\n", pruefsumme(x, y)); return 0; }
und so pruefsumme.s

.section ".text" .align 8 .skip 16 .global pruefsumme .type pruefsumme,2 ! %i0 Addresse des Arrays ! %i1 Groesse des Arrays ! %o2 Ergebnisszwischenspeicher ! %o3 bearbeitetes Element ! %o4 Arrayindex ! %o5 Hilfsteil pruefsumme: save %sp,-104,%sp orcc %g0,%i1,%o1 ! Ist n == 0 ? ble .ende ! dann gehe direkt zum Ende mov %g0,%o2 ! Summe = 0 mov %g0,%o4 ! Arrayindex = 0 mov %g0,%o5 ! Hilfsteil .schleife: ld [%i0+%o4],%o3 ! Hole erstes Element add %o2,%o3,%o2 ! Addiere Element auf Summe srl %o2,16,%o5 ! Schau ob Ueberlauf und addiere add %o2,%o5,%o2 subcc %o1,1,%o1 ! ein Element weniger bne .schleife ! wenn %o1 > 0 hole naechstes Element add %o4,4,%o4 ! inkrementiere Index (DELAY SLOT) .ende: mov %o2,%i0 jmp %o7+8 restore
danke….

Re: T3 Blatt 11 2003-01-20 16:56
TriPhoenix
.section ".text" .align 8 .skip 16 .global pruefsumme .type pruefsumme,2

mach mal align und skip und vor allem das type weg…ich vermute mit dem Type bekommt Prüfsumme was falsches Ausgezwängt. Align ist bie Section-Beginn sowieso hinfällig und skip ebenso (wozu soll da auch freier Platz sein), guck mal obs ohne die drei Dinge geht



Re: T3 Blatt 11 2003-01-20 17:06
sheckmueller
sowohl fuer pruefsumme.c als auch pruefsumme.s heisst die object-datei pruefsumme.o. Das heisst im konkreten Fall, das die pruefsumme.o von der c-datei die object-datei der assembler-datei ueberschreibt. wenn die dateien unterschiedliche Namen haben, solltest du zumindest keinen Linkererror mehr haben.

Re: T3 Blatt 11 2003-01-20 20:08
Slater
.schleife: ld [%i0+%o4],%o3 ! Hole erstes Element add %o2,%o3,%o2 ! Addiere Element auf Summe srl %o2,16,%o5 ! Schau ob Ueberlauf und addiere add %o2,%o5,%o2 subcc %o1,1,%o1 ! ein Element weniger bne .schleife ! wenn %o1 > 0 hole naechstes Element add %o4,4,%o4 ! inkrementiere Index (DELAY SLOT) .ende: mov %o2,%i0 jmp %o7+8 restore
du solltest auch
* nach jedem entdecken eines überlaufes diese führende 1 dann entfernen,

* die adresse eigentlich nur um 2 erhöhen? so klappte das bei mir,

* am ende das ergebnis noch einer-invertieren,

* eher nach %i7+8 springen



..wenn du schon mal fragst [img]http://www.fb18.de/gfx/22.gif[/img]




Re: T3 Blatt 11 2003-01-20 23:22
TurboP
* nach jedem entdecken eines überlaufes diese führende 1 dann entfernen,
Ja, das sollte man wohl tun, sonst wird das nix mit der 16-Bit Prüfsumme :-)

* die adresse eigentlich nur um 2 erhöhen? so klappte das bei mir,
Das hängt davon ab, ob du mit Halfword oder Word arbeitest. Bei uns in der Gruppe wurde ein einfaches Word empfohlen, dass soll wohl auch performanter sein…

* eher nach %i7+8 springen
Das ist ein schwieriges Ding, da habe ich heute ziemlich lang dran gesessen. Also:
Wenn man Werte in Form von Zeigern übergibt (Was man bei einem Array zwangsläufig machen muß), dann bekommt man eine Fehlermeldung an der Stelle des ld-Befehls(Segmentation Fault), falls diese Unterfunktion einen Save-Befehl ausführt.
Der Speicherbereich der aufrufenden Funktion ist dann nämlich nicht mehr verfügbar, da er als 'fremd' markiert wird…
Folge: Eine Zugriffsverletzung

Um das zu umgehen, lässt man den Save-Befehl einfach weg (das Restore am Ende auch, kann sonst ne lange Suche werden:-) )
Die Prozedur heißt dann 'Leaf Routine'

Diese benutzt nun die gleichen Register wie der Aufrufer, deswegen halt jmpl %o7+8, %g0

Ein Beispiel dazu findet man auf Seite 57 / 58 in unserem kleinen Manual



Re: T3 Blatt 11 2003-01-21 01:22
TriPhoenix
Wenn man Werte in Form von Zeigern übergibt (Was man bei einem Array zwangsläufig machen muß), dann bekommt man eine Fehlermeldung an der Stelle des ld-Befehls(Segmentation Fault), falls diese Unterfunktion einen Save-Befehl ausführt.
Der Speicherbereich der aufrufenden Funktion ist dann nämlich nicht mehr verfügbar, da er als 'fremd' markiert wird…
Folge: Eine Zugriffsverletzung

Um das zu umgehen, lässt man den Save-Befehl einfach weg (das Restore am Ende auch, kann sonst ne lange Suche werden:-) )
Die Prozedur heißt dann 'Leaf Routine'

Hm, also dass ein Save den Adressbereich als ungültig markiert halte ich für ein Gerücht. Meine Funktion funktioniert zumindets noch vollkommen zuverlässig, auch mit save/restore :) Es wäre auf recht unsinnig in einem save den Adressbereich ungültig zu machen, da
a) es vielzuviel Zeit kostet für so einen kleines, ständig ausgeführtes Ding
b) Es Betriebssystemsache ist und nicht des Prozessors
c) Dann jede Funktion die mit Zeigern arbeitet eine Leaf-Funktion sein müsste. D.h. in C-Programmen dürfte man keine Zeiger benutzen, solange die Unterfunktion auch was aufruft. Des weiteren dürften die meisten Standardbefehle, wie z.B. printf vermutlich auch nicht mehr gehen, da die dazu neigen, sleber weitere Dinge aufzurufen.

Check lieber mal deine Variablen und dass du die o- und i-Register nicht verwechselt hast [img]http://www.fb18.de/gfx/22.gif[/img]



Re: T3 Blatt 11 2003-01-21 07:09
Zaphod
Ich hab mal ne Frage zu dem Maskieren. Irgendwo muss man ja den eventuell vorhandenen Übertrag rausschmeißen. und da das mit

and %l0, 0xffff, %l0

nicht geht, da 0xffff zu groß ist, dachte ich mir, dass man in der ".rodata"-Sektion einfach eine Adresse angibt, in der das enthalten ist. Dort müsste das ja eigentlich gehen, oder?

and %l0, meinLabel, %l0

meinLabel: ".WelcherTypIstDasEigentlich?" 0xffff



Re: T3 Blatt 11 2003-01-21 07:22
Slater
* die adresse eigentlich nur um 2 erhöhen? so klappte das bei mir,
Das hängt davon ab, ob du mit Halfword oder Word arbeitest. Bei uns in der Gruppe wurde ein einfaches Word empfohlen, dass soll wohl auch performanter sein…
hmm, bist du bei dem angegebenen programm mit von der partie?,
da ist nämlich im zugehörigen C programm der datentyp short verwendet worden, und das war bei mir auch so, und funktionierte mit +2
* eher nach %i7+8 springen
Das ist ein schwieriges Ding, da habe ich heute ziemlich lang dran gesessen. Also:
[..]
Um das zu umgehen, lässt man den Save-Befehl einfach weg (das Restore am Ende auch, kann sonst ne lange Suche werden:-) )

Diese benutzt nun die gleichen Register wie der Aufrufer, deswegen halt jmpl %o7+8, %g0
und wieder gilt:
in dem programm steht doch save/restore! (was auch wiederum in meinem programm, wenn auch unnötig, einwandfrei funktionierte)

also i7,



aber müssige diskussion, ich gebs zu [img]http://www.fb18.de/gfx/23.gif[/img],
bei programm-umkonstruktionsvorschlägen bitte nicht meine hinweise zitieren, das verdreht irgendwie alles..


den Segmentation Fault kriegst auch mit ganz anderen geschichten als nur bei richtigen speicherproblemen (wenn denn dort auch),
sollte dein programm aber ohne save/restore/i7 funktionieren, und mit den dreien den fehler ergeben, wärs natürlich ne interessante sache, kannst ja mal posten ;)




Re: T3 Blatt 11 2003-01-21 13:02
Slater
.. dachte ich mir, dass man in der ".rodata"-Sektion einfach eine Adresse angibt, in der das enthalten ist. Dort müsste das ja eigentlich gehen, oder?

and %l0, meinLabel, %l0

meinLabel: ".WelcherTypIstDasEigentlich?" 0xffff

so mal wieder das büchlein gefunden, da gibts doch so nette beispiele wie auf seite 53

.section ".rodata"

meinLabel: .half 0xffff

(wenns denn den typ gibt und das align kein ärger macht, .word wirds wohl auch tun)


.section ".text"



sethi %hi(meinLabel), %l4
or %l4, %lo(meinLabel), %l4

edit
dann also noch laden mit
ld [%l4] %l4
/edit

und dann

and %l0,%l4,%l0

(and funktioniert sicher nur mit registern)



Re: T3 Blatt 11 2003-01-21 13:14
TriPhoenix
.section ".rodata"

meinLabel: .halfword 0xffff

(wenns denn den typ gibt und das align kein ärger macht, .word wirds wohl auch tun)
.half :)

.section ".text"



sethi %hi(meinLabel), %l4
or %l4, %lo(meinLabel), %l4

und dann

and %l0,%l4,%l0
Das verANDet den Wert von l0 mit der Adresse von meinLabel, das willst du doch bestimmt nicht ;) Warum überhuapt den Aufwand und nicht gleich
sethi %hi(0xffff), %l4
or %l4, %lo(0xffff), %l4

(and funktioniert sicher nur mit registern)

AND funktioniert wie fast jeder Befehl mit 3 Registern oder 2 Registern und einem 13-bit-Wert. Leider ist 0xffff ein bissl zu groß [img]http://www.fb18.de/gfx/28.gif[/img]

Re: T3 Blatt 11 2003-01-21 13:15
Zaphod
Hmm… irgendwie funktioniert das immer noch nicht… ich erhalte dann ein Ergebnis von fffefffe, was mir doch ein wenig groß erscheint.. kann man dieses Löschen des Übertrags nicht eigentlich auch so lösen?

sll %i0, 16, %i0
srl %i0, 16, %i0

dooferweise klappt das bei mir immer noch nicht, aber… wenn ich wüsste, dass es nicht daran liegt, dann wäre ich schonmal einen Schritt weiter [img]http://www.fb18.de/gfx/22.gif[/img]

Re: T3 Blatt 11 2003-01-21 13:18
Zaphod
heul
sethi %hi(0xffff), %l4
or %l4, %lo(0xffff), %l4

jetzt krieg ich ffffdb56…

Re: T3 Blatt 11 2003-01-21 13:24
Slater
Hmm… irgendwie funktioniert das immer noch nicht… ich erhalte dann ein Ergebnis von fffefffe, was mir doch ein wenig groß erscheint.. kann man dieses Löschen des Übertrags nicht eigentlich auch so lösen?

sll %i0, 16, %i0
srl %i0, 16, %i0

dooferweise klappt das bei mir immer noch nicht, aber… wenn ich wüsste, dass es nicht daran liegt, dann wäre ich schonmal einen Schritt weiter [img]http://www.fb18.de/gfx/22.gif[/img]
das klappt dummerweise nicht, weil die stellen weiter links gemerkt werden, wenn ich mich recht erinnere,

or %g0, 0xff,%l4
sll %l4, 8, %l4
add %l4, 0xff, %l4

sollte es aber tun, so mal als weitere alternative.. ;)




Re: T3 Blatt 11 2003-01-21 13:24
TriPhoenix
heul
sethi %hi(0xffff), %l4
or %l4, %lo(0xffff), %l4

jetzt krieg ich ffffdb56…

Hast du denn auch bim allerletzten umdrehen der Bits nochmal maskiert?

Re: T3 Blatt 11 2003-01-21 13:32
Zaphod
hüstel… nein

Re: T3 Blatt 11 2003-01-21 13:33
Fred
meinLabel: .halfword 0xffff

sethi %hi(meinLabel), %l4
or %l4, %lo(meinLabel), %l4

and %l0,%l4,%l0
Den Fehler habe ich auch erst gemacht. Womit andest Du? Mit der ADRESSE des Labels. Das willst Du aber nicht, Du willst mit 0xffff anden. Also:

sethi %hi(0xffff), %l4
or %l4, %lo(0xffff), %l4

and %l0,%l4,%l0


Re: T3 Blatt 11 2003-01-21 15:29
Anonymer User
HMppf so ich hatte save/restore entfernt, klappte ganz gut,
aber leider kam immer der gleiche WErt raus

Allerdings habe ich jetzt so lange an meinem Code rumgefisselt,
das ich leider nur noch 'nen Bus Error kriege.

Daher meine Frage:

Wenn ich save/restore nicht benutze, wo steht dann die Adresse des Arrays und der Int-Wert???

In %i0,%i1 oder in %o0,%O0??

Re: T3 Blatt 11 2003-01-21 15:31
Digital Juhnke
oops vergessen mich einzuloggen…

Re: T3 Blatt 11 2003-01-21 15:41
TurboP
Wenn du save/restore nicht benutzt, steht das da, wo du es im Hauptprogramm reingeschrieben hast, weil er ja die selben Register verwendet :-)

Wenn du die main() in C geschrieben hast, dann steht die Adresse des Arrays in %o0 und die Anzahl der Elemente dann in %o1

Re: T3 Blatt 11 2003-01-21 15:56
XPhilosoph
Slater schrieb:
* am ende das ergebnis noch einer-invertieren,

Und das heißt ? In meiner Übungsgruppe wurde nix davon erwähnt…

Außerdem:
Sehe ich das richtig, daß der gleiche Übertrag nicht zweimal "überlaufen" kann??

Re: T3 Blatt 11 2003-01-21 16:16
Zaphod
Einer-Invertieren soll wohl heißen, dass ud das Einer-Komplement bilden sollst, wie in der Aufgabe gefordert. Das machst du, indem du jedes Bit deines Ergebnisses invertierst , d.h.
xnor %l0, %g0, %l0
wenn dein Ergebnis in %l0 steht.

Sehe ich das richtig, daß der gleiche Übertrag nicht zweimal "überlaufen" kann??
Ja, denn wen du zwei zahlen addierst, dann taucht sicherlich irgendwo eine Null auf, wenn du einen Übertrag hattest. Wird nun noch die Eins addiert, dann kommt es höchstens zu einem "Überlauf, bis zu dieser Null".

Re: T3 Blatt 11 2003-01-21 16:38
XPhilosoph
Danke, Zaphod, hatte es mir just genauso gedacht. [img]http://www.fb18.de/gfx/28.gif[/img]

Bleibt eigentlich nur noch die Frage:
Wo ist eigentlich der unterschied zwischen 1- und 2-Komplement?

Beim 1-K. werden alle invertiert, beim 2-K. ebenso, aber es wird einer addiert?!?

Re: T3 Blatt 11 2003-01-21 17:09
Zaphod
jupp, genau das ist der Unterschied!

Re: T3 Blatt 11 2003-01-21 17:32
Digital Juhnke
oh yeah finally it's working.

danke sehr.

[img]http://www.fb18.de/gfx/15.gif[/img]

Re: T3 Blatt 11 2003-01-21 17:41
Anonymer User
Nur ne kurze Frage:

andcc %l2, %l3, %l4

In welchem Register wird der Carry abgespeichert???




Re: T3 Blatt 11 2003-01-21 18:08
XPhilosoph
Im Prozessorstatusregister. Davon abhängig wird z.B. bei den Branch-Befehlen verzweigt oder auch nicht.

Re: T3 Blatt 11 2003-01-21 18:45
TriPhoenix
Nur ne kurze Frage:

andcc %l2, %l3, %l4

In welchem Register wird der Carry abgespeichert???

Aber nur der Carry vom 32ten Bit, leider nicht der vom 16ten den wir hier gebrauchen könnten…



Re: T3 Blatt 11 2003-01-21 20:54
Slater
hmm sei doch froh, dass das ne 32bit-maschine ist,

wieso dieser rückschrittliche wunsch, den ein paar hilfbefehle auch erfüllen können [img]http://www.fb18.de/gfx/24.gif[/img]

Re: T3 Blatt 11 2003-01-21 21:10
TriPhoenix
hmm sei doch froh, dass das ne 32bit-maschine ist,

Bin ihc ja auch :) Wollte nur darauf hinweisen…mit dem Carry-Bit wäre es fast nur umständlicher geworden…32 bit sind shcon was feines [img]http://www.fb18.de/gfx/28.gif[/img]



Re: T3 Blatt 11 2003-01-21 23:10
Fred
or %g0, 0xff,%l4
sll %l4, 8, %l4
add %l4, 0xff, %l4

sollte es aber tun, so mal als weitere alternative.. ;)
Ich hab noch ne Alternative gefunden [img]http://www.fb18.de/gfx/7.gif[/img]

sub %g0, 1, %l4
srl %l4, 16, %l4


Re: T3 Blatt 11 2003-01-25 22:59
Anonymer User
Irgendwie hab ich noch nicht genau kapiert, wann ich eine 1 drauf addieren soll und wann ich alle Bits invertieren soll.
Ich hab den Code erstmal in C geschrieben.
Kann mir einer sagen, wo der Fehler liegt?

#include <stdio.h> unsigned short pruefsumme(unsigned short data[], unsigned short anz) { int summe; for(int i=0; i<anz; i++) { summe += data[i]; if((0x00010000 & summe) == 0x00010000) { summe &= 0x00001111; summe += 1; } } summe = ~summe; return summe; } int main() { unsigned short bitstrom[ 16] = {0x866d, 0xc059, 0x866d, 0xc0d7, 0x0006, 0x0018, 0x8cba, 0x0009, 0x847a, 0xfb43, 0x0000, 0x6002, 0x2238, 0x0000, 0x0204, 0x05b4}; unsigned short ergebnis; ergebnis = pruefsumme(bitstrom, 16); printf("Pruefsumme : %0x\n", ergebnis); return 0; }

Re: T3 Blatt 11 2003-01-25 23:18
Anonymer User
Ok, ich hab die Fehler schon entdeckt.
Es funktioniert jetzt …

Re: T3 Blatt 11 2003-01-25 23:58
Fred
Irgendwie hab ich noch nicht genau kapiert, wann ich eine 1 drauf addieren soll und wann ich alle Bits invertieren soll.
Um negative Zahlen darstellen zu koennen, gibt es drei Moeglichkeiten. Ich beschraenke mich hier der Einfachheit halber auf 16 Bit Zahlen.

a) Sign (1 Bit) getrennt vom Wert speichern, z.B. 0000000000001100 bin = 12 dez, 1000000000001100 bin = -12 dez. Der Wertebereich geht von -32767 bis +32767, die Null kommt doppelt vor (einmal positiv und einmal negativ). So gespeicherte Zahlen lassen sich (relativ) einfach multiplizieren und dividieren, Addition und Subtraktion ist dagegen aufwendig.

b) Einerkomplement: positive Zahlen werden wie gehabt gespeichert. Um eine negative Zahl zu speichern (z.B. -12), nimmt man einfach das Bitmuster des Wertes (12 dez = 0000000000001100 bin) und invertiert alle Bits (1111111111110011). Der Wertebereich ist der gleiche wie bei a), und auch hier erkennt man negative Zahlen am MSB (most significant Bit). Der Wert der Zahl ist aber jetzt nicht mehr so direkt fuer den Menschen sichtbar. Beim Einerkomplement ist die Addition nicht trivial: ein eventuell auftretender Ueberlauf muss nach der Addition zusaetzlich addiert werden. Beispiel:

_1111111111110011 = -12
_1111111111110010 = -13
CS—————
11111111111100101 ("Carry" ist in Bit 16)
________________1 ("Carry" addieren)
—————–
_1111111111100110 = -25

Das Ergebnis wurde wieder auf 16 Bit zurechtgeschnibbelt, d.h. das "Carry" geloescht. Was man sofort sieht ist, dass das Ergebnis negativ ist (MSB = 1). Um nun das Ergebnis zu ueberpruefen, invertieren wir die Bits wieder: 1111111111100110 bin ^ 1111111111111111 bin = 0000000000011001 bin = 25 dez. Stimmt also!

c) Zweierkomplement: positive Zahlen wie gehabt, negative Zahlen in zwei Schritten ermittelbar: zuerst invertiert man alle Bits (d.h. man bildet das Einerkomplement), und anschliessend addiert man 1. Dann kann eine Addition "einfach so" durchgefuehrt werden. Das gleiche Beispiel mit -12 und -13 im Zweierkomplement:

_1111111111110100 = -12
_1111111111110011 = -13
CS—————
11111111111100111 (das Carry interessiert uns im Zweierkomplement nicht)
—————–
_1111111111100111 = -25

Um das Ergebnis zu checken (d.h. aus dem offensichtlich negativen Ergebnis den Wert zu lesen), bilden wir erneut das Zweierkomplement: 1111111111100111 -> 0000000000011000 -> 0000000000011001 = 25

unsigned short pruefsumme(unsigned short data[], unsigned short anz) {
Es gibt keinen Grund, die Laenge eines unsigned short Arrays auf unsigned short zu beschraenken. Es gibt schliesslich Dateien groesser als 64K ;-)

int summe;
Du initialisierst summe nicht, d.h. der Inhalt von summe und somit auch das Ergebnis sind nicht determiniert. Im Gegensatz zu Java initialisiert C nicht automatisch angelegte Variablen.

for(int i=0; i<anz; i++) {
summe += data;
if((0x00010000 & summe) == 0x00010000) {
summe &= 0x00001111;
summe += 1;
}
}
summe = ~summe;
return summe;
}
Der Fehler liegt im Ausmaskieren des Carrybit. Du moechtest 16 Bits "stehen lassen", laesst aber nur 4 stehen. Die richtige Bitmaske lautet 0xFFFF (oder 0x0000FFFF wenn Dir das besser gefaellt).

Ich habe das Programm mit den korrigierten Fehlern jetzt nicht ausprobiert, kannst ja sagen ob es jetzt klappt oder nicht.




Re: T3 Blatt 11 2003-01-25 23:59
Fred
Ok, ich hab die Fehler schon entdeckt. Es funktioniert jetzt …
Na super, alles umsonst getippert [img]http://www.fb18.de/gfx/22.gif[/img]


Re: T3 Blatt 11 2003-01-26 14:15
XPhilosoph
Na super, alles umsonst getippert [img]http://www.fb18.de/gfx/22.gif[/img]

Also ich fands schön [img]http://www.fb18.de/gfx/15.gif[/img]!

Warum erklärte das Möller nicht so…?