Anmelden

Archiv verlassen und diese Seite im Standarddesign anzeigen : Rechnen und Ausgeben von Binärcodes



kundesbanzler
20-10-2005, 20:04
Moin,

ich will einem EPROM multiplizieren beibringen, und zwar je 8 Bit mit 8 Bit. Das Ergebnis soll wieder auf 8 Bit gekürzt werden (natürlich auf die 8 höherwertigen Bit). Hierfür brauche ich einfach nur eine Binärdatei(!! keine ASCII oder Hex-Datei!) mit allen möglichen Multiplikationen (sind 65536 mögliche Kombinationen..) und genau dafür will ich ein C-Programm schreiben. Nun programmiere ich im Allgemeinen eher µCs und habe null Plan, wie ich eine Binärdatei erzeugen kann. Auch wollen meine bisherigen Versuche die Binärzahlen nicht richtig multiplizieren (was vielmehr daran liegt, dass ich keine Ahnung habe, wie ich die richtig ausgeben muss.. :/).

Nun wäre ich sehr dankbar, wenn mir hier jemand ein Beispielprogramm zum Rechnen mit Binärzahlen schreiben würde und mir möglicherweise auch gleich erklären könnte, wie ich die Binärdatei erstellen könnte (wichtig dabei ist auch, dass die Datei nicht jedesmal überschrieben werden soll, sondern jeder Wert eine neue Zeile bekommen muss).

SeeksTheMoon
20-10-2005, 20:56
Die Multiplikation im Binärsystem läuft mit den Shiftoperatoren und wenn Du die ganzen Ergebnisse in einer Binärdatei speichern willst, dann musst Du zum Schreiben die Funktion fwrite benutzen anstatt fputc oder fprintf.

Am einfachsten ist es erstmal, die Zahlen alle dezimal zu multiplizieren und dann die Ergebnisse in Binärzahlen umzuwandeln.
Das geht mit einem Bitmaskenvergleich mit besagtem Shiftoperator:

Du nimmst die Dezimalzahl und die Zahl 1. Dann schiebst Du bei der 1 die 1 von der niedrigsten auf die höchste Stelle und dann machst Du in einer Schleife einen binären Vergleich der Maske mit der Zahl und shiftest die 1 wieder runter.

So könntest Du die Zahl binär ausgeben. Die Speicherung kannst Du z.B. in einem struct machen oder in einem Array und das dann in die Datei schreiben

kundesbanzler
20-10-2005, 21:58
Also wenn ich das richtig verstanden habe, schiebe ich einfach die 1 so lange, bis die dez-Zahl nicht mehr durch die bin-Zahl teilbar ist. Wenn ich das erreicht habe, schiebe ich die 1 wieder um eins nach rechts und füge eine neue 1 ein, durch die ich dann den Rest der ersten Division (wieder mit hin-und-her schieben) dividiere, bis der Rest 0 ist? Hmm.. Also wenn ich das jetzt nicht komplett falsch verstanden habe, verstehe ich zumindest mal das Prinzip.. Kann ich das hin-und-her-schieben nicht auch am einfachsten mit einem Array realisieren?

Die andere Frage wäre: wie definiere ich eine Binärzahl? Hab' darüber nichts gefunden, einfach mit 0x00100010 (als Bsp.)? die muss dann auch als unsigned char gespeichert werden, sonst wird mir das Binärfile zu groß, oder speichert fwrite sowieso alles im Binärformat ab, unabhängig vom Datentyp?

Aber danke erstmal, werde mich dann gleich morgen wieder dransetzen :)

SeeksTheMoon
21-10-2005, 09:34
fwrite speichert immer binär, die anderen immer Text.

Du machst keine Division durch die 1-Zahl (Bitmaske), sondern einen binärvergleich:

Du hast zuerst 0000 0001, das ist 1. Dann schiebst Du die 1 ganz nach links (<<), so dass Du 1000 0000 hast und dann benutzt Du einen Binärvergleich (&) mit Deiner Dezimalzahl (dem Rechenergebnis).
Im Rechner sieht das dann z.B. so aus:
erster Schritt:

