-         

Ergebnis 1 bis 6 von 6

Thema: Simple Division mit AVR

  1. #1
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    24.02.2004
    Ort
    Starnberg
    Alter
    40
    Beiträge
    170

    Simple Division mit AVR

    Anzeige

    Hallo zusammen,

    Ich habe eine ziemlich einfache Frage: Ich möchte mit einem Tiny26 eine 8-Bit Zahl durch eine 8-Bit Zahl teilen (Assembler). Für die 16/8 habe ich leider nicht mehr genügend Register. Mein Wertebereich erfordert das auch nicht. Momentan bin ich wohl zu blöd, im Internet oder hier im Forum passenden Code zu finden. Wenn mir bitte jemand weiterhelfen könnte...

    Danke, Martin

  2. #2
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    06.11.2004
    Beiträge
    1.693
    Würde es dir helfen, wenn ich das ganze mit Bascom schreibe und den Assemblercode poste?
    Ich denke 16/8 (bit) geht da auch?!

  3. #3
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    24.02.2004
    Ort
    Starnberg
    Alter
    40
    Beiträge
    170
    Danke für das Angebot, aber ich habe asm-Code für 16/8, der mir aber leider ein Register zuviel benutzt. Wird Bascom nicht anders machen, denke ich.

    Grüsse, Martin

  4. #4
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    10.12.2004
    Ort
    LEV
    Beiträge
    505
    Hi Martin,
    hier zwei Routinen aus einer ATMEL-AVR Applikation Note.
    Einmal eine 8/8 Division ohne Vorzeichen (unsigned)
    Einmal eine 8/8 Division mit Vorzeichen (signed)
    Die verwendeten Register kannst du dir ja leicht selbst anpassen

    Gruß Jan

    Code:
    ;***************************************************************************
    ;*
    ;* "div8u" - 8/8 Bit Unsigned Division
    ;*
    ;* This subroutine divides the two register variables "dd8u" (dividend) and 
    ;* "dv8u" (divisor). The result is placed in "dres8u" and the remainder in
    ;* "drem8u".
    ;*  
    ;* Number of words	:14
    ;* Number of cycles	:97
    ;* Low registers used	:1 (drem8u)
    ;* High registers used  :3 (dres8u/dd8u,dv8u,dcnt8u)
    ;*
    ;***************************************************************************
    
    ;***** Subroutine Register Variables
    
    .def	drem8u	=r15		;remainder
    .def	dres8u	=r16		;result
    .def	dd8u	=r16		;dividend
    .def	dv8u	=r17		;divisor
    .def	dcnt8u	=r18		;loop counter
    
    ;***** Code
    
    div8u:	sub	drem8u,drem8u	;clear remainder and carry
    	ldi	dcnt8u,9	;init loop counter
    d8u_1:	rol	dd8u		;shift left dividend
    	dec	dcnt8u		;decrement counter
    	brne	d8u_2		;if done
    	ret			;    return
    d8u_2:	rol	drem8u		;shift dividend into remainder
    	sub	drem8u,dv8u	;remainder = remainder - divisor
    	brcc	d8u_3		;if result negative
    	add	drem8u,dv8u	;    restore remainder
    	clc			;    clear carry to be shifted into result
    	rjmp	d8u_1		;else
    d8u_3:	sec			;    set carry to be shifted into result
    	rjmp	d8u_1
    
    
    
    ;***************************************************************************
    ;*
    ;* "div8s" - 8/8 Bit Signed Division
    ;*
    ;* This subroutine divides the two register variables "dd8s" (dividend) and 
    ;* "dv8s" (divisor). The result is placed in "dres8s" and the remainder in
    ;* "drem8s".
    ;*  
    ;* Number of words	:22
    ;* Number of cycles	:103
    ;* Low registers used	:2 (d8s,drem8s)
    ;* High registers used  :3 (dres8s/dd8s,dv8s,dcnt8s)
    ;*
    ;***************************************************************************
    
    ;***** Subroutine Register Variables
    
    .def	d8s	=r14		;sign register
    .def	drem8s	=r15		;remainder
    .def	dres8s	=r16		;result
    .def	dd8s	=r16		;dividend
    .def	dv8s	=r17		;divisor
    .def	dcnt8s	=r18		;loop counter
    
    ;***** Code
    
    div8s:	mov	d8s,dd8s	;move dividend to sign register
    	eor	d8s,dv8s	;xor sign with divisor
    	sbrc	dv8s,7		;if MSB of divisor set
    	neg	dv8s		;    change sign of divisor
    	sbrc	dd8s,7		;if MSB of dividend set
    	neg	dd8s		;    change sign of divisor
    	sub	drem8s,drem8s	;clear remainder and carry
    	ldi	dcnt8s,9	;init loop counter
    d8s_1:	rol	dd8s		;shift left dividend
    	dec	dcnt8s		;decrement counter
    	brne	d8s_2		;if done
    	sbrc	d8s,7		;    if MSB of sign register set
    	neg	dres8s		;        change sign of result
    	ret			;    return
    d8s_2:	rol	drem8s		;shift dividend into remainder
    	sub	drem8s,dv8s	;remainder = remainder - divisor
    	brcc	d8s_3		;if result negative
    	add	drem8s,dv8s	;    restore remainder
    	clc			;    clear carry to be shifted into result			
    	rjmp	d8s_1		;else
    d8s_3:	sec			;    set carry to be shifted into result
    	rjmp	d8s_1

  5. #5
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    24.02.2004
    Ort
    Starnberg
    Alter
    40
    Beiträge
    170
    Danke, sowas hab ich gesucht!

    Martin

  6. #6
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    24.02.2004
    Ort
    Starnberg
    Alter
    40
    Beiträge
    170
    Hallo nochmal,

    ich hab mir eine "Minimalversion" gebastelt. Nicht besonders getestet, aber für meine Zwecke funktionierts:

    "Poor man´s division" Kein Rest, kein nix. Für kleine Zahlen denke ich OK.
    Ergebnis momentan in temp3 und temp1.

    Code:
    pmd:	     ;temp1/temp2 unsigned
    		clr temp3
    pm1:
    		inc temp3
    		sub temp1, temp2
    		brcc pm1
    		mov temp1, temp3
    		ret
    Ciao, Martin

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •