www.mikrocontroller.net

AVR Arithmetik

Inhaltsverzeichnis

[bearbeiten] Vergleich

[bearbeiten] 16 Bit

    ;
    ; Vergleiche < r16, r17 > mit < r20, r21 >
    ;
 
    cp    r16, r20
    cpc   r17, r21

[bearbeiten] 32 Bit

    ;
    ; Vergleiche < r16, r17, r18, r19 > mit < r20, r21, r22, r23 >
    ;
 
    cp    r16, r20
    cpc   r17, r21
    cpc   r18, r22
    cpc   r19, r23

[bearbeiten] Addition

[bearbeiten] 16 Bit + 16 Bit

    ;
    ; < r16, r17 > = < r16, r17 > + < r20, r21 >
    ;
 
    add   r16, r20
    adc   r17, r21

[bearbeiten] 32 Bit + 32 Bit

    ;
    ; < r16, r17, r18, r19 > = < r16, r17, r18, r19 > + < r20, r21, r22, r23 >
    ;
 
    add   r16, r20
    adc   r17, r21
    adc   r18, r22
    adc   r19, r23

[bearbeiten] Subtraktion

[bearbeiten] 16 Bit - 16 Bit

    ;
    ; < r16, r17 > = < r16, r17 > - < r20, r21 >
    ;
 
    sub   r16, r20
    sbc   r17, r21

[bearbeiten] 32 Bit - 32 Bit

    ;
    ; < r16, r17, r18, r19 > = < r16, r17, r18, r19 > - < r20, r21, r22, r23 >
    ;
 
    sub   r16, r20
    sbc   r17, r21
    sbc   r18, r22
    sbc   r19, r23

[bearbeiten] Division

[bearbeiten] 32 Bit / 32 Bit

Ergebnis gerundet, und mit Restbildung

.def	a0	= r16
.def	a1	= r17
.def	a2	= r18
.def	a3	= r19
 
.def	b0	= r20
.def	b1	= r21
.def	b2	= r22
.def	b3	= r23
 
.def	t0	= r24
.def	t1	= r25
.def	t2	= r26
.def	t3	= r27
.def	t4	= r28
 
;************************************************************************
;*                                                                      *
;*                      unsigned rounded division 32 bit                *
;*                                                                      *
;************************************************************************
 
urdiv32:
	mov	t0, b0		;T = B
	mov	t1, b1
	mov	t2, b2
	mov	t3, b3
	lsr	t3		;B / 2
	ror	t2
	ror	t1
	ror	t0
	add	a0, t0		;A = A + B / 2
	adc	a1, t1
	adc	a2, t2
	adc	a3, t3
 
;************************************************************************
;*                                                                      *
;*                      unsigned division 32 bit                        *
;*                                                                      *
;************************************************************************
 
; a3..0 = a3..0 / b3..0
; b3..0 = remainde
 
;cycle: max 684
 
udiv32:
	clr	t0
	clr	t1
	clr	t2
	clr	t3
	ldi	t4, 32
udi1:	lsl	a0
	rol	a1
	rol	a2
	rol	a3
	rol	t0
	rol	t1
	rol	t2
	rol	t3
	cp	t0, b0
	cpc	t1, b1
	cpc	t2, b2
	cpc	t3, b3
	brcs	udi2
	sub	t0, b0
	sbc	t1, b1
	sbc	t2, b2
	sbc	t3, b3
	inc	a0
udi2:	dec	t4
	brne	udi1
	mov	b0, t0
	mov	b1, t1
	mov	b2, t2
	mov	b3, t3
	ret
.def	a0	= r16
.def	a1	= r17
.def	a2	= r18
.def	a3	= r19
 
.def	b0	= r20
.def	b1	= r21
.def	b2	= r22
.def	b3	= r23
 
.def	t0	= r24
.def	t1	= r25
.def	t2	= r26
.def	t3	= r27
 
;************************************************************************
;*                                                                      *
;*                      unsigned rounded division 32 bit                *
;*                                                                      *
;************************************************************************
 
urdiv32:
	mov	t0, b0		;T = B
	mov	t1, b1
	mov	t2, b2
	mov	t3, b3
	lsr	t3		;B / 2
	ror	t2
	ror	t1
	ror	t0
	add	a0, t0		;A = A + B / 2
	adc	a1, t1
	adc	a2, t2
	adc	a3, t3
 
;************************************************************************
;*                                                                      *
;*                      unsigned division 32 bit                        *
;*                                                                      *
;************************************************************************
;cycle: max 431 (63%) (684)
 
udiv32:
	clr	t1
	tst	b3
	breq	udi10
	ldi	t0, 8
