Pfad: Home => AVR-Überblick => Programmiertechniken => Wandlung 8-bit bin    (This page in English: Flag EN) Logo

Programmiertechnik für Anfänger in AVR Assemblersprache

Umwandlung von 8-bit Binär in eine ASCII-Zeichenkette

Das braucht man auch sehr oft: eine 8-Bit-Binärzahl soll in dezimales Format umgewandelt und auf einer LCD angzeigt werden. Weil man das so oft braucht, und weil es ein gutes Lehrstück in Assembler ist, gibt es das hier im Detail. Zuerst nackig, dann, weil es schöner anzuschauen ist, mit Unterdrückung führender Nullen.

Die Methode

8-Bit-Binärzahlen können hexadezimal zwischen 0x00 und 0xFF liegen. Wir kriegen daher bei der Umwandlung eine dreistellige Zeichenkette, irgendwo zwischen "000" und "255" als Ergebnis der Umwandlung heraus.

Eine potenzielle Methode, die wir wählen könnten, wäre es, die einzelnen Bits der Zahl nach rechts in das Carry zu schieben und jeweils den dezimalen Wert dieses Bits aufzuaddieren. Dazu bräuchten wir die folgenden Zahlen:
BitWenn Bit=1 addiere ...
0"001"
1"002"
2"004"
3"008"
4"016"
5"032"
6"064"
7"128"
Das bedeutet eine Menge Additionen, wobei auch noch häufig Überläufe in die nächste Ziffer erfolgen. Außerdem wären ständig ASCII-Zeichen in binär codierte Ziffern zu verwandeln, bevor man sie addieren kann, und umgekehrt. Der ganze Assembler-Code dafür wäre kompliziert, komplex und ein Albtraum beim Entwanzen des Codes.

Viel einfacher als das geht das wiederholte Abziehen von 100, bis ein Unterlauf auftritt. Die Anzahl Durchläufe, bis dieser Unterlauf passiert, werden gezählt. Das kann dann entweder null Mal, ein Mal oder zwei Mal passieren und ist unsere erste Dezimalziffer.

Wir wiederholen dieses Spiel dann mit dem Abziehen von 10, bis ein Unterlauf auftritt. Die Anzahl, wie oft das geht, ist unsere zweite Dezimalziffer.

Die dritte Dezimalziffer ist dann einfach der verbliebene Rest der Zahl, die nur noch nach ASCII umgewandelt werden muss.

Das Flussdiagramm der Umwandlung