1001 0110 <- unbekanntes Ergebnis in interner Darstellung
& 1000 0000 <- unsere Bitmaske
Vergleich ist 1, also true, weil an beiden Stellen eine 1 steht. Die erste Zahl im Array wird eine 1.
Die Bitmaske einmal nach rechts shiften (>>) und wieder vergleichen:

1001 0110
& 0100 0000
diesmal 0, false -> nächste Zahl im Array wird 0 usw.

Der & Operator funktioniert wie ein UND-Gatter: Sind zwei Einser da, kommt 1 raus, sonst nicht.

kundesbanzler
21-10-2005, 14:18
Das mit fwrite ist schonmal gut zu wissen, danke :)

Und ich kann eine Dezimalzahl wirklich mit dieser Bitmaske UND-verknüpfen? Hab ich das richtig verstanden? (sry, hab's normalerweise mehr mit µCs, da hab' ich selten solche Probleme..).

SeeksTheMoon
22-10-2005, 09:45
sicher, dafür ist der Operator ja da. Die Dezimalzahl und die 1 haben auch den gleichen Datentyp, da ist das eh kein Problem.
Falls Du float-Zahlen binär umwandeln willst, dann wird es etwas wilder, weil deren interner Aufbau ja etwas wilder ist.

kundesbanzler
22-10-2005, 17:27
So, hab ein wenig herumexperimentiert und bin am Ende irgendwie doch auf Binärzahlen gekommen. Allerdings ohne den UND-Operator, aber mit einem Ähnlichen Verfahren. Die Ausgabe mit printf funktioniert hier tadellos, aber mit fwrite habe ich noch Probleme. Und zwar lässt sich das c-File normal kompilieren, aber nicht ausführen, ich bekomme nur die Meldung "Speicherzugriffsfehler"..

Ich hänge die Datei mal an (sitze hier leider an einem Windowsrechner, der formatiert die Datei grauenhaft, sonst würde ich sie hier reinkopieren), wäre super wenn es mal jemand ausprobieren könnte.

Achja, kann es sein, dass dieser Speicherzugriffsfehler damit zusammenhängt, dass ich das alles unter Knoppix kompiliere? Habe hier leider keinen Linux-Rechner, bin erst ab morgen Abend wieder zuhause..

So, hoffe, das mit dem Anhang funktioniert und lässt sich auch im VI-Editor oä. richtig darstellen..

Danke schonmal im Voraus :)

SeeksTheMoon
23-10-2005, 10:13
Du benutzt den sizeof operator nicht korrekt:
Normalerweise müsste es sizeof(d) heißen, aber das sollte der Compiler eigentlich anmeckern.
Ansonsten sieht die Dateiverarbeitung auf den ersten Blick richtig aus.

Was ich nicht verstehe: Wenn die zahl 8 Bit hat, warum nimmst Du dann nur ein Array der Größe 7?

kundesbanzler
23-10-2005, 12:29
Hmm, ja, das mit dem kleinen Array war von Anfang an irgendwie Falsch. Hab' an 0-7 gedacht und den Fehler danach nicht mehr bemerkt; komischerweise ging es mit printf trotzdem :confused:

Danke für den Hinweis auf sizeof(d), es hat leider nichts geholfen. Naja, ich werde das ganze bis heute Abend ruhen lassen und dann auf einem installierten Linux-System ausprobieren. Wahrscheinlich liegt's eh am Knoppix.

Auf jeden Fall vielen Dank für deine Hilfe! :)

locus vivendi
23-10-2005, 18:19
ich will einem EPROM multiplizieren beibringen, und zwar je 8 Bit mit 8 Bit. Das Ergebnis soll wieder auf 8 Bit gekürzt werden (natürlich auf die 8 höherwertigen Bit). Hierfür brauche ich einfach nur eine Binärdatei(!! keine ASCII oder Hex-Datei!) mit allen möglichen Multiplikationen (sind 65536 mögliche Kombinationen..)
Hmm... willst du die wirklich alle abspeichern? Ich kenne ehrlich gesagt keinen Mikrocontroller, der so viel EEPROM-Platz hat, aber nicht auch 8 Bit multiplizieren könnte.

