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/280689

    Wichtig 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.


Anmelden zum Antworten