www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik assembler division mit rest


Autor: M. S. (sadmarvin)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Für ein Programm brauche ich eine Routine die durch 10 teilt.
Ich brauche das Ergebnis und den Rest.

Ich habe mir dies hier überlegt
.def ergebnis = r1
.def rest =  r2
.def divident = r16

division10:        ; division durch 10 mit Rest
  clr    ergebnis
  clr    rest
div10:
  mov   rest, divident
  subi  divident, 10
  inc   ergebnis
  brmi  div10_ende    ; Sprung wenn divident < 0
  rjmp  div10
div10_ende:
  dec    ergebnis    
  ret

nach aufruf der Routine sollte jetzt ja das Ergebins in "ergebnis" und 
der Rest in "rest" stehen.

Ist das so richtig?

Autor: Ansgar K. (paulderbademeister)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zwei Dinge solltest du überprüfen:

1. Welche Flags können durch INC verändert werden und welche werden 
durch BRMI geprüft?

2. Was steht in deinem Rest? Der wird kein einziges mal verändert.

Autor: Spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Ich habe mir dies hier überlegt

Ich dies:
.def ergebnis = r1
.def rest =  r2
.def divident = r16

division10:        ; division durch 10 mit Rest
  ldi ergebnis,-1
  mov   rest, divident
div10:
  inc   ergebnis
  subi  rest, 10
  brcc  div10    ; Sprung wenn divident > 0
  add rest,10
  ret

MfG Spess

Autor: Spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

Korrektur:

  add rest,10 -> subi rest, -10

MfG Spess

Autor: M. S. (sadmarvin)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ansgar K. schrieb:
> Zwei Dinge solltest du überprüfen:
>
> 1. Welche Flags können durch INC verändert werden und welche werden
> durch BRMI geprüft?

Ah, ja das INC das N Flag verändert hatte ich nicht berücksichtigt.

>
> 2. Was steht in deinem Rest? Der wird kein einziges mal verändert.

Hm, eigentlich doch jedesmal am Anfang von div10:

mov  rest, divident

EDIT:
so müsste es doch dann klappen, oder?
.def ergebnis = r1
.def rest =  r2
.def divident = r16

division10:        ; division durch 10 mit Rest
  clr    ergebnis
  clr    rest
div10:
  mov   rest, divident
  subi  divident, 10
  brmi  div10_ende    ; Sprung wenn divident < 0
  inc   ergebnis
  rjmp  div10
div10_ende:
  ret

Autor: Ansgar K. (paulderbademeister)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stimmt, da hatte ich einen kleinen Denkfehler was den Rest angeht - das 
funktioniert tatsächlich so, ist aber umständlich.

Dein neuer Code sollte so gut funktionieren, falls es dir nicht um 
maximale Geschwindigkeit geht. Falls doch, solltest du dir einmal den 
Vorschlag von Spess angucken, er braucht in seiner Schleife nur 4 statt 
deiner 7 Zyklen.

Noch schneller wäre eine Multiplikation mit 0.1, falls ein 
Hardwaremultiplizierer zur Verfügung steht. In 99% der Fälle dürfte 
deine Lösung aber gute Dienste leisten.

Autor: M. S. (sadmarvin)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok,

werde mir die version von Spess angucken.

Autor: M. S. (sadmarvin)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Spess53 schrieb:
> Hi
>
> Korrektur:
>
>   add rest,10 -> subi rest, -10
>
> MfG Spess

Ich habe mir den Spess Code mal angeguckt und auch verstanden.
Aber warum kein add ?

Weil man das nur auf zwei Register anwenden kann?

wenn ich jetzt noch ein Register als divident definieren und mit 10 
laden würde, könnte ich doch auch add nehmen, oder?

und dann halt SUB statt SUBI

Autor: M. S. (sadmarvin)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Korrektur

divident -> divisor

Autor: Spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Weil man das nur auf zwei Register anwenden kann?

Richtig.

>wenn ich jetzt noch ein Register als divident definieren und mit 10
>laden würde, könnte ich doch auch add nehmen, oder?

Wozu? Das 'subi' erfüllt seinen Zweck.

>wenn ich jetzt noch ein Register als divident definieren und mit 10
>laden würde, könnte ich doch auch add nehmen, oder?

>und dann halt SUB statt SUBI

Was hast du davon?

MfG Spess

Autor: M. S. (sadmarvin)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
nochmal ich ;)

bin grad doch etwas verwirrt

In der Beschreibung von SUBI und SUB steht ja

"Das C-Flag wird gesetzt, wenn der absolute Wert der Konstante größer 
als der absolute Wert von Rd ist, andernfalls wird es gelöscht."

müsste man dann bei verwendung von BRCC nicht die Addition nach der 
Schleife weglassen? (ergbnis am Anfang = 0)

EDIT:
oder bezieht sich die Beschreibung auf die Registerinhalte vor der 
Subtraktion?

Autor: Spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>(ergbnis am Anfang = 0)

Ergebnis am Anfang ist -1  ->  ldi ergebnis,-1

Dann folgt ein inc ergebnis -> ergebnis=0

Danach die Subtraktion. Wenn Rest<10 ist wird das Carry-Flag gesetzt und 
nicht wieder nach 'div10' gesprungen. Ergebnis hat damit den richtigen 
Wert und mit 'subi rest, -10' wird die letzte Subtraktion rückgängig 
gemacht.

MfG Spess

Autor: M. S. (sadmarvin)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich glaube mein Denkfehler war, dass ich dachte der Vergleich zwichen 
rest und 10 zum setzen des Carry Flags wird mit dem Inhalt den reset 
NACH der Subtraktion hat gemacht, kann das sein?

also:

z.B. rest = 12

12 - 10 = 2 --> 2 < 10 --> C-Flag = 1

aber es ist

12 > 10 -- > C-Flag = 0

Autor: Spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>aber es ist

>12 > 10 -- > C-Flag = 0

Bingo.

Autor: M. S. (sadmarvin)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok, hab ich wohl zu kompliziert gedacht ;)

Autor: Spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>ok, hab ich wohl zu kompliziert gedacht ;)

Kommt vor. Wenn du breq/ne/cc/cs richtig verstanden hast, kannst du 
damit 99,... aller Fälle erschlagen.

MfG Spess

Autor: M. S. (sadmarvin)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, danke Dir. :)

Ich bin ja grad erst am Assembler lernen, wird schon noch mit der Zeit. 
;)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.