Zum Vertauschen der Reihenfolge wird gern der Stack verwendet, so wie auch im ATmega-Beispiel (SendNumber) angegeben.
.macro negc ;Register ldi r16,0 sbc r16,@0 mov @0,r16 .endm
Führende Nullen werden für Uhrzeit-Ausgaben sowie für Hexadezimalzahlen gern verwendet.
printf(). Make Program Look Big.
Clevere C-Programmierer geben Festkommazahlen schon so aus:
printf("%d,%u", Zahl/10, Zahl%10);
printf("%d,%02u", Zahl/100, Zahl%100); //usw.
Das Punkt-Komma-Problem wird gleich mit erschlagen.
Diese Vorgehensweise erspart das Einbinden einer Gleitkomma-Bibliothek,
wobei die printf-Unterstützung einen großen Teil ausmacht.
Division mit Rest - das macht die Ausgaberoutine sowieso. Deshalb ist es besser, die Komma-Ausgabe nach oder in die Ausgabe einzubauen.
Um das Rad nicht jedesmal neu erfinden zu müssen und trotz Low-Level (Assembler) voran zu kommen.
Die Ausgaberoutine SendNumber hat folgende Features:
putchar-Routine
Einfach
.include "itoa.i90"und anschließend
;R2..R5, R18, R19 laden rcall SendNumberDezaufrufen. (Na gut,
putchar muss noch irgendwo aufrufbar sein.)
div ab-Befehl verwenden.
Außerdem kommt der selten verwendete Befehl xchd sinnvoll zum Einsatz.
;DWORD (4 Byte) durch 10 teilen: in 8 Nibbles! ;PE: R0 zeigt auf die Zahl in Big-Endian-Anordnung im iRAM ;PA: A = Rest (0..9) ; R0 zeigt hinter das Divisionsergebnis ; Zahl durch 10 dividiert ;VR: A,B=A,R0+=4,R2=0 ldiv10: mov r2,#8 ;Anzahl Nibbles clr a divl: swap a ;Rest (0..9) in High-Nibble mov b,a mov a,@r0 ;hole nächstes Nibble swap a mov @r0,a ;anderes Nibble retten bzw. richtig positionieren anl a,#0Fh orl a,b ;vorhergehenden Rest einsetzen mov b,#10 div ab xchd a,@r0 ;Ergebnis-Nibble abspeichern mov a,r2 jnb ACC.0,div1 inc r0 ;nächstes Byte div1: mov a,b ;Rest (0..9) liefern oder in nächste Runde djnz r2,divl ret ;DWORD (4 Byte) auf Null testen ;PE: R0 zeigt hinter das letzte Byte im iRAM ;PA: A = 0 wenn alle Bytes Null sind ; R0 zeigt auf das erste Byte ;VR: A,R0+=4,R2=0 lck0: mov r2,#4 clr a ck0l: dec r0 orl a,@r0 djnz r2,ck0l ckFe: ret ;Dezimal-Ausgabe; zerstört die auszugebende Zahl! ;PE: R0 zeigt auf die vzl. 32-bit-Zahl in Big-Endian-Anordnung im iRAM ;VR: A,B,R2=0,R3=0 SendNumberDez: mov r3,#0 ;Ziffernzähler snl: call ldiv10 push ACC inc r3 call lck0 ;Ergebnis Null? jnz snl ;nein, nächste Ziffer generieren snn: pop ACC add a,#'0' call putchar ;Ziffern in umgekehrter Reihenfolge ausgeben djnz r3,snn retDer Divisionsalgorithmus mit den Nibbles funktioniert für Divisoren (= Zahlenbasis) von 2 bis 16.