assembler division mit rest

#2052195
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
1
.def ergebnis = r1
2
.def rest =  r2
3
.def divident = r16
4

5
division10:        ; division durch 10 mit Rest
6
  clr    ergebnis
7
  clr    rest
8
div10:
9
  mov   rest, divident
10
  subi  divident, 10
11
  inc   ergebnis
12
  brmi  div10_ende    ; Sprung wenn divident < 0
13
  rjmp  div10
14
div10_ende:
15
  dec    ergebnis    
16
  ret

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

Ist das so richtig?
Gast #2052225
Lesenswert?

Hi

>Ich habe mir dies hier überlegt

Ich dies:
1
.def ergebnis = r1
2
.def rest =  r2
3
.def divident = r16
4

5
division10:        ; division durch 10 mit Rest
6
  ldi ergebnis,-1
7
  mov   rest, divident
8
div10:
9
  inc   ergebnis
10
  subi  rest, 10
11
  brcc  div10    ; Sprung wenn divident > 0
12
  add rest,10
13
  ret

MfG Spess
#2052243
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?
1
.def ergebnis = r1
2
.def rest =  r2
3
.def divident = r16
4

5
division10:        ; division durch 10 mit Rest
6
  clr    ergebnis
7
  clr    rest
8
div10:
9
  mov   rest, divident
10
  subi  divident, 10
11
  brmi  div10_ende    ; Sprung wenn divident < 0
12
  inc   ergebnis
13
  rjmp  div10
14
div10_ende:
15
  ret
#2052270
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.
#2052747
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
Gast #2052785
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
#2052801
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?
Gast #2052844
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
#2052846
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren