Gibt es eine Möglichkeit, ohne großen Aufwand, bcd nach binär zu wandeln ( irgendeine Bit-Schieberei)?
Und zum dritten, da ist jetzt nur Thomas dran schuld
:
@LotadaC du bist ja auch eine hochqualifizierte Bitschubse.
Aaalsoo...
Es handelt sich hier natürlich nicht um BCDs (eine binary coded digit ist logischerweise bereits binär, die binäre Zahl hat genau den Wert der Dezimal
stelle (digit).
Du hast gepackte BCD, das heißt das untere Nibble enthält die Einer, das Obere die Zehner (den Rest bei den Stunden vernachlässige ich jetzt mal).
Ein Nibble selbst ist also die korrekte, binäre 4bit-Zahl.
@Dirk hat Dir ja bereits gezeigt, wie das dann geht: Du separierst die beiden Nibbles (Digits). Da das Zehnernibble den zehnfachen Wert haben müßte, multiplizierst Du es mit zehn, und addierst es zum Einernibble. Fertig.
Wie Bascom das ganze, insbesondere die Multiplikation macht, braucht Dich nicht wirklich zu interessieren.
Aber da Thomas mich ja herausgefordert hat hier mal ein Weg, wie man das im AVR angehen könnte:
Vorüberlegung:
Wie multipliziert man binär? Genauso, wie man das schriftlich in der Schule gelernt hat. Mit zwei wesentlichen Unterschieden:
Erstens arbeitet man auf der Basis zwei (statt auf 10, also beim verschieben verdoppelt/halbiert man, anstatt zu zehnteln/verzehnfachen),
Zweitens gibt es nur zwei Ziffern (also das kleine einmaleins beschränkt sich auf vier Gleichungen (0*0=0, 1*0=0, 0*1=0, 1*1=1))
Wie hat man nun dezimal schriftlich Multipliziert? Im Prinzip hat man einen Faktor in seine Zehnerpotenzen aufgeteilt, diese je mit dem anderen Faktor multipliziert, und die Ergebnisse addiert.
Beispiel:
15*23
also 15*2(*10)=30(*10)=300
15*3(*1)=45(*1)=45
Zusammenaddiert also 345.
(Die Zehnerpotenzen in den Klammern hat man nicht wirklich mitgeschrieben, sondern durch die Treppenartige Anordnung dazugeschummelt.
Binär geht das genauso, nur eben mit Zweierpotenzen (also Schiebeoperationen und Additionen). Ich will jetzt hier das ganze nicht ausführen - letztlich ist es wegen Basis zwei viel einfacher. Es läuft darauf hinaus, einen der Faktoren in Zweierpotenzen zu zerlegen (was durch einfaches schieben realisiert wird), den anderen Faktor mit dessen uhrsprünglicher Bitwertigkeit (auch durch schieben) und dem Bit selbst zu Multiplizieren (Zur Erinnerung: Das Bit ist eins oder Null). Man hat also entweder einen geschobenen Faktor oder Null zu addieren. Also kann man genausogut schieben, und anhand der Bits des ersten Faktors entscheiden, ob dieses geschobene Teilergebnis mitsummiert werden muß, oder nicht.
Weiter:
Der hier verwendet konstante Faktor ist Zehn (0b1010) - da würden also nur zwei geschobene Zwischenergebnisse addiert werden (Nibble*8+Nibble*2).
Und zuletzt:
Das Zehnernibble ist das Highnibble der gepackten BCD - statt das erstmal nach rechts zu schieben, um es dann mehfach nach links zu schieben, kann man es auch mehrfach nach rechts schieben.
soooooooooooooo... los gehts
- gepackte BCD in ein Rechenregister (nennen wir es Arbeitsregister) laden
- von dort ins Ergebnisregister kopieren
- dort das Highnibble wegmaskieren (Ergebnis=Einer. bisher vier Systemtakte)
- im Arbeitsregister das Lownibble wegmaskieren
- Arbeitsregister einmal rechtsschieben (entspricht Faktor einhalb, aber da es ja im Highnibble statt im Lownibble steht (Faktor 16) entspricht das zusammen Faktor 8)
- Arbeitsregister zum Ergebnisregister hinzuaddieren (Ergebnis=Einer+(8*Zehner). weitere drei Takte
- Arbeitsregister noch zweimal rechtsschieben (über vier zu zwei)
- Arbeitsregister zum Ergebnisregister hinzuaddieren (Ergebnis=Einer+(8*Zehner)+(2*Zehner). weitere drei Takte
- Ergebnis abspeichern (zwei Takte)
Fertig nach 12 Takten, wobei ein drittel auf das Laden und Speichern der Variablen aus dem/ins SRAM entfallen.
Edit: Das ist der Weg ohne interner Multiplikationsinstruktion. Gehts mit schneller?
Hmm...
Das Multiplizieren sind oben die Schritte 5 bis 8. Zusammen 5 Takte.
MUL selbst kostet zwei Takte, aber da es kein MULI gibt, muß erstmal die Zehn als zweiter Faktor in ein Rechenregister geladen werden (1 Takt).
Wenn wir die BCD mit 10 multiplizieren wollen, muß sie als Low Nibble im Rechenregister stehen. Also vorher viermal rechtsschieben? Wären vier weitere Takte. Wären also bereits sieben. Ok, Schritt 4 wäre dann auch überflüssig, hat aber auch nur einen Takt.
Nur dreimal rechtsschieben (3 Takte), und statt mit zehn mit 5 Multiplizieren? Dann brauchts das Maskieren, also auch hier ein Takt mehr.
Und wenn man nicht schiebt, sondern die Nibbles tauscht?
Also statt 5..8
Nibbles im Arbeitsregister tauschen (Swap - ein Takt)
Zehn in weiteres Rechenregister laden (ein Takt)
Arbeitsregister mit Zehn-Register multiplizieren (zwei Takte)
Multiplikationsergebnis (aus R0) auf das Ergebnisregister addieren (ein Takt)
wären dieselben fünf Takte...