Einfacher Zähler von 0->99 auf 2 Halbbyte

OP (Firma: Germany) #2610867
Lesenswert?

Was läuft denn hier falsch?!

Ich habe einen 1Byte Wert dieser soll mir jeweils aus dem Oberen und 
unteren Byte eine Dez. Zahl von 1 bis 9 Zählen und dann auf einen 
Display ausgeben.

Nur leider Zählt es jetzt mit den Einer 1->3->7->? FERTIG
und die Zehner  1.2.3.4.5.6.7.8.9 noch 6 Sonderzeichen und dann wieder 
bei 0 und die Einerstelle ändert sich nicht. Ist hier ein Denkfehler 
drin?

R21 : Ist sind meine zwei Dez. Zahlen … also 00 bis 99


zaelen:     push    r16
            ldi     r16,0
            mov     r16,r21
            cbr     r16,0b11110000      ;Lösche Oberes Halbbyte
            cpi     r16,9               ;Ist die Zahl jetzt 9?
            breq    zaelenZehn          ;Dann verzweige
            inc     r16                 ;Addiere um 1
            add     r21,r16             
            pop     r16
            ret                         ;Zurück

zaelenZehn:
            mov     r16,r21             
            swap    r16                 ;Oberes und unteres Halbbyte tau 
schen
            cbr     r16,0b11110000      ;Löschen Oberes Halbbyte
            cpi     r16,9               ;Ist der Wert jetzt 9?
            breq    zaelenReset         ;Dann verzweige
            inc     r16                 ;Addiere um 1
            swap    r16                 ;Oberes und unteres Halbbyte tau 
schen
            mov     r21,r16
            pop     r16
            ret
            
zaelenReset:
            clr     r20
            pop     r16
            ret



AusgabeWertA:
            ldi     r16,0x44
            rcall   lcdGoto
            ldi     r17,0x30
            mov     r16,r21
            swap    r16
            cbr     r16,0xF0
            add     r16,r17
            rcall   lcdData
            ldi     r17,0x30
            mov     r16,r21
            cbr     r16,0xF0
            add     r16,r17
            rcall   lcdData
            ret
OP (Firma: Germany) #2610907
Lesenswert?

Ne das ist es nicht. Das sollte ja so sein dann will ich ja wieder in 
mein mainloop da wo ich her komme.

Ich habe aber den fehler.
            inc     r16                 ;Addiere um 1
(bevor ich die Werte wieder zusammenbringe muss ich doch den unteren 
bzw. oberen Halbbyte löschen sonst addiere ich den wert mit dem wert 1 - 
3 - 7

also

          ->cbr     r21,0x0F            ;Unteren Halbbyte löschen <-

            add     r21,r16
            pop     r16
            ret                         ;Zurück


Aber danke für die Antworten... man muss manchmal eben nur eine rauchen 
und nochmal überlegen. in diesem fall war das erfolgreich =)
Gast #2611052
Lesenswert?

Hi

>Wenn schon Assembler: mit dem BRHC-Befehl könntest Du die Zählerei auf
>ca 10 Befehle kürzen.

Nein. Das wird erst bei $xF+1 gesetzt. Aber das mit den 10+x Befehlen 
kommt trotzdem hin.

MfG Spess
Gast #2611067
Lesenswert?

spess53 schrieb:
> Nein. Das wird erst bei $xF+1 gesetzt. Aber das mit den 10+x Befehlen
> kommt trotzdem hin.

Ich wollte jetzt nicht die komplette Lösung zu den Hausaufgaben 
hinschreiben aber wenn man will kann man den Überlauf des digit carry 
bei $xA + testweise Addition von 6 in ein Hilfsregister erzwingen.

Gruß Anja
#2611191
Lesenswert?

Eine CPU rechnet immer binär. Es kostet daher viel Code, wenn man 
versucht, sie auf dezimal zu vergewaltigen.

Einfacher ist es, binär zu zählen und nur zur Ausgabe nach Dezimal zu 
wandeln:
1
.def    counter = r16
2
.def    wr0     = r18
3
.def    wr1     = r19
4
;----------------------------------------
5

6
;count up 0 .. 99
7
count:
8
        inc     counter
9
        cpi     counter, 100
10
        brcs    _count1
11
        clr     counter
12
_count1:
13
        ret
14
;----------------------------------------
15

16
;input: wr0 = number 0 .. 99
17
;output: wr0 = ones, wr1 = tens (ASCII)
18
numout:
19
        ldi     wr1, '0' - 1
20
_numout1:
21
        inc     wr1
22
        subi    wr0, 10
23
        brcc    _numout1
24
        subi    wr0, -(10 + '0')
25
        ret
26
;----------------------------------------

Es ist sinnvoll, die Register zu benamen. Ansonsten kommt man sehr 
schnell durcheinander, was nun welches Register für eine Funktion hat.

Auch sollte man einige Register als zerstörbar (Arbeitsregister) 
reservieren, das erspart haufenweises Push/Pop. Sinnvoll dienen sie auch 
gleich der Parameterübergabe (Argumente und Returnwerte).


Peter
Gast #2611491
Lesenswert?

Hi

>Es kostet daher viel Code, wenn man
>versucht, sie auf dezimal zu vergewaltigen.

Nicht wirklich. Mit der Anregung von Anja:
1
bcd_cnt:   push r16
2
           ldi r16,$67
3
           add r21,r16
4
           brcs bcd_cnt20
5
           brhs bcd_cnt10
6
           subi r21,$06
7
bcd_cnt10: subi r21,$60
8
bcd_cnt20: pop r16
9
           ret

Wenn man die $67 noch in einem der unteren Register ablegt, würden es 
nur noch 6 Befehle sein. Gerade einer mehr wie bei dir.

MfG Spess
#2611546
Lesenswert?

spess53 schrieb:
> Gerade einer mehr wie bei dir.

Ziemlich tricky der Code, schwer zu durchschauen.
Wenn man nicht nur INC, sondern auch andere Operationen machen will, 
artet das aber schnell aus.
Und die Ausgabe muß die Nibble ja wieder auseinanderpfrimeln.

Die Ausgabe des Binärwertes würde so aussehen:
1
AusgabeWertA:
2
        ldi     wr0, 0x44
3
        rcall   lcdGoto
4

5
        mov     wr0, counter    ; get value
6
        rcall   numout          ; bin -> dec
7
        push    wr0
8
        mov     wr0, wr1        ; tens first
9
        rcall   lcdData
10
        pop     wr0             ; then ones
11
        rjmp    lcdData


Peter

P.S.
Der Originalcode sichert R16 beim Zählen, aber die Ausgabe zerstört R16, 
R17. Entweder immer sichern oder garnicht.
Gerade bei Assembler ist es wichtig, konsequent zu sein, sonst sucht man 
sich dumm und dämlich nach den Fehlern.
Deshalb auch der Tip mit der Benamung, damit die zerstörbaren Register 
sofort ins Auge fallen. Und auch, damit man Argumente nicht im falschen 
Register übergibt. Namen lassen sich leichter merken, als nur die Zahlen 
0 .. 31.
Gast #2611568
Lesenswert?

Hi

>Wenn man nicht nur INC, sondern auch andere Operationen machen will,
>artet das aber schnell aus.

Ist richtig. Mit BCD/Packet BCD kann man kaum etwas herausreissen.

>Der Originalcode sichert R16 beim Zählen,...

Da passt einiges nicht.

MfG Spess

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