Forum: Mikrocontroller und Digitale Elektronik Fehler im Atmel AVR AN200.ASM?


von Thomas (kosmos)


Lesenswert?

Hallo,

ich habe mir ein AN von Atmel durchgeschaut und glaube einen Fehler 
gefunden zu haben, vielleicht kann sichs mal jemand anschauen der sich 
mit ASM auskennt. Und zwar geht es um eine 16/16bit unsigned 
Rechenroutine nur finde ich darin leider nichts vom Ergebniss. Es werden 
zwar extra 2 Register(dres18uL und dres18uH) fürs Ergebniss definiert, 
diese bleiben aber ungenutzt. Eigentlich kann ich mir nicht vorstellen 
das Atmel da so geschludert hat aber vielleicht habe ich auch etwas 
übersehen. Da der Quelltext nicht ganz so lange ist hänge ich ihn mal 
etwas gekürzt direkt dran. Könnte es vielelicht sein das das Ergebniss 
in drem16uL und drem16uH steht und noch in die dafür gedachten Register 
kopiert werden muss?

;********************************************************************
;* "div16u" - 16/16 Bit Unsigned Division
;* "This subroutine divides the two 16-bit numbers
;* "dd8uH:dd8uL" (dividend) and "dv16uH:dv16uL" (divisor).
;* "The result is placed in "dres16uH:dres16uL" and the remainder in
;* "drem16uH:drem16uL".
;********************************************************************
;***** Divide Two Unsigned 16-Bit Numbers (50,000/60,000)
ldi  dd16uL,low(50000)
ldi  dd16uH,high(50000)
ldi  dv16uL,low(60000)
ldi  dv16uH,high(60000)
rcall  div16u    ;result:  $0000 (0)
      ;remainder:  $c350 (50,000)
.def  drem16uL=r14
.def  drem16uH=r15
.def  dres16uL=r16
.def  dres16uH=r17
.def  dd16uL  =r16
.def  dd16uH  =r17
.def  dv16uL  =r18
.def  dv16uH  =r19
.def  dcnt16u  =r20

div16u:  clr  drem16uL  ;clear remainder Low byte
  sub  drem16uH,drem16uH;clear remainder High byte and carry
  ldi  dcnt16u,17  ;init loop counter
d16u_1:  rol  dd16uL    ;shift left dividend
  rol  dd16uH
  dec  dcnt16u    ;decrement counter
  brne  d16u_2    ;if done
  ret      ;    return
d16u_2:  rol  drem16uL  ;shift dividend into remainder
  rol  drem16uH
  sub  drem16uL,dv16uL  ;remainder = remainder - divisor
  sbc  drem16uH,dv16uH  ;
  brcc  d16u_3    ;if result negative
  add  drem16uL,dv16uL  ;    restore remainder
  adc  drem16uH,dv16uH
  clc      ;    clear carry to be shifted into result
  rjmp  d16u_1    ;else
d16u_3:  sec      ;    set carry to be shifted into result
  rjmp  d16u_1

von Joerg X. (Gast)


Lesenswert?

schau (noch-) mal genau hin:
dres16uL=r16 <-> dd16uL  =r16
... und auch bei den ...H Registern ;-)
 Der Nachteil ist, dass man die dres...-Register nicht einfach so ändern 
kann

von Michael U. (Gast)


Lesenswert?

Hallo,

die habe ich gerade letztens genutzt, die Registerbezeichnungen muß man 
wirklich 3x lesen, damit man versteht, was wo landet...

Ansonsten macht die Routine genau, was sie soll.

Gruß aus Berlin
Michael


von Thomas (kosmos)


Lesenswert?

danke das ist mir überhaupt nicht aufgefallen das die da doppelt benutzt 
werden.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.