nobody0
24-10-2005, 02:04
In einem externen Speicher wie einer MMC oder SDC kann man sowas unterbringen. Man kann natürlich auch sowas wie einen ARM9-Prozessor mit reichlich RAM, Flash und einigen hundert Megahertz Takt nehmen, aber wegen den langsamen Speicher-Zugriffen ist eine Funktion sicherlich schneller.

kundesbanzler
24-10-2005, 06:16
Nein, ich will einfach nur einen EPROM (sogar noch einen alten UV-EPROM) mit 512kbit Speicher mit dem File füttern. Der braucht nur multiplizieren können, das ganze soll als eine Art Laboraufbau für eine Schule dienen. In die Schaltung sind 2 CPLDs, ein EPROM, ein RAM und ein µC integriert, wobei man auch alles in einem einzigen µC oder Signalprozessor unterbringen könnte. Allerdings geht's bei dem ganzen um den Lerneffekt.

So, und das Programm funzt noch immer nicht, auch nicht auf einem installierten Debian-System. Findet wirklich keiner einen Fehler? :/

pyrorl
24-10-2005, 07:42
Wahrscheinlich ist dein d[] noch zu klein, mach mal d[8] daraus.

kundesbanzler
24-10-2005, 21:59
Funzt leider auch mt d[8] nicht :( der "neue" Error lautet:



*** glibc detected *** double free or corruption (top): 0x0804a008 ***
Abgebrochen


:confused:


Achja, der erste Error (Speicherzugriffsfehler oder so) trat bei Knoppix auf, der oben genannte ist mit dem absolut gleichen Programm unter Debian (gcc4.0.2-2).

nobody0
24-10-2005, 23:37
Du solltest einen Debugger nehmen.

pyrorl
25-10-2005, 05:51
Bei mir lässt sich das kompilieren und sogar ausführen:



orlando@giacomo ~ $ gcc -Wall -o prog2 prog2.c
orlando@giacomo ~ $ ./prog2
[...]
11111011
11111100
11111101
11111110
orlando@giacomo ~ $


Außerdem steht in deinem Quelltext nichts, was diesen Fehler verursachen könnte, hast du mitlerweile was geändert?

kundesbanzler
27-10-2005, 23:46
Hmm, scheinbar habe ich euch das falsche File hochgeladen, in dem war noch die Ausgabe mittels printf, sry.. Hier nochmal der aktuelle Quelltext:


#include <stdio.h>
#include <stdlib.h>

int main()
{
FILE *eprom = fopen("eprom", "r+");
int a, b=0, c, i, e, d[8], f;
for(a=0;a<256;a=a+1)
{
for(b=0;b<256;b=b+1)
{
c=(a*b)/256;
for(i=0;i<8;i=i+1)
{
f=256;
for(e=0;e<=i;e=e+1)
{
f=f/2;
}
if(c-f>=0)
{
c=c-f;
d[i]=1;
}
else
{
d[i]=0;
}
fwrite(d,1,sizeof(d), eprom);
fclose(eprom);
}
}
}
return 0;
}


Hoffe, jemand kann was damit anfangen..

SeeksTheMoon
28-10-2005, 11:10
Warum machst Du nach dem write direkt ein close? Die Schleife läuft noch weiter und stolpert sofort weil die file freigegeben wurde.
Mach das close am Ende des Programms.

kundesbanzler
28-10-2005, 17:52
Hmm, ich komme mir gerade ziemlich blöd vor. Eigentlich gehört das fwrite auch außerhalb der for-Schleife, welche für die Generierung der Binärzahl zuständig ist.. :o
Jedenfalls lässt sich die Datei jetzt erzeugen, allerdings ist sie 16(!)MB groß.. Naja, kann mir jemand einen guten Editor für Binärfiles empfehlen?

nobody0
29-10-2005, 00:15
khexedit ist sehr gut; der kann eine Datei auch als C-Array ausgeben.

kundesbanzler
29-10-2005, 08:53
Thx, war zwar etwas lästig, die ganzen kde-libs mitzuinstallieren, aber wenigstens kann ich jetzt sehen, dass die erzeugte Datei kompletter Nonsens ist..:(

Ich schau dann heute am Nachmittag, ob ich das ganze irgendwie noch zum Laufen bringe.. Irgendwie habe ich das Gefühl, dass es bald einfacher wäre, das ganze händisch einzugeben..:p

Joghurt
29-10-2005, 11:42
ich will einem EPROM multiplizieren beibringen, und zwar je 8 Bit mit 8 Bit. Das Ergebnis soll wieder auf 8 Bit gekürzt werden (natürlich auf die 8 höherwertigen Bit).Wieso auf die 8 höherwertigen bits?

Falls es auch die 8 niederwertigen Bits sein dürfen, nimm doch diese Funktion (dachte erst, dass du einem miniprozzi multiplizieren beibrigen wolltest, deshalb das register)


unsigned char mul(unsigned char a, unsigned char b)
{
register unsigned char c;
if (a>b) {
c = a;
a = b;
b = c;
}
c=0;
for( ; a ; a>>=1,b<<=1) {
if (a&1)
c += b;
}
return c;
}

kundesbanzler
29-10-2005, 12:29
Also das, was du da jetzt gerechnet hast, verstehe ich überhaupt nicht, sry :confused:

Naja, die 8 höherwertigen Bit deshalb, weil das Ergebnis ansich ja eine 16Bit-Zahl ist. Wenn ich diese 16 Bit auf 8 Bit kürze, sind es die 8 höherwertigen, die signifikant sind, nicht die 8 niederwertigen.
Und das, was ich brauche, ist einfach nur eine Binärdatei mit 65k*8 0en und 1en, die exakt (auf den Bit genau) 512kBit groß sein muss. Da ich mir die Mühe nicht machen will, alles extra in einen Hex Editor einzugeben, will ich das eben durch ein kleines Programm für mich erledigen lassen ;)

Joghurt
29-10-2005, 12:40
Also das, was du da jetzt gerechnet hast, verstehe ich überhaupt nicht, sry :confused: Ich dachte zuerst, du brauchst dieses Array, weil du mit einem Mikroprozessor multiplizieren willst; ich wollte einfach nur zeigen, wie du die Binäre Multiplikation implementierst.


Wenn ich diese 16 Bit auf 8 Bit kürze, sind es die 8 höherwertigen, die signifikant sind, nicht die 8 niederwertigen.2*128 = 1... Nagut


Und das, was ich brauche, ist einfach nur eine Binärdatei mit 65k*8 0en und 1en, die exakt (auf den Bit genau) 512kBit groß sein muss.Willst du jedes Bit einzeln als Byte gespeichert haben? Oder wie oder was?
Eine 512kBit große Datei mit dem gewünschten Ergebnis bekommst du so:
#include <stdio.h>
int main()
{
FILE* f;
char mul[256][256];
int a,b,c;
char d;
f = fopen("multable","wb");
for (a=0;a<256;a++) for (b=0;b<256;b++) mul[a][b] = (a*b)/256; // so? Dann wäre 1*1 = 0, da das höherwertige Byte 0 ist.
// Ansonsten mul[a][b] = a*b;
fwrite(mul,sizeof(mul),1,f);
fclose(f);
}Falls du möchtest, dass in der Datei jedes Bit einzeln ein Byte einnimmt, also in der Art
00 01 00 01 01 01 00, dann ersetze den fwrite durch
for(a=0;a<256;a++) for(b=0;b<256;b++) for(c=7;c>=0;c--) {d = (mul[a][b]>>c)&1;fwrite(d,1,1,f);}

kundesbanzler
29-10-2005, 13:33
Verdammt, ich hab ganz vergessen, dass fwrite ja sowieso alles im Binärformat speichert o.O

Danke jedenfalls, die Datei passt exakt (und ist genau 65536Byte (=512kBit) groß), danke vielmals :)

Das Programm hab ich übrigens gleich 1:1 übernehmen können, hat auch alles gepasst..
Danke an alle für die Einführung in fwrite, ich glaube, ich hab's jetzt endlich kapiert..:p

Und wegen der Datei, naja, das EPROM legt für jede Zeile eine Adresse an, dh. man kann durch geeignete Wahl der Adressleitungen direkt die zwei 8bit-Zahlen an den Adressport liefern.