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
	


			FreeBASIC-Nachrichten jetzt auch über Twitter erhalten. Follow us!