udi1:	lsl	a0
	rol	a1
	rol	a2
	rol	a3
	rol	t1
	cp	a1, b0
	cpc	a2, b1
	cpc	a3, b2
	cpc	t1, b3
	brcs	udi2
	sub	a1, b0
	sbc	a2, b1
	sbc	a3, b2
	sbc	t1, b3
	inc	a0
udi2:	dec	t0
	brne	udi1
	mov	b0, a1
	clr	a1
	mov	b1, a2
	clr	a2
	mov	b2, a3
	clr	a3
	mov	b3, t1
	ret
 
udi10:	tst	b2
	breq	udi20
	ldi	t0, 16
udi11:	lsl	a0
	rol	a1
	rol	a2
	rol	a3
	rol	t1
	brcs	udi12
	cp	a2, b0
	cpc	a3, b1
	cpc	t1, b2
	brcs	udi13
udi12:	sub	a2, b0
	sbc	a3, b1
	sbc	t1, b2
	inc	a0
udi13:	dec	t0
	brne	udi11
	mov	b0, a2
	clr	a2
	mov	b1, a3
	clr	a3
	mov	b2, t1
	ret
 
udi20:	tst	b2
	breq	udi30
	ldi	t0, 24
udi21:	lsl	a0
	rol	a1
	rol	a2
	rol	a3
	rol	t1
	brcs	udi22
	cp	a3, b0
	cpc	t1, b1
	brcs	udi23
udi22:	sub	a3, b0
	sbc	t1, b0
	inc	a0
udi23:	dec	t0
	brne	udi21
	mov	b0, a3
	clr	a3
	mov	b1, t1
	ret
 
udi30:	ldi	t0, 32
udi31:	lsl	a0
	rol	a1
	rol	a2
	rol	a3
	rol	t1
	brcs	udi32
	cp	t1, b0
	brcs	udi33
udi32:	sub	t1, b0
	inc	a0
udi33:	dec	t0
	brne	udi31
	mov	b0, t1			;store remainder
	ret
;------------------------------------------------------------------------ 

[bearbeiten] Multiplikation

[bearbeiten] 32 Bit * 16 Bit

.def	a0	= r16
.def	a1	= r17
.def	a2	= r18
.def	a3	= r19
 
.def	b0	= r20
.def	b1	= r21
.def	b2	= r22
.def	b3	= r23
 
.def	t0	= r24
.def	t1	= r25
.def	t2	= r26
.def	t3	= r27
.def	i0	= r28
 
;************************************************************************
;*                                                                      *
;*                      unsigned multiplication 32 bit                  *
;*                                                                      *
;************************************************************************
;cycle: max 245
 
umul32:
	cpi	a3, 0
	cpc	a3, a2
	breq	_umu1		;one operand must be below 65536
	mov	t0, a0		; swap A <-> B
	mov	a0, b0
	mov	b0, t0
	mov	t0, a1
	mov	a1, b1
	mov	b1, t0
	mov	b2, a2
	mov	b3, a3
	clr	a2
	clr	a3
;				a3,2,1,0 = a1,0 * b3,2,1,0
_umu1:	ldi	i0, 16
	clr	t0
	clr	t1
	ror	a1
	ror	a0
_umu2:	brcc	_umu3
	add	a2, b0
	adc	a3, b1
	adc	t0, b2
	adc	t1, b3
_umu3:	ror	t1
	ror	t0
	ror	a3
	ror	a2
	ror	a1
	ror	a0
	dec	i0
	brne	_umu2
	ret
;------------------------------------------------------------------------ 

[bearbeiten] Wurzel

[bearbeiten] sqrt( 32 Bit )

; WURZEL 32Bit
;	04/2006
; Bernhard.Erfurt@gmx.de
 
; ATmega8
.include "m8def.inc"
 
 
.def temp   = R16       ; TEMP
.def temp1  = R17       ; TEMP1
.def temp2  = R18       ; TEMP2
.def temp3  = R19       ; TEMP3
.def temp4  = R20       ; TEMP4
 
 
;STACK initialisieren
    ldi   temp, LOW(RAMEND)
    out   SPL, temp
    ldi   temp, HIGH(RAMEND)
    out   SPH, temp
 
LOOP:
 
; TESTZAHLEN
    ldi   temp1, BYTE1(10000)
    ldi   temp2, BYTE2(10000)
    ldi   temp3, BYTE3(10000)
    ldi   temp4, BYTE4(10000)
; WURZEL berechnen
    rcall WURZEL_32            ; INP: TEMP1...4 OUT: TEMP1...2
    nop
    rjmp  LOOP
 
 
;#######################################################################
;
;		INPUT 	temp1  (LOW)
;		INPUT 	temp2
;		INPUT 	temp3
;		INPUT 	temp4  (HIGH)
;
;		OUTPUT 	temp1 (LOW)
;		OUTPUT 	temp2 (HIGH)
;
;		Hilfsregister: R0,R1,R14,R15,R16,R21,R22,R23,R24
;
; 	rcall WURZEL_32		; INP: TEMP1...4 OUT: TEMP1...2
;
WURZEL_32:
; HILFSREGISTER sichern	(STACK)
    push  R0
    push  R1
    push  R14
    push  R15
    push  R16
    push  R21
    push  R22
    push  R23
    push  R24
