Rekursionseinstieg: Fakultät - Logikproblem!?

  • Du hast noch einen Fehler in deiner Fakultätsfunktion. 0! = 1 und dieser Fall wird bei dir nicht abgefragt.

    Allgemein: Rekursion ist manchmal einfacher zum hinschreiben und ja bei großen Funktionen kann, man den Stack gleich mal voll laufen lassen. Aber bitte löst doch mal die Ackermann-Funktion iterativ :P Es gibt Problemstellungen die sich mit Rekursion geschickt lösen lassen. Z. B. auf eine einfache Art einen Baum zu traversieren etc.

    Da es ja leider keinen Konditionaloperator gibt in AutoIt, würde ich das so lösen:

    [autoit]

    func fakul($n)
    if($n==0 OR $n==1) then return 1;
    return $n*fakul($n-1);
    endfunc

    [/autoit]


    Zum Vergleich Fakultät als Iteration:

    [autoit]

    func fakul($n)
    If $n < 0 Then Return -1 ; Fehler
    If $n < 2 Then Return 1
    For $i = $n-1 To 1 Step -1
    $n *= $i
    Next
    return $n
    endfunc

    [/autoit]
  • Hab die iterative Variante nochmal optimiert und für AspirinJunkie noch eine C Funktion mit inline Assembler zum testen


    [autoit]

    Func Fibonacci_i($f)
    If $f < 2 Then Return $f

    Dim $f1 = 1, $f2 = 1

    For $i = 3 To $f
    $f1 = $f1 + $f2
    If $i < $f Then
    $f2 = $f1 + $f2
    $i = $i + 1
    Else
    Return $f1
    EndIf
    Next

    Return $f2
    EndFunc

    [/autoit]
  • Danke - würde ich gerne mal mit testen aber ich nutze minGW als Compiler und der nutzt GAS statt NASM.
    Brauche daher den Inline-Code in AT&T-Syntax statt Intel.

    Habe bisher das als Umbau gemacht:

    Spoiler anzeigen


    Allerdings gibt der Compiler mir folgende Fehlermeldung:

    Zitat

    [Linker error] undefined reference to `n'


    Da ich sonst nichts mit Assembler zu tun habe weiß ich auch nicht wie ich die C-Variable n korrekt in den Inline-Assembler-Code integriere.

  • So wie ich das verstanden habe könnte das so gehen
    Link

  • Jepp so geht es tatsächlich - Dankeschön.
    Hier nun der Gesamtvergleich in C++:

    Spoiler anzeigen


    Um dennoch genauer als eine Millisekunde zu kommen hab ich mich erstmal etwas anders beholfen bis jemand eine bessere Möglichkeit findet.
    Laut den jetzigen Ergebnissen ist die Inline-Assembler-Variante klar die schnellste Methode gefolgt von der 2. Rekursionsmethode und dann der iterativen.
    Bleibt dennoch das Problem mit der Bereichsüberschreitung ab Fib(47).

    Hab das zum Testen auch mal bereits kompiliert in den Anhang ... ja "gehangen".

    Edit: So hab jetzt die Methoden konsequent auf unsigned long long umgestellt um den Wertebereich so weit wie möglich zu vergrößern.
    Außer natürlich bei der Assembler-Methode - die bleibt auf unsigned int (Will mir nicht vorstellen was man da für Kopfstände machen muss um unsigned long long hinzubekommen... :S )
    Heißt bis auf die Assemblermethode kann man mit den anderen bis auf Fib(96) rechnen - dann ist Schluss.
    Will man mehr muss man ganz andere, eigene und vor allem langsamere Variablentypen bemühen. (Ähnlich wie bei der bigint.au3)

  • Mh man könnte das ganze noch auf einem FPGA/CPLD mit VHDL implementieren. Wenn man geschickt vorgeht müsste das nochmals schneller sein. Könnte man ja mit nem Logikanalysator durchmessen.

  • Hi zusammen,
    da es ja auch zwei Möglichkeiten gibt, Assembler direkt in AutoIt einzubinden, war ich mal so frei und habe die freundlicherweise schon von RAPTOR-ONE im Assemblercode vorgestellte Fibonaccifunktion "AutoItkompatibel" gemacht.

    Die erste Variante benötigt keinerlei Includes, im Prinzip wird der Bytecode in den Speicher geschrieben und per Funktion dort aufgerufen. Man könnte das Script noch etwas "tunen", aber ich habe es der Übersichtlichkeit wegen so gemacht....
    Die Zeiten sind kein Witz, ich vermute, daß die AutoIt-Timer einfach an die Grenzen kommen. Die Berechnung der Zahl (egal welche^^) erfolgt auf meinem Rechner in ca. zwei hundertstel Millisekunden
    Da ist vom speed her nicht mehr viel zu verbessern denke ich 8o

    Spoiler anzeigen
    [autoit]

    ;idea by trancexx
    ;Assemblerscript by RAPTOR-ONE
    ;binary translated and hardcoded by Andy

    [/autoit] [autoit][/autoit] [autoit]

    Local $tCodeBuffer = DllStructCreate("byte[512]") ;Speicher für den assemblercode belegen

    [/autoit] [autoit][/autoit] [autoit]

    $g=0 ;timestamp merken
    for $i=1 to 46 ;die Fibonaccizahlen von 1-46

    [/autoit] [autoit][/autoit] [autoit]

    DllStructSetData($tCodeBuffer, 1, "0x558BECC7C1"& Hex(Binary($i))& _ ;bytecode "hardcoded"
    "C7C001000000C7C30100000081F902000000761A81E90200000003C38BD02BD349E30D03C28BD82BDA67E2EEEB028BC15DC3")

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    $t=timerinit() ;timestamp merken
    $a= DllCall("user32.dll", "int", "CallWindowProcW", _ ;bytecode aufrufen, rückgabe in a[0]
    "ptr", dllstructgetptr($tCodeBuffer), _
    "int", 0, _
    "int", 0, _
    "int", 0, _
    "int", 0)
    $x=timerdiff($t)
    $g+=$x
    consolewrite ("Die "&$i&". Fibonaccizahl lautet "&$a[0] &" Berechnungszeit: "&$x & " ms"&@CRLF )
    next

    [/autoit] [autoit][/autoit] [autoit]

    ConsoleWrite( @CRLF & "Gesamtzeit: "&$g&" ms" & @CRLF )

    [/autoit]


    Für die 2. Variante benötigt man die Asm.AU3 autoit.de/wcf/attachment/7479/
    Allerdings ist jetzt auch der Code wesentlich lesbarer. Da bei jedem Aufruf der Funktion der komplette Assembler gestartet werden muss, ist diese Variante nur sinnvoll, wenn es nicht auf die letzte hunderttausenstel Sekunde ankommt...
    Ich habe die Mnemonics in Bytecode übersetzt, jetzt sieht man auch, woher der beim Beispiel 1 kommt^^

    Spoiler anzeigen
    [autoit]

    #include <ASM.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Global $Asm = AsmInit() ;Assembler initialisieren
    Local $g=0 ;gesamtzeit

    [/autoit] [autoit][/autoit] [autoit]

    for $i=1 to 45 ;Fibonaccizahlen von 1-45
    $t=timerinit()
    $a=fibonacci($i)
    $x=timerdiff($t)
    $g+=$x ;gesamtzeit
    consolewrite ("Die "&$i&". Fibonaccizahl lautet "&$a &" Berechnungszeit: "&$x & " ms"&@CRLF )
    next

    [/autoit] [autoit][/autoit] [autoit]

    ConsoleWrite( @CRLF & "Gesamtzeit: "&$g&" ms" & @CRLF )

    [/autoit] [autoit][/autoit] [autoit]

    AsmExit($Asm) ;asmobjekt freigeben
    Exit

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func Fibonacci($fibo)
    ; Demo 1: Using Parameters
    AsmReset($Asm)

    [/autoit] [autoit][/autoit] [autoit]

    AsmAdd($Asm, "push ebp");55
    AsmAdd($Asm, "mov ebp, esp");8B EC
    AsmAdd($Asm, "mov ecx, [ebp + 08]");8B 8D XXXXXXXX ;übergebener parameter
    AsmAdd($Asm, "mov eax, 1");C7 C0 01000000
    AsmAdd($Asm, "mov ebx, 1");C7 C3 01000000
    AsmAdd($Asm, "cmp ecx, 2");81 F9 02000000
    AsmAdd($Asm, "jbe $+1C");76 1A ;jbe @ende
    AsmAdd($Asm, "sub ecx, 2");81 E9 02000000
    AsmAdd($Asm, "start:")
    AsmAdd($Asm, "add eax, ebx");03 C3 ;// fn2(ax) = fn1(ax) + fn(bx)
    AsmAdd($Asm, "mov edx, eax");8B D0 ;// fn2(cx) = fn2(ax)
    AsmAdd($Asm, "sub edx, ebx");2B D3 ;// fn1(dx) = fn2(dx) - fn(bx)

    [/autoit] [autoit][/autoit] [autoit]

    AsmAdd($Asm, "dec ecx"); ;loop @startx
    AsmAdd($Asm, "jecxz $+F"); ;loop @startx
    AsmAdd($Asm, "startx:")
    AsmAdd($Asm, "add eax, edx");03 C2 ;// fn2(ax) = fn1(ax) + fn(dx)
    AsmAdd($Asm, "mov ebx, eax");8B D8 ;// fn2(bx) = fn2(ax)
    AsmAdd($Asm, "sub ebx, edx");2B DA ;// fn1(bx) = fn2(bx) - fn(dx)
    AsmAdd($Asm, "loop @start");67 E2 EE
    AsmAdd($Asm, "jmp $+4") ;EB 02 ;jmp @ende")
    AsmAdd($Asm, "endek2:")
    AsmAdd($Asm, "mov eax, ecx");8B C1
    AsmAdd($Asm, "ende:")
    AsmAdd($Asm, "pop ebp");5D
    AsmAdd($Asm, "retn 4") ;C2 0400

    [/autoit] [autoit][/autoit] [autoit]

    ;ConsoleWrite(String(AsmGetBinary($Asm)) & @CRLF) ;zeigt den bytecode

    [/autoit] [autoit][/autoit] [autoit]

    $Ret = MemoryFuncCall("int", AsmGetPtr($Asm), "int", $fibo)
    return $ret[0]
    EndFunc

    [/autoit] [autoit][/autoit] [autoit][/autoit]
  • Andy:

    das hatte ich auch gestern Abend noch probiert, aber ich weiß nicht, wie ich den Code sauber umwandeln kann.

    Hier mein Versuch:

    [autoit]


    #include <ASM.au3>

    [/autoit][autoit][/autoit][autoit]

    ; Initial an asm object
    Global $Asm = AsmInit()
    $n = 30
    AsmReset($Asm) ;Zeilennummer Kommentar
    AsmAdd($Asm, " mov ecx, " & $n ) ;0E
    AsmAdd($Asm, " mov eax, 1" ) ;13
    AsmAdd($Asm, " mov ebx, 1" ) ;19
    AsmAdd($Asm, " cmp ecx, 2" ) ;1E
    AsmAdd($Asm, " jbe $+19" ) ;21 jbe @endek2
    AsmAdd($Asm, " sub ecx, 2" ) ;23
    AsmAdd($Asm, "start: ")
    AsmAdd($Asm, " add eax, ebx" ) ;26 fn2(ax) = fn1(ax) + fn(bx)
    AsmAdd($Asm, " mov edx, eax" ) ;28 fn2(cx) = fn2(ax)
    AsmAdd($Asm, " sub edx, ebx" ) ;2A fn1(dx) = fn2(dx) - fn(bx)
    AsmAdd($Asm, " loop $+4" ) ;2C loop @start2
    AsmAdd($Asm, " jmp $+E" ) ;2E jmp @ende"
    AsmAdd($Asm, "start2: ")
    AsmAdd($Asm, " add eax, edx" ) ;30 fn2(ax) = fn1(ax) + fn(dx)
    AsmAdd($Asm, " mov ebx, eax" ) ;32 fn2(bx) = fn2(ax)
    AsmAdd($Asm, " sub ebx, edx" ) ;34 fn1(bx) = fn2(bx) - fn(dx)
    AsmAdd($Asm, " loop @start" ) ;36 loop @start
    AsmAdd($Asm, " jmp $+4" ) ;38 jmp @ende"
    AsmAdd($Asm, "endek2: ")
    AsmAdd($Asm, " mov eax, ecx" ) ;3A
    AsmAdd($Asm, "ende: ")
    AsmAdd($Asm, " ret ") ;3C

    [/autoit][autoit][/autoit][autoit]

    ConsoleWrite(String(AsmGetBinary($Asm)) & @CRLF)

    [/autoit][autoit][/autoit][autoit]

    $Ret = MemoryFuncCall("int", AsmGetPtr($Asm))

    [/autoit][autoit][/autoit][autoit]

    MsgBox(0, "Demo 0: Fibonacci via Inline ASM", "Fibonacci (" & $n & ") = " & $Ret[0])

    [/autoit][autoit][/autoit][autoit]

    ; Release the asm object
    AsmExit($Asm)
    Exit

    [/autoit]

    Ich hatte trancexx gefragt, aber sie konnte / wollte mir nicht helfen!

    Kannst du mir den Weg erklären, wie du das gemacht hast?

    Danke,
    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

  • ... ohne Worte...

    ... eigentlich wollte ich ja nur anmerken das der Unterschied nicht der Rekursion geschuldet ist sondern der Berechnung....
    .... aber das jetzt sowas hier dabei enstanden ist.... ne....

    :thumbup:

    Jungs ich hab ne Menge hierbei gelernt - Danke an ALLE!

  • Hi UEZ,

    ähnlich war mein Versuch anfangs auch, allerdings bekam ich permanent Fehlermeldungen. Also habe ich den Binärstring in eine Datei geschrieben und diese mit dem Debugger IDA eingelesen. So fand ich heraus, daß der "AutoIt-Assembler" keine Vorwärts-Sprünge beim LOOP-Befehl auflösen kann!
    Das heisst,

    [autoit]

    AsmAdd($Asm, " loop $+4" ) ;2C loop @start2
    AsmAdd($Asm, " jmp $+E" ) ;2E jmp @ende"
    AsmAdd($Asm, "start2: ")

    [/autoit]

    funktioniert nicht!

    Also habe ich die Zeilen mit

    [autoit]

    AsmAdd($Asm, "dec ecx"); ;ecx = ecx -1
    AsmAdd($Asm, "jecxz $+F"); ;Jump to target , if ECX is Zero

    [/autoit]

    angepasst, und nu gehts^^

    Am meisten hat mich fasziniert, Programme direkt aus dem Speicher auszuführen. Man spart also den (im Vergleich zur Laufzeit der Funktion) extrem langsamen DLL-Aufruf. Ich habe leider von C nicht sonderlich viel Ahnung, vielleicht gäbe es eine Möglichkeit, "kompilierten" C-code direkt in den Speicher einzupflanzen (wie in meinem 1. Assemblerbeispiel). Dann bräuchte man die Umwege über den Assembler auch nicht mehr zu machen....

    ciao
    Andy


    "Schlechtes Benehmen halten die Leute doch nur deswegen für eine Art Vorrecht, weil keiner ihnen aufs Maul haut." Klaus Kinski
    "Hint: Write comments after each line. So you can (better) see what your program does and what it not does. And we can see what you're thinking what your program does and we can point to the missunderstandings." A-Jay

    Wie man Fragen richtig stellt... Tutorial: Wie man Script-Fehler findet und beseitigt...X-Y-Problem

    2 Mal editiert, zuletzt von Andy (26. Januar 2010 um 15:25)

  • Ich benutze HIEW um die Hex Codes in die Datei und W32Dasm um den ASM Code angezeigt zu bekommen!

    Ich habe auch das Bespiel von RAPTOR-ONE versucht in ASM zu bekommen, aber irgendwie will es nicht so richtig! Deins geht ja wunderbar.

    Ich würde gerne wissen, woran das liegt.

    Ich habe dein Beispiel mit der Demo3 (mein Versuch) erweitert:

    Spoiler anzeigen
    [autoit]


    Func Demo3($n)
    Func Demo3($n)
    ; Initial an asm object
    AsmReset($Asm) ;Zeilennummer Kommentar
    AsmAdd($Asm, " push ebp" ) ;00
    AsmAdd($Asm, " mov ebp, esp" ) ;01
    AsmAdd($Asm, " mov ecx, [ebp + 08]") ;03
    AsmAdd($Asm, " mov eax, 1" ) ;09
    AsmAdd($Asm, " mov ebx, 1" ) ;0F
    AsmAdd($Asm, " cmp ecx, 2" ) ;15
    AsmAdd($Asm, " jbe $+1E" ) ;1B jbe @endek2
    AsmAdd($Asm, " sub ecx, 2" ) ;1D
    AsmAdd($Asm, "start:" )
    AsmAdd($Asm, " add eax, ebx" ) ;23 fn2(ax) = fn1(ax) + fn(bx)
    AsmAdd($Asm, " mov edx, eax" ) ;25 fn2(cx) = fn2(ax)
    AsmAdd($Asm, " sub edx, ebx" ) ;27 fn1(dx) = fn2(dx) - fn(bx)
    AsmAdd($Asm, " loop $+5" ) ;29 loop @start2
    AsmAdd($Asm, " jmp $+F" ) ;2C jmp @ende"
    AsmAdd($Asm, "start2:" )
    AsmAdd($Asm, " add eax, edx" ) ;2E fn2(ax) = fn1(ax) + fn(dx)
    AsmAdd($Asm, " mov ebx, eax" ) ;30 fn2(bx) = fn2(ax)
    AsmAdd($Asm, " sub ebx, edx" ) ;32 fn1(bx) = fn2(bx) - fn(dx)
    AsmAdd($Asm, " loop @start" ) ;34 loop @start
    AsmAdd($Asm, " jmp $+4" ) ;37 jmp @ende"
    AsmAdd($Asm, "endek2:" )
    AsmAdd($Asm, " mov eax, ecx" ) ;39
    AsmAdd($Asm, "ende: " )
    AsmAdd($Asm, " pop ebp" ) ;3B
    AsmAdd($Asm, " ret" ) ;3C

    [/autoit] [autoit][/autoit] [autoit]

    ConsoleWrite(String(AsmGetBinary($Asm)) & @CRLF)

    [/autoit] [autoit][/autoit] [autoit]

    $Ret = MemoryFuncCall("int", AsmGetPtr($Asm), "int", $n)

    [/autoit] [autoit][/autoit] [autoit]

    MsgBox(0, "Demo 0: Fibonacci via Inline ASM", "Fibonacci (" & $n & ") = " & $Ret[0])

    [/autoit] [autoit][/autoit] [autoit]

    ; Release the asm object
    AsmExit($Asm)
    EndFunc

    [/autoit]

    Hier der Disassembler Code:

    Spoiler anzeigen

    Weiß du, warum meins nicht funktioniert?

    Danke,
    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

    Einmal editiert, zuletzt von UEZ (26. Januar 2010 um 14:33)

  • ja, wie schon geschrieben, der " AUTOIT-Assembler" bekommt es nicht auf die Reihe, einen LOOP mit "nach vorne" gerichteter Adresse auszuführen (bei deinem Autoit-Assembler Zeile 17) . D.h. dort ist irgendetwas im Code suboptimal/buggy. Also muß man sich behelfen und "zu Fuß" den Loop emulieren, also ecx decrementieren, auf Zeroflag testen und abhängig davon jumpen.
    Was allerdings ohne weiteres funktionieren sollte, ist per irgendeinem Assembler den BYTECODE zu generieren und diesen dann auszuführen. Die Übergabeparameter müssen dann natürlich im bytecode per Hex(Binary($parameter)) ersetzt werden!

  • ja, wie schon geschrieben, der " AUTOIT-Assembler" bekommt es nicht auf die Reihe, einen LOOP mit "nach vorne" gerichteter Adresse auszuführen (bei deinem Autoit-Assembler Zeile 17) . D.h. dort ist irgendetwas im Code suboptimal/buggy. Also muß man sich behelfen und "zu Fuß" den Loop emulieren, also ecx decrementieren, auf Zeroflag testen und abhängig davon jumpen.
    Was allerdings ohne weiteres funktionieren sollte, ist per irgendeinem Assembler den BYTECODE zu generieren und diesen dann auszuführen. Die Übergabeparameter müssen dann natürlich im bytecode per Hex(Binary($parameter)) ersetzt werden!


    Dann kann man gleich 2 Versionen erstellen, einmal x86 und einmal x64. Damit läuft es dann auch im 64bit-modus von AutoIt ;)

  • Zitat

    einmal x86 und einmal x64

    genau so siehts aus^^.
    Da der Code auch bei "größeren" Projekten sehr kompakt wird, könnte man beide Funktionen abhängig vom BS implementieren, falls es wirklich mal auf Geschwindigkeit ankommen sollte.

    Als Beispiel mal den CRC32-Checksum in Assembler:
    Ich habe die Bytecodes wieder angefügt

    Spoiler anzeigen
    [autoit]

    #include <ASM.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Func AsmCRC32($Data, $CRC32 = -1)
    Local $AsmObj = AsmInit()
    AsmAdd($AsmObj, " enter 400h,0 ");C8 00 0400
    AsmAdd($AsmObj, " push ebx ");53
    AsmAdd($AsmObj, " mov edx,0EDB88320h ");C7 C2 2083B8ED
    AsmAdd($AsmObj, " mov ecx,100h ");C7 C1 00010000
    AsmAdd($AsmObj, "L3: ")
    AsmAdd($AsmObj, " lea eax,[ecx-1] ");8D 81 FFFFFFFF
    AsmAdd($AsmObj, " push ecx ");51
    AsmAdd($AsmObj, " push 8 ");68 08000000
    AsmAdd($AsmObj, " pop ecx ");59
    AsmAdd($AsmObj, "L2: ")
    AsmAdd($AsmObj, " shr eax,1 ");C1 E8 01
    AsmAdd($AsmObj, " jnc $+4 ");73 02 ; jnc @L1
    AsmAdd($AsmObj, " xor eax,edx ");33 C2
    AsmAdd($AsmObj, "L1: ")
    AsmAdd($AsmObj, " loop @L2 ");67 E2 F6
    AsmAdd($AsmObj, " pop ecx ");59
    AsmAdd($AsmObj, " mov [ebp+ecx*4-404h],eax");89 84 8D FCFBFFFF

    [/autoit] [autoit][/autoit] [autoit]

    AsmAdd($AsmObj, " loop @L3 ");67 E2 DE
    AsmAdd($AsmObj, " mov ebx,[ebp+8] ");8B 9D 08000000
    AsmAdd($AsmObj, " mov ecx,[ebp+0Ch] ");8B 8D 0C000000
    AsmAdd($AsmObj, " mov eax,[ebp+10h] ");8B 85 10000000
    AsmAdd($AsmObj, " test ebx,ebx ");85DB
    ;
    AsmAdd($AsmObj, " je $+19 ");74 17 ;je @L4
    AsmAdd($AsmObj, " jecxz $+17 ");E3 15 ;jecxz @L4
    AsmAdd($AsmObj, "L5: ")
    AsmAdd($AsmObj, " mov dl,[ebx] ");8A 13 ;235
    AsmAdd($AsmObj, " xor dl,al ");32 D0
    AsmAdd($AsmObj, " movzx edx,dl ");0F B6 D2
    AsmAdd($AsmObj, " shr eax,8 ");C1 E8 08
    AsmAdd($AsmObj, " xor eax,[ebp+edx*4-400h]");33 8495 00FCFFFF
    AsmAdd($AsmObj, " inc ebx ");43
    AsmAdd($AsmObj, " loop @L5 ");67 E2 EB
    AsmAdd($AsmObj, "L4: ")
    AsmAdd($AsmObj, " not eax ");F7D0
    AsmAdd($AsmObj, " pop ebx ");5B
    AsmAdd($AsmObj, " leave ");C9
    AsmAdd($AsmObj, " ret ");C3

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Local $Input = DllStructCreate("byte[" & BinaryLen($Data) & "]")
    DllStructSetData($Input, 1, $Data)

    [/autoit] [autoit][/autoit] [autoit]

    Local $Ret = MemoryFuncCall("uint:cdecl", AsmGetPtr($AsmObj), "ptr", DllStructGetPtr($Input), "uint", BinaryLen($Data), "int", $CRC32)
    AsmExit($AsmObj)

    [/autoit] [autoit][/autoit] [autoit]

    Return $Ret[0]
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    $CRC32 = AsmCRC32("The quick brown fox jumps over the lazy dog")
    MsgBox(0, 'Method 1 Result', Hex($CRC32))

    [/autoit] [autoit][/autoit] [autoit][/autoit]

    /EDIT/ Dateigrößen von 22MB werden in 13 Millisekunden abgefertigt....

    ciao
    Andy


    "Schlechtes Benehmen halten die Leute doch nur deswegen für eine Art Vorrecht, weil keiner ihnen aufs Maul haut." Klaus Kinski
    "Hint: Write comments after each line. So you can (better) see what your program does and what it not does. And we can see what you're thinking what your program does and we can point to the missunderstandings." A-Jay

    Wie man Fragen richtig stellt... Tutorial: Wie man Script-Fehler findet und beseitigt...X-Y-Problem

    Einmal editiert, zuletzt von Andy (26. Januar 2010 um 15:41)

  • Zitat

    Dann kann man gleich 2 Versionen erstellen, einmal x86 und einmal x64. Damit läuft es dann auch im 64bit-modus von AutoIt

    Dazu habe ich noch eine Frage. Gesetzt den Fall, es wird mit AutoIt32 ein Script gebastelt, welches (Im eingefügten Bytecode) 64-Bit Befehle verarbeitet. Werden die dann auf einer 64-Bit-Maschine mit 32-Bit BS auch ausgeführt, oder führt das zu einer Schutzverletzung? Eigentlich sollte das BS davon ja überhaupt nichts mitbekommen, oder werden 64-Bitbefehle erkannt und nicht zugelassen?

  • Dazu habe ich noch eine Frage. Gesetzt den Fall, es wird mit AutoIt32 ein Script gebastelt, welches (Im eingefügten Bytecode) 64-Bit Befehle verarbeitet. Werden die dann auf einer 64-Bit-Maschine mit 32-Bit BS auch ausgeführt, oder führt das zu einer Schutzverletzung? Eigentlich sollte das BS davon ja überhaupt nichts mitbekommen, oder werden 64-Bitbefehle erkannt und nicht zugelassen?


    Wenn du AutoIt im 32bit-Modus ausführst, kannst du auch nur 32bit-Code verwenden. 64bit wird werder in der virtuellen 32bit-Umgebung von 64-Windows noch in 32bit-Win auf x64-CPUs unterstützt. (Die 64bit-Befehle werden nicht erkannt und können deshalb nicht ausgeführt werden)

    Edit: wenn das Betriebssystem nichts davon mitbekommen würde, müsstetst du auch x64-Exen auf x32 starten können, da diese ebenfalls in Binärform vorliegen ...

  • Ich erwähnte oben, daß der Autoit-Code im Zusammenspiel mit dem Bytecode noch zu "tunen" sei...

    [autoit]

    $tCodeBuffer = DllStructCreate("byte[512]") ;Speicher für den assemblercode belegen
    DllStructSetData($tCodeBuffer, 1, "0x558BECC7C100000000C7C001000000C7C30100000081F902000000761A81E90200000003C38BD02BD349E30D03C28BD82BDA67E2EEEB028BC15DC3") ;das ist der bytecode
    $substruct = DllStructCreate("byte[4]", DllStructGetPtr($tCodeBuffer) + 5) ;position der Variablen im bytecode

    [/autoit][autoit][/autoit][autoit]

    For $i = 1 To 46 ;die Fibonaccizahlen von 1-46
    DllStructSetData($substruct, 1, $i) ; Inhalt der Variablen an die Position im Bytecode setzen
    $a = DllCall("user32.dll", "int", "CallWindowProcW", "ptr", DllStructGetPtr($tCodeBuffer), "int", 0, "int", 0, "int", 0, "int", 0);bytecode aufrufen, rückgabe in a[0]
    ConsoleWrite("Die " & $i & ". Fibonaccizahl lautet " & $a[0] & " Berechnungszeit: " & $x & " ms" & @CRLF)
    Next

    [/autoit]

    Auf diese Art und Weise lassen sich nicht nur Variablen, sondern auch Pointer auf API-Funktionen übergeben. Da diese schon im Speicher stehen, entfällt das komplette (mit relativ viel Overhead verbundene) Procedere des DLL-Calls. Funktionsparameter in der richtigen Reihenfolge auf den Stack pushen, Funktionspointer in eax, Call eax, fertig....ggf werde ich dafür auch mal ein Beispiel machen. Gerade für sehr viele Funktionsaufrufe wird sich das lohnen, der Overhead fällt ja komplett weg!