Flussdiagramm der 8-Bit-Wandlung Dies ist das ganze Flussdigramm. Man kann die beiden Zählschleifen mit der Verzweigung für den Fall, dass beim Abziehen kein Unterlauf auftrat, schön erkennen. Alle Befehlsworte sind Assembler-Mnemonics, so dass das Flussdiagramm sehr einfach in Quellcode übersetzt werden kann. (Die Methode mit dem Flussdiagramm ist ganz besonders für die Programmplanung empfehlenswert, weil sie Klarheit über die Abläufe schafft, noch bevor man die erste Zeile Quellcode eingetippt hat.

Der Ablauf beginnt mit dem Setzen des Registers (hier: R16) auf die umzuwandelnde Zahl. Irgendwo im Quellcode sollte die Zahl mit der Direktive .equ cZahl = 0x7B definiert werden.

Der zweite Schritt ist das Definieren des Ziels, wo die Ziffern hingeschrieben werden sollen. Hier enutzen wir den Zeiger X, um zu einem Bereich im SRAM zu zeigen. Diesen Bereich präparieren wir mit den folgenden Direktiven:

.dseg
sD:
  .byte 3
.cseg

Das SRAM ist damit für die Aufnahme der drei Ergebnisbytes der ASCII-Zeichenkette vorbereitet.

Danach folgt die erste Abziehschleife. Zu Beginn setzen wir den Zähler, hier R17. Aber nicht auf die ASCII-Null (das wäre LDI R17,'0'), sondern auf ein Zeichen davor. Die Schleife beginnt nämlich mit einem Erhöhen, und falls das erste Abziehen schon zu einem Unterlauf führt, steht in R17 dann schon die '0'. Falls das nicht der Fall ist, wird die Schleife ein oder zwei Mal erneut durchlaufen und es steht '1' oder '2' in R17.

Das letzte Abziehen führte zu einem Unterlauf, so dass wir nach dem Verlassen der Schleife das letzte Abziehen wieder rückgängig machen müssen. Da AVR-Assembler kein ADDI als Menmonic haben, nehmen wir stattdessen SUBI, aber mit Minus 100. Das macht rechenmäßig dasselbe, setzt aber die Flaggen etwas anders. Da wir die Flaggen hier aber gar nicht brauchen, brauchen wir uns darum auch gar nicht weiter bekümmern.

Der Zähler in R17, der nun entweder '0','1' oder '2' enthält, wird jetzt in den SRAM-Speicher kopiert. Der X-Zeiger wird danach auto-inkrementiert, so dass er nun auf die zweite Ziffer zeigt.

Nun folgt die Schleife mit dem Abziehen von 10. Erneut beginnt der Zähler mit '0' minus 1, nun werden aber mit SUBI immerzu 10 abgezogen, bis der Unterlauf auftritt. Wenn das erfolgt ist, wird R17 in das SRAM geschrieben.

Der Rest der Zahl wird nun in ASCII umgewandelt, indem 48 addiert werden. Das erfolgt wieder mit SUBI, aber mit -'0'. Auch diese Ziffer landet schließlich im SRAM, und wir sind komplett fertig.

Simulieren der Wandlung

Der Assembler-Quellcode kann von hier heruntergeladen werden. Er kann mit dem Simulator avr_sim ausgeführt werden.

avr_sim nach dem Laden der Register Hier wurden die ersten drei Insruktionen ausgeführt, die Zahl in Register R16 und der Zeiger X in das SRAM sind entsprechend gesetzt.

avr_sim nach der Hunderter-Schleife Hier ist die erste Schleife durchlaufen, das Ergebnis '1' ist im SRAM angekommen.

avr_sim nach der Zehnerschleife Der zweite Loop ist absolviert, die zweite Ziffer ist im SRAM angekommen.

avr_sim nach der dritten Ziffer Auch die letzten beiden Instruktionen sind ausgeführt, die dritte Ziffer steht im SRAM.

avr_sim am Ende avr_sim mit 190 am Ende Hier sind die Ausführungszeiten, links die 123 und rechts die 190. Die Zeiten sind etwa den Faktor 2 länger, wenn viel abgezogen werden muss, aber alles ist unter einer Millisekunde.

Unterdrückung führender Nullen

Zahlen wie "000", "001" oder "012" sind nicht sehr bequem lesbar wegen der vielen führenden Nullen. Wenn wir die loswerden wollen, gibt es zwei Methoden:
  1. sie können nachträglich durch Leerzeichen ersetzt werden, oder
  2. sie können schon während der Umwandlung durch Leerzeichen ersetzt werden.

Formatieren der Zeichenkette

Nachträgliches Umformatieren der Zeichenkette ist simpel. Wir können das ohne oder mit einem Zeiger erledigen, beides ist gleich effektiv.

Wir prüfen zunächst das erste Zeichen darauf, ob es eine ASCII-Null ist. Ist das nicht der Fall, hat sich das alles schon erledigt.

Falls ja, ersetzen wir das erste Zeichen durch ein Leerzeichen. Dann muss auch noch das zweite Zeichen auf ASCII-Null überprüft werden. Ist auch dieses eine Null, wird auch dieses ersetzt.

Beim dritten Zeichen lassen wir das Prüfen, weil im Falle Null gar nichts mehr übrig bliebe, und das lädt zu Spekulationen ein.

Unterdrückung führender Nullen während der Wandlung

Um führende Nullen schon während der Umwandlung zu unterdrücken, ist es nötig, die Prüfung auf Null schon während der Wandlung vorzunehmen. Dabei gibt es einen möglichen Fehlschluss: die zweite Ziffer darf nur dann durch Leerzeichen ersetzt werden, wenn auch die Hunderter schon Null sind. Wir brauchen daher ein Flaggenbit, das beim Hunderter-Testen gesetzt und beim Zehner-Testen ausgewertet wird.

Als beste Wahl kommt dafür die T-Flagge im SRAM infrage. Wenn die Hunderter nicht Null sind, wird T gelöscht, anderenfalls gesetzt.

evor die Zehner auf Null geprüft werden, wird die T-Flagge abgefragt und mit BRTC wird der Zehner-Check übersprungen.

Diese Variation ist im Quellcode dann aktiviert, wenn die Konstante cSuppress0 auf Eins gesetzt wird. Das hat etwas, aber nicht sehr viel Einfluss auf die Ausführungszeiten.

avr_sim mit unterdrückten Nullen Das ist das Ergebnis der Simulation von 0 mit unterdrückten führenden Nullen.


Zum Seitenanfang

©2022 by http://www.avr-asm-tutorial.net