Buchempfehlung
Mikrocomputertechnik mit Controllern der Atmel AVR-RISC-Familie
Mikrocomputertechnik mit Controllern der Atmel AVR-RISC-Familie
Umfassend, aber leicht verständlich führt dieses Buch in die Programmierung von ATMEL AVR Mikrocontrollern ein. [Mehr Infos...]
FreeBASIC-Chat
Es sind Benutzer im FreeBASIC-Chat online.
(Stand:  )
FreeBASIC bei Twitter
Twitter FreeBASIC-Nachrichten jetzt auch über Twitter erhalten. Follow us!

fb:porticula NoPaste

Info
Info / Hilfe
Liste
Übersicht / Liste
Neu
Datei hochladen
Suche
Quellcode suchen
Download
Dateidownload

naked Functions

Uploader:RedakteurVolta
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