Pfad: Home =>
AVR-Übersicht =>
Binäres Rechnen => Zahlenumwandlung
Das Umwandeln von Zahlen kommt in Assembler recht häufig vor, weil der Prozessor
am liebsten (und schnellsten) in binär rechnet, der dumme Mensch aber nur das
Zehnersystem kann. Wer also aus einem Assemblerprogramm heraus mit Menschen an einer
Tastatur kommunizieren möchte, kommt um Zahlenumwandlung nicht herum. Diese
Seite befasst sich daher mit diesen Wandlungen zwischen den Zahlenwelten, und zwar
etwas detaillierter und genauer.
Wer gleich in die Vollen gehen möchte, kann sich direkt in den üppig
kommentierten Quelltext stürzen. Den gibt es über diesen
Link im HTML-Format oder über diesen
Link im Assemblerformat.
Die hier behandelten Zahlensysteme sind:
- Dezimal: Jedes Byte zu je acht Bit enthält eine Ziffer, die in ASCII
formatiert ist. So repräsentiert der dezimale Wert 48, in binär $30, die
Ziffer Null, 49 die Eins, usw. bis 57 die Neun. Die anderen Zahlen, mit denen
ein Byte gefüllt werden kann, also 0 bis 47 und 58 bis 255, sind keine gültigen
Dezimalziffern. (Warum gerade 48 die Null ist, hat mit amerikanischen
Militärfernschreibern zu tun, aber das ist eine andere lange Geschichte.)
- BCD-Zahlen: BCD bedeutet Binary Coded Decimal. Es ist ähnlich wie
dezimale ASCII-Zahlen, nur entspricht die BCD-dezimale Null jetzt tatsächlich
dem Zahlenwert Null (und nicht 48). Dementsprechend gehen die BCDs von 0 bis 9.
Alles weitere, was noch in ein Byte passen würde (10 .. 255) ist keine
gültige Ziffer und gehört sich bei BCDs verboten.
- Binärzahlen: Hier gibt es nur die Ziffern 0 und 1. Von hinten
gelesen besitzen sie jeweils die Wertigkeit der Potenzen von 2, also ist die
Binärzahl 1011 soviel wie 1* (2 hoch 0) + 1*(2 hoch 1) + 0*(2 hoch 2) +
1*(2 hoch 3), so ähnlich wie dezimal 1234 gleich 4*(10 hoch 0) + 3*(10 hoch 1)
+ 2*(10 hoch 2) + 1*(10 hoch 3) ist (jede Zahl hoch 0 ist übrigens 1, nur nicht
0 hoch 0, da weiss man es nicht so genau!). Binärzahlen werden in Paketen
zu je acht (als Byte bezeichnet) oder 16 (als Wort bezeichnet) Binärziffern
gehandhabt, weil die einzelnen Bits kaum was wert sind.
- Hexadezimal: Hexadezimalzahlen sind eigentlich Viererpäckchen
von Bits, denen man zur Vereinfachung die Ziffern 0 bis 9 und A bis F (oder a
bis f) gibt und als solche meistens ASCII-verschlüsselt. A bis F deswegen,
weil vier Bits Zahlen von 0 bis 15 sein können. So ist binär 1010
soviel wie 1*(2 hoch 3) + 1*(2 hoch 1), also dezimal 10, kriegt dafür den
Buchstaben A. Der Buchstabe A liegt aber in der ASCII-Codetabelle beim dezimalen
Wert 65, als Kleinbuchstabe sogar bei 97. Das alles ist beim Umwandeln wichtig
und beim Codieren zu bedenken.
Soweit der Zahlenformatsalat. Die zum Umwandeln geschriebene Software soll
einigermaßen brauchbar für verschiedene Zwecke sein. Es lohnt sich
daher, vor dem Schreiben und Verwenden ein wenig Grütze zu investieren.
Ich habe daher folgende Regeln ausgedacht und beim Schreiben eingehalten:
- Binärzahlen: Alle Binärzahlen sind auf 16 Bit ausgelegt
(Wertebereich 0..65.535). Sie sind in den beiden Registern rBin1H (obere
8 Bit, MSB) und rBin1L (untere 8 Bit, LSB) untergebracht. Dieses
binäre Wort wird mit rBin1H:L abgekürzt. Bevorzugter Ort beim AVR
für die beiden ist z.B. R1 und R2, die Reihenfolge ist dabei egal.
Für manche Umwandlungen wird ein zweites binäres Registerpaar
gebraucht, das hier als rBin2H:L bezeichnet wird. Es kann z.B. in R3 und
R4 gelegt werden. Es wird nach dem Gebrauch wieder in den Normalzustand
versetzt, deshalb kann es unbesehen auch noch für andere Zwecke
dienen.
- BCD- und ASCII-Zahlen: Diese Zahlen werden generell mit dem Zeiger
Z angesteuert (Zeigerregister ZH:ZL oder R31:R30), weil solche Zahlen meistens
irgendwo im SRAM-Speicher herumstehen. Sie sind so angeordnet, dass die
höherwertigste Ziffer die niedrigste Adresse hat. Die Zahl 12345
würde also im SRAM so stehen: $0060: 1, $0061: 2, $0062: 3, usw. Der
Zeiger Z kann aber auch in den Bereich der Register gestellt werden, also
z.B. auf $0005. Dann läge die 1 in R5, die 2 in R6, die 3 in R7, usw.
Die Software kann also die Dezimalzahlen sowohl aus dem SRAM als auch aus
den Registern verarbeiten. Aber Obacht: es wird im Registerraum unbesehen
alles überschrieben, was dort herumstehen könnte. Sorgfältige
Planung der Register ist dann heftig angesagt!
- Paketeinteilung: Weil man nicht immer alle Umwandlungsroutinen
braucht, ist das Gesamtpaket in vier Teilpakete eingeteilt. Die beiden
letzten Pakete braucht man nur für Hexzahlen, die beiden ersten zur
Umrechnung von ASCII- oder BCD- zu Binär bzw. von Binär in
ASCII- und BCD. Jedes Paket ist mit den darin befindlichen Unterprogrammen
separat lauffähig, es braucht nicht alles eingebunden werden. Beim
Entfernen von Teilen der Pakete die Aufrufe untereinander beachten! Das
Gesamtpaket umfasst 217 Worte Programm.
- Fehler: Tritt bei den Zahlenumwandlungen ein Fehler auf, dann
wird bei allen fehlerträchtigen Routinen das T-Flag gesetzt. Das kann
mit BRTS oder BRTC bequem abgefragt werden, um Fehler in der Zahl zu
erkennen, abzufangen und zu behandeln. Wer das T-Flag im Statusregister
SREG noch für andere Zwecke braucht, muss alle "set"-, "clt"-, "brts"-
und "brtc"-Anweisungen auf ein anderes Bit in irgendeinem Register
umkodieren. Bei Fehlern bleibt der Zeiger Z einheitlich auf der Ziffer
stehen, bei der der Fehler auftrat.
- Weiteres: Weitere Bedingungen gibt es
im allgemeinen Teil des Quelltextes.
Dort gibt es auch einen
Überblick zur Zahlenumwandlung,
der alle Funktionen, Aufrufbedingungen und Fehlerarten enthält.
Die Routine AscToBin2 eignet sich
besonders gut für die Ermittlung von Zahlen aus Puffern. Sie überliest
beliebig viele führende Leerzeichen und Nullen und bricht die
Zahlenumwandlung beim ersten Zeichen ab, das keine gültige
Dezimalziffer repräsentiert. Die Zahlenlänge muss deshalb nicht
vorher bekannt sein, der Zahlenwert darf nur den 16-Bit-Wertebereich der
Binärzahl nicht überschreiten. Auch dieser Fehler wird erkannt
und mit dem T-Flag signalisiert.
Soll die Länge der Zahl exakt fünf Zeichen ASCII umfassen, kann
die Routine Asc5ToBin2 verwendet
werden. Hier wird jedes ungültige Zeichen, bis auf führende
Nullen und Leerzeichen, angemahnt.
Die Umrechnung erfolgt von links nach rechts, d.h. bei jeder weiteren
Stelle der Zahl wird das bisherige Ergebnis mit 10 multipliziert und
die dazu kommende Stelle hinzugezählt. Das geht etwas langsam,
weil die Multiplikation mit 10 etwas rechenaufwendig ist. Es gibt
sicher schnellere Arten der Wandlung.
Die Umwandlung von BCD zu Binär funktioniert ähnlich. Auf eine
eingehende Beschreibung der Eigenschaften
dieses Quellcodes wird daher verzichtet.
Diese Routine Bin1Mul10 nimmt eine
16-Bit-Binärzahl mit 10 mal, indem sie diese kopiert und durch
Additionen vervielfacht. Aufwändig daran ist, dass praktisch bei
jedem Addieren ein Überlauf denkbar ist und abgefangen werden muss.
Wer keine zu langen Zahlen zulässt oder wem es egal ist, ob Unsinn
rauskommt, kann die Branch-Anweisungen alle rauswerfen und das
Verfahren damit etwas beschleunigen.
Die Wandlung von Binär nach ASCII erfolgt in der Routine
Bin2ToAsc5. Das Ergebnis ist generell
fünfstellig. Die eigentliche Umwandlung erfolgt durch Aufruf von
Bin2ToBcd5. Wie das funktioniert,
wird weiter unten beschrieben.
Wird statt Bin2ToAsc5 die Routine
Bin2ToAsc aufgerufen, kriegt man den Zeiger Z auf die erste Nicht-Null
in der Zahl gesetzt und die Anzahl der Stellen im Register rBin2L
zurück. Das ist bequem, wenn man das Ergebnis über die serielle
Schnittstelle senden will und unnötigen Leerzeichen-Verkehr vermeiden
will.
Bin2ToBcd5 rechnet die Binärzahl
in rBin1H:L in dezimal um. Auch dieses Verfahren ist etwas
zeitaufwändig, aber sicher leicht zu verstehen. Die Umwandlung
erfolgt durch fortgesetztes Abziehen immer kleiner werdender
Binärzahlen, die die dezimalen Stellen repräsentieren, also
10.000, 1.000, 100 und 10. Nur bei den Einern wird von diesem Schema
abgewichen, hi.
Die Routine Bin2ToHex4 produziert
aus der Binärzahl eine vierstellige Hex-ASCII-Zahl, die etwas leichter
zu lesen ist als das Original in binär. Oder mit welcher
Wahrscheinlichkeit verschreiben Sie sich beim Abtippen der Zahl
1011011001011110? Da ist B65E doch etwas bequemer und leichter zu
memorieren, fast so wie 46686 in dezimal.
Die Routine produziert die Hex-Ziffern A bis F in Großbuchstaben.
Wer es lieber in a .. f mag: bitte schön, Quelltext ändern.
Mit Hex4ToBin2 geht es den umgekehrten
Weg. Da hier das Problem der falschen Ziffern auftreten kann, ist wieder
jede Menge Fehlerbehandlungscode zusätzlich nötig.
Zum Seitenanfang
©2002 by http://www.avr-asm-tutorial.net