; HILFSREGISTER initialisieren
    ldi   temp, 1
    mov   R14, temp		;= 1
    ldi   temp, 2
    mov   R15, temp		;= 2
    clr   temp
    clr   r0          	; ERGEBNIS
    clr   r1 
    ldi   r21,1        	;= 1
    clr   r22 
    clr   r23 
    clr   r24 
 
; Wurzel-Berechnung
WURZEL_32_w:
    sub   temp1,R21 	; SUBTRAKTION
    sbc   temp2,R22 
    sbc   temp3,R23 
    sbc   temp4,R24 
    brlo  WURZEL_32_ww
    add   R0,R14 		; ADDITION +1(Ergebnis)
    adc   R1,temp 
    add   R21,R15 		; ADDITION +2
    adc   R22,temp 
    adc   R23,temp 
    adc   R24,temp 
    rjmp  WURZEL_32_w
WURZEL_32_ww:   
    mov   temp1,r0 		; ERGEBNIS KOPIEREN
    mov   temp2,r1 
; HILFSREGISTER wieder herstellen (STACK)
    pop   R24
    pop   R23
    pop   R22
    pop   R21
    pop   R16
    pop   R15
    pop   R14
    pop   R1
    pop   R0
    ret

Schnelle Implementierung für große Operanden: http://www.mikrocontroller.net/topic/98432

[bearbeiten] Binär zu BCD - Umwandlung

Zur Ausgabe einer Binärzahl auf ein Textdisplay oder zur seriellen ASCII-Übertragung an den PC ist diese Umwandlung nötig. Sie ist ähnlich aufwendig wie eine Division, zum Beispiel für eine 32-Bit-Zahl etwa 500-900 Taktzyklen und 10 Register. Mehrere Verfahren werden angeboten:

[bearbeiten] Division /10

Für eine Division pro Dezimalstelle ist nur ein Unterprogramm nötig. Der Divisionsrest, engl. remainder, bildet unmittelbar die BCD-codierte Dezimalziffer, von rechts nach links fortschreitend. Zur Ausgabe von links nach rechts kann man die Ziffern auf dem Stack zwischenlagern (LIFO-Register last-in first-out)

Beispiele:

[bearbeiten] Division /10000, /1000, /100, /10

ähnlich dem vorigen, aber die BCD-Ziffern erscheinen sofort von links nach rechts.

Beispiele:

[bearbeiten] Addition von $33

Hier wird die Binärzahl, mit der höchstwertigen Stelle voran, von rechts in die Ergebnisregister geschoben. Nach jedem Schiebevorgang wird eine Korrekturrechnung ausgeführt. Für 32 Bit bilden 4 Eingabe- und 5 Ausgaberegister ein 72 Bit Schieberegister, das 32 mal links geschoben wird. Durch die Korrekturrechnung wird die Binärzahl zur gepackten (2 Stellen pro Byte) BCD-Zahl "aufgebläht".

Eine Erklärung des Algorithmus soll hier versucht werden: Um die niederwertigste 4 Bit Binärziffer in BCD umzuwandeln, ist für $0...$9 keine Änderung nötig, für $A...$F wird "6" addiert. Diese Addition wird ersetzt durch eine Addition von "3" und anschließendes Linksschieben. Das führt man zunächst für beide Halbbytes gleichzeitig mit "subi Reg,-$33" aus. Anschließend werden die beiden Additionen einzeln für den Fall "0...9" rückgängig gemacht. Die Bits 4 und 7 des Registers dient dabei als BCD-Carry-Flag (Halbbyte-Übertrag). Das normale C-Flag wird durch die Additionen nicht beeinflußt, es dient nur dem Schiebevorgang.

Beispiele:

[bearbeiten] Tabelle

Für kleine Zahlen kann die gesuchte BCD-Zahl auch aus einer Tabelle entnommen werden.

[bearbeiten] Mischvarianten

Eine Mischung mehrerer Verfahren wird z.B. von Andre Birua in der ersten Variante von "Bin4BCD" verwendet. Die oberen 16 Bit werden nach "Div/10000" vorbearbeitet und anschließend alle 32 Bit nach "Add $33".

[bearbeiten] Tutorial

enthält C-Code und PIC-Code für schnelle 16 Bit Wandlung, Hardware-Multiplizierer möglich - auch für FPGA interessant

[bearbeiten] Diskussionsbeiträge im Forum

[bearbeiten] Weblinks

webmaster@mikrocontroller.netImpressumWerbung auf Mikrocontroller.net