Habe übrigens in
@Dirk s Code (#6) noch einen Fehler gefunden, den Gerd (#14) ein wenig ... ineffizient behoben hat.
Dirk kopiert sich in Zeile 10 BCDdata in 'ne Extravariable MSBdata, shiftet aber dann BCDdata statt MSBdata.
Gerd hat zur Korrektur dann einfach ab Zeile 20 komplett mit BCDdata weitergerechnet. Dadurch wird natürlich der Inhalt von BCDdata verändert. Wenn das akzeptabel ist, kann man sich das vorherige kopieren sparen.
Soo...
hab mal versucht, Dirks und meinen Weg als Bascom-Subroutine umzusetzen:
CodeBox BascomAVR
$regfile = "m8def.dat"
$crystal = 8000000
Dim Bcd_in As Byte , Bin_out As Byte
Declare Function Makedec_dirk(byref Bcddata As Byte ) As Byte
Declare Function Makedec_lotadac(byref Bcddata As Byte) As Byte
Bcd_in = &B01000010 '&B01000010 'Zweiundvierzig als gBCD
Bin_out = Makedec(bcd_in) 'Bascom-Makedec
Bin_out = 0
Bin_out = Makedec_dirk(bcd_in) 'Dirk
Bin_out = 0
Bin_out = Makedec_lotadac(bcd_in) 'LotadaC
Bin_out = 0
End 'end program
'****************Subroutinen*****************
Function Makedec_dirk(byref Bcddata As Byte ) As Byte
Dim Lsbdata As Byte , Msbdata As Byte
Lsbdata = Bcddata And &B00001111 '"Einer" extrahieren
Msbdata = Bcddata
Shift Msbdata , Right , 4 '"Zehner" extrahieren
Makedec_dirk = 10 * Msbdata '"Zehner" ausrechnen
Makedec_dirk = Makedec_dirk + Lsbdata 'Summieren
End Function
Function Makedec_lotadac(byref Bcddata As Byte) As Byte
'Der Funktionsaufruf pusht erst die SRAM-Adresse von Makedec_lotadac,
'danach die vom Parameter Bcddate (byref) auf den Softstack.
'Dieses PUSHen geschieht über das X-Doppelregister,
'X zeigt also beim Eintritt in die eigentliche Funktion auf den letzten Parameter
$asm
LD R16, X 'BCDdata laden
MOV R17, R16 'Kopie für "Einer"
ANDI R17, &b00001111 '"Einer" extrahieren
ANDI R16, &b11110000 '"Zehner" extrahieren
LSR R16 '"Zehner"*8
ADD R17, R16 'zum "Einer" addieren
LSR R16
LSR R16 '"Zehner"*2
ADD R17, R16 'zum "Einer" addieren
Loadadr Makedec_lotadac , X 'Makedec-Adresse nach X laden
ST X, R17 'Ergebnis abspeichern
$end Asm
End Function
Das Original-Makedec braucht (wie vorhergesagt) variabel viele Takte, im worst case ("Neunundneunzig") sinds 63Takte.
Dirks Weg benötigt ca. 100 Takte, was neben dem Subroutinen Overhead (ca. 15 Takte) vor allen Dingen an den vielen SRAM-Zugriffen liegt (bei jedem Lese- und Schreibzugriff wird die Variable aus dem SRAM gelesen/dorthin geschrieben). Trotz automatischer Verwendung der MUL-Instruktion.
Mein Weg braucht konstant 37 Takte. Bascom für die Vierziger 38 Takte, von 0..9 nur 18 Takte.
Besser bekomme ich es mit sauberen Funktionen nicht hin (wie gesagt erzeugt bereits die Subroutine selbst beim Aufruf 15 Takte) - Bascom-Makedec macht das nicht, und kann außerdem auf die Adressen der Variablen direkt zugreifen. Ich muß mir die erst aus dem Softstack ziehen (Softstack in Pointer-Register laden, und dann indirekt laden/speichern).