8-Bit Mal-Rechnen
-
Hallo zusammen!
Ich veruche gerade ein Programm in Assembler(uC-Familie: 8051) zu schreiben.
Das Programm soll 2 8 Bit-Zahlen multiplizieren mit der "Verschiebetechnik".Angabe:
Multiply 2 8-Bit values R0 and R1 with the shift and add method. The
result has to be returned also in (R0,R1) with R0 Low-Byte and R1 High-Byte. The
method will be explained in the lecture.Mein Code:
NAME arithlib_MAIN ;benennen des modules ;Hier werden Segmente eines bestimmten Segmenttyps definiert MAIN_SUB segment CODE ; MAIN_SUB für Programmspeicher DATEN segment DATA ; DATEN für indirekter interner RAM STACK segment IDATA ; STACK für indirekter interner RAM stacksize equ 10 ; stacksize=10 ;---------reset--------- cseg at 0 jmp MAIN ; sprung ins Hauptprogramm ;--------stack---------- rseg STACK ; mit rseg kann man diese "Speichersegmente" auswählen ds stacksize ; reserviert 10 Bytes für stack ;--------reservieren-------- rseg DATEN ; mit rseg kann man diese "Speichersegmente" auswählen mult: ds 1 wert: ds 1 zwischenspeicher: ds 1 rseg MAIN_SUB ;-------main-------- MAIN: mov sp,#STACK-1 mov sp,#stack-1 call mult_8bit ;call mult_16bit STATICRUN: JMP $ mult_8bit: mov r0,zwischenspeicher mov a,mult mov r1,#0 jb acc.0,shift1 rlc R0 jnb acc.0,null1 shift1: rlc R0 null1: jb acc.1,shift2 rlc R0 jnb acc.1,null2 shift2: push a mov a,zwischenspeicher add a,r0 mov zwischenspeicher,a rlc R0 null2: jb acc.2,shift3 rlc R0 jnb acc.2,null3 shift3: push a mov a,zwischenspeicher add a,r0 mov zwischenspeicher,a rlc R0 null3: jb acc.2,shift4 rlc R0 jnb acc.2,null4 shift4: push a mov a,zwischenspeicher add a,r0 mov zwischenspeicher,a rlc R0 null4: jb acc.2,shift5 rlc R0 jnb acc.2,null5 shift5: push a mov a,zwischenspeicher add a,r0 mov zwischenspeicher,a rlc R0 null5: jb acc.2,shift6 rlc R0 jnb acc.2,null6 shift6: push a mov a,zwischenspeicher add a,r0 mov zwischenspeicher,a rlc R0 null6: jb acc.2,shift7 rlc R0 jnb acc.2,null7 shift7: push a mov a,zwischenspeicher add a,r0 mov zwischenspeicher,a rlc R0 null7: jb acc.2,shift8 rlc R0 jnb acc.2,null8 shift8: push a mov a,zwischenspeicher add a,r0 mov zwischenspeicher,a rlc R0 null8: rlc R0 RET END
Ich finde der Code ist nicht wirklich richtig. rlc register geht doch nicht mal, da nur rlc acc funktioniert. Und Pop a gehört auch noch irgendwo hin, aber habe ich das Programm soweiso anders schreiben muss, dass es funktioniert.
Ich hab jetzt einfach 8mal verschoben, da man ja 8mal schieben muss bei der 8bit multiplikation. Und kann mir einer erklären was mit dem Carry hier passiert? Bzw. was ich machen muss mit dem?Und bitte gebt mir Tipps wie ich das programmieren kann.
Danke im voraus!
Es wird einfach R0*R1 gemacht. Und R0 wird immer um 1 nach links verschoben.
mfg achtbit
-
achtbit schrieb:
Multiply 2 8-Bit values R0 and R1 with the shift and add method. The result has to be returned also in (R0,R1) with R0 Low-Byte and R1 High-Byte. The method will be explained in the lecture.
Mir scheint, Du stehst wie der Ochs vorm Berg. Zumindest stehe ich so vor Deinem Programm :).
Zunächst musst Du Dir ohne Assembler klar werden, was zu tun ist. Am besten ist, Du machst mal eine russische Bauernmultiplikation (http://de.wikipedia.org/wiki/Russische_Bauernmultiplikation) mit 13*7 auf dem Papier. Dann machst Du dasselbe binär (13=00001101, 7=00000111). Der Trick ist, dass "Halbieren mit Abwärtsrundung" im Binärsystem gleich "shift right" und "Verdoppeln" gleich "shift left" ist. Verdoppeln kann man aber auch, indem man das Register mit sich selbst addiert (ADD A, acc). Der zweite Trick ist, dass Du mit der Addition nicht bis zum Schluss warten musst, sondern zwei Zahlen gleich addieren kannst. Mach das noch ein paar Mal mit verschiedenen Binärzahlen. Wenn Du Dir sicher bist, dass Du das geschnallt hast, dann versuche Dich am Assemblercode.
Es gibt noch (mindestens) eine weitere "shift and add method": Bei dieser Methode wird nicht der Multiplikator, sondern das Zwischenergebnis verdoppelt. Das läuft so ähnlich wie die Schulmethode der Multiplikation. Welche Methode Du anwenden sollst, "will be explained in the lecture".
Das Carry nimmt sowohl das herausgeschobene Bit auf wie auch den Überlauf bei einer Addition. Beachte, dass beim Schieben (bzw. Rotieren) das vorige Carry auch hineingeschoben wird. Wenn es notwendig werden sollte, dass auf jeden Fall eine '0' hineingeschoben werden muss, musst Du vorher das Carry mit 'CLR C' löschen.
Normalerweise gibt es tatsächlich nur den 'RLC A'-Befehl. Du musst also A sichern, A mit dem zu schiebenden Wert laden, schieben, geschobenes A abspeichern, gesichertes A zurückholen. Und überlegst Dir, wie Du ohne Sichern und Laden auskommen könntest. Vielleicht gibt es aber auch Prozessoren, die ein 'RLC R0' verarbeiten können. Guck in Deine Unterlagen, welchen 8051-Prozessor Du genau nehmen sollst.
viele grüße
ralph
-
So eine ähnliche Frage hatten wir schon mal:
http://www.c-plusplus.net/forum/280689Wichtig sind eigentlich nur die Linksverschiebung (und add) und die Überlegung, wie groß das Ergebnis sein darf.
Wie man guckt, ob man addieren muß oder nicht kann man so oder so hinbekommen.