fb:porticula NoPaste
naked Functions
Uploader: | Volta |
Datum/Zeit: | 21.01.2009 19:19:39 |
' dies war aus dem vorhergehenden Test die schnellste Funktion
Function Quersum_i (n As Integer) As Integer
Dim As Integer i, tmp = Abs(n) 'Abs(n) damit das Ergebnis positiv wird
While tmp ' Abbruch bei n = 0
i += tmp Mod 10 ' plus Einerstelle
tmp \= 10 ':10 = eine Dezimalstelle nach rechts
Wend
Function = i
End Function
'in Assembler ist das mehr Quelltext, aber wesentlich kürzerer Code ;)
Function Quersum_asm (n As Integer) As Integer
Dim As Integer tmp = Abs(n) 'Abs(n) damit das Ergebnis positiv wird
Asm
mov eax, [tmp]
mov ecx, 10
xor ebx, ebx '= i
.balign 16
nochmal:
Xor edx, edx
idiv ecx 'tmp \= 10
add ebx, edx 'i += tmp Mod 10
or eax, eax 'While tmp<>0
jnz nochmal 'Wend
mov eax, ebx
mov [Function], ebx
End Asm
End Function
'##########################################################################
'Achtung dies funktioniert erst mit dem FBC 0.21.0 vom Dezember 2008,
'erst hier wurde die naked - Option eingebaut.
'##########################################################################
'Am Anfang und Ende einer Prozedur werdem vom Kompeiler einige, organisatorisch
'wichtige, Befehle eingesetzt. Dieser 'Prolog' und 'Epilog' sichert die
'Datenübergabe, erstellt Speicherplatz für lokale Variable und sorgt für einen
'sauberen Abgang aus der Prozedur. Mit einer nakten (naked) Prozedur muss man
'auf diesen Komfort zum größten Teil verzichten und selbst Hand anlegen...
'Specken wir den Aufruf der Funktion mal ab.
Function Quersum_nak Naked (n As Integer) As Integer
Asm
'ABS(n)
mov eax, [esp+4] 'n direkt vom Stack holen
mov ebx, eax 'n sichern in ebx
neg eax 'eax = -eax
cmovs eax,ebx'wenn eax negativ war, n aus ebx holen
mov ecx, 10
xor ebx, ebx '= i
.balign 16
weiter:
Xor edx, edx
idiv ecx 'tmp \= 10
add ebx, edx 'i += tmp Mod 10
or eax, eax 'While tmp<>0
jnz weiter 'Wend
mov eax, ebx 'eax hat Rückgabewert
ret 4 'bei stdall Stack hier bereinigen
End Asm
End Function
'##########################################################################
'Hinweis zu Naked :
'Der Aufruf von Naked ohne Cdecl kann bei Linux Probleme bereiten.
'siehe : http://freebasic.net/wiki/KeyPgNaked
'Function Funktionsname Naked Cdecl (n As Integer) As Integer
' Asm
' ..
' ..
' ret 'bei cdecl nur ret
' End Asm 'da Aufrufer den Stack bereinigt
'End Function
'##########################################################################
Dim As Integer j, i = 1234567895
Dim t As Double
Print "Quersumme von " & i ;" ="; Quersum_i(i);" (Iteratives BASIC Programm)"
Print "Quersumme von " & -i ;" ="; Quersum_i(-i);" (Iteratives BASIC Programm)"
Print "Test (2000000 mal) in: ";
t = Timer
For j = 1 To 2000000
Quersum_i(i)
Quersum_i(-i)
Next
t = Timer-t
Print Left(Str(t),5);" Sekunden."
'Na bitte, mehr als 2x so schneller, hier lohnt sich Asm ..
Print "Quersumme von " & i ;" ="; Quersum_asm(i);" (Inline Programmierung)"
Print "Quersumme von " & -i ;" ="; Quersum_asm(-i);" (Inline Programmierung)"
Print "Test (3000000 mal) in: ";
t = Timer
For j = 1 To 3000000
Quersum_asm(i)
Quersum_asm(-i)
Next
t = Timer-t
Print Left(Str(t),5);" Sekunden."
'Na ja, nur 5% (80 ms) besser, aber immerhin .. :)
'Bei grafischen Anwendungen könnte das ein Bild mehr pro Sekunde sein.
Print "Quersumme von " & i ;" ="; Quersum_nak(i);" (Inline mit Naked Funktion)"
Print "Quersumme von " & -i ;" ="; Quersum_nak(-i);" (Inline mit Naked Funktion)"
Print "Test (3000000 mal) in: ";
t = Timer
For j = 1 To 3000000
Quersum_nak(i)
Quersum_nak(-i)
Next
t = Timer-t
Print Left(Str(t),5);" Sekunden."
Sleep