1. Dashboard
  2. Mitglieder
    1. Letzte Aktivitäten
    2. Benutzer online
    3. Team
    4. Mitgliedersuche
  3. Forenregeln
  4. Forum
    1. Unerledigte Themen
  • Anmelden
  • Registrieren
  • Suche
Alles
  • Alles
  • Artikel
  • Seiten
  • Forum
  • Erweiterte Suche
  1. AutoIt.de - Das deutschsprachige Forum.
  2. Mitglieder
  3. Oscar

Beiträge von Oscar

  • wav. datei abspielen

    • Oscar
    • 13. Januar 2018 um 17:33

    Nach dem Sleep(4000) muss ein WEnd stehen und bei _SoundOpen musst Du den korrekten Pfad zu Deiner Sounddatei eintragen.

    Den korrekten Pfad können wir nicht kennen, weil die Datei bei Dir auf der Festplatte liegt.

    Ehrlich gesagt verstehe ich auch nicht so ganz, wieso Du mit diesen einfach Grundlagen bereits Probleme hast. Du bist seit 2009 hier im Forum angemeldet und hast immer noch Grundlagen-Probleme?

  • wav. datei abspielen

    • Oscar
    • 13. Januar 2018 um 14:22

    Und Dir ist nicht aufgefallen, dass da ein WEnd fehlt?

    Und der Pfad bei _SoundOpen falsch ist?

    Wie wäre es mit etwas ErrorHandling?

  • Hilfe bei _Ispressed einzelne und auch mehrere Tasten gedrückt // Motorsteuerung

    • Oscar
    • 13. Januar 2018 um 13:55

    Naja, so schwer ist das eigentlich nicht!

    Man benötigt nur etwas Logik, um die Tasten den Motoren zuzuordnen. Und solange es nur um AN/AUS bei den Motoren geht, ist die Logik dafür recht simpel ("1" = Motor vorwärts, "0" = Stop, "-1" = Motor rückwärts):

    AutoIt
    #include <GUIConstantsEx.au3>
    #include <WinAPISys.au3>
    
    Global $aKeys[4] = [0x57, 0x53, 0x41, 0x44] ; <= W,S,A,D
    Global $iState, $iOldState = -1, $iEngineA = 0, $iEngineB = 0
    Global $hGui = GUICreate('Test', 240, 120)
    GUISetFont(14, 400, 0, 'Arial')
    GUICtrlCreateLabel('Motor A', 10, 10, 70, 20)
    Global $idEngineA = GUICtrlCreateLabel('', 30, 40, 50, 20)
    GUICtrlCreateLabel('Motor B', 160, 10, 70, 20)
    Global $idEngineB = GUICtrlCreateLabel('', 180, 40, 50, 20)
    GUISetState()
    
    While True
        If GUIGetMsg() = $GUI_EVENT_CLOSE Then Exit
        $iState = 0
        For $i = 0 To UBound($aKeys) - 1
            $iState += (2^$i) * (BitAND(_WinAPI_GetKeyState($aKeys[$i]), 128) == 128)
        Next
        If $iState <> $iOldState Then
            $iOldState = $iState
            $iEngineA = (BitAND($iState, 1) == 1) - (BitAND($iState, 2) == 2)
            $iEngineB = (BitAND($iState, 4) == 4) - (BitAND($iState, 8) == 8)
            GUICtrlSetData($idEngineA, $iEngineA)
            GUICtrlSetData($idEngineB, $iEngineB)
        EndIf
    WEnd
    Alles anzeigen

    Hier wird zusätzlich ausgeschlossen, dass ein Motor nicht gleichzeitig vor- und rückwärts drehen kann. Also ein drücken von "A" und "D" führt zu einer "0" (Stillstand) des Motors.

  • Slider bewegen sich nicht gleichmäßig

    • Oscar
    • 10. Januar 2018 um 18:38
    Zitat von Norbertttt

    (Dieser Thread kann jetzt geschlossen werden)

    Geschlossen (bzw. gelöscht) werden Threads nur, wenn sie gegen unsere Forenregeln verstossen.

    Wenn ein Thema erledigt ist, dann sollte der Ersteller den Thread als erledigt kennzeichnen (1. Beitrag edieren und als erledigt markieren). Das hast Du ja bereits getan, also ist alles gut! :)

  • Slider bewegen sich nicht gleichmäßig

    • Oscar
    • 10. Januar 2018 um 17:29

    Ich habe gerade mal zwei Testscripte erstellt, mit denen man diesen Effekt gut sehen kann.

    Bei dem Script im MessageLoop-Modus verändert sich die Anzahl der Schleifendurchläufe pro Sekunde (RPS) von 100 (Maus wird nicht bewegt) bis auf über 2200 (Maus wird ganz schnell bewegt).

    Das Script im OnEventModus schafft dagegen über 7000 Schleifendurchläufe, was ja auch verständlich ist, weil die Events nicht permanent abgefragt werden müssen.

    Und das ist der Grund, warum ich den MessageLoop-Modus nur in ganz einfachen Scripten verwende, wo nicht viel in der Schleife ausgeführt wird.

    Sobald man etwas "nebenher" laufen lässt, sollte man immer zum OnEventMode greifen.

    Edit: Was ich beim Testen feststellte, ist, dass die Tastendrücke keine Rolle spielen (da bleibt es immer bei nur 100 RPS). Ich war der Meinung, dass das in einer früheren Version von AutoIt mal anders war.

    Dateien

    MessageLoopMode.au3 604 Byte – 179 Downloads OnEventMode.au3 651 Byte – 171 Downloads
  • Slider bewegen sich nicht gleichmäßig

    • Oscar
    • 10. Januar 2018 um 06:12
    Zitat von Norbertttt

    Sonderbarer Nebeneffekt:

    Bewegt man aber gleichzeitig die Mouse, dann bewegen sich die Slider anscheinend gleichmäßig.

    Das sieht sehr nach dem MessageLoop-Modus (GuiGetMsg-Schleife) aus. GuiGetMsg regelt die Schleifen-Durchläufe anhand der Mausbewegungen bzw. Tastaturanschläge.

    Wenn Du den OnEventMode verwendest, dann tritt dieser Effekt nicht auf.

  • Infinite Image Zoom Flight build 2018-01-10

    • Oscar
    • 8. Januar 2018 um 08:55

    Genial! :):rock:

    Die neuen Versionen sind unglaublich schnell (auf meinem Rechner mit 2560x1440 px Auflösung, bei beiden ca. 120 fps).

    Und Deine Arkadia-Version gefällt mir besser als die JS-Version, weil sie nicht diesen Farbfilter darüberlegt. :klatschen:

  • AlignComment richtet Kommentare aus Update 13.08.2016

    • Oscar
    • 6. Januar 2018 um 09:33
    Zitat von Bitnugger

    Ja, die gibt es...

    Ah, mIt #Tidy_Off und #Tidy_On klappt das! Super! Vielen Dank! :klatschen:

  • AlignComment richtet Kommentare aus Update 13.08.2016

    • Oscar
    • 5. Januar 2018 um 17:29

    Das Problem mit Tidy ist nur, dass alle ASM-Code-Einrückungen zunichte gemacht werden. Tidy sieht den ASM-Code komplett als Kommentar an (steht ja zwischen #cs und #ce) und formatiert alles in eine Spalte.

    Bei meinen ASM-Codes vermeide ich daher Tidy und lasse mein kleines Script nur die Kommentare ausrichten.

  • Infinite Image Zoom Flight build 2018-01-10

    • Oscar
    • 5. Januar 2018 um 15:06

    Wow!

    Das sieht echt klasse aus! Sowohl im Browser, als auch in Deinem Script. :thumbup::klatschen:

    Aber ich habe das Sleep in Zeile 98 auskommentiert: Until Not 1; Sleep(10)

    So habe ich ca. 120 fps und das ruckeln zwischendurch tritt nicht mehr auf.

  • AlignComment richtet Kommentare aus Update 13.08.2016

    • Oscar
    • 5. Januar 2018 um 14:52
    Zitat von Andy

    Den auf Tastendruck "schön" ausgerichtet und eingerückt würde AssembleIt bestimmt aufwerten

    Ich habe mir für meine ASM-Codes ein kleines Script geschrieben, mit dem ich die Kommentare an einer bestimmten Position ausrichten kann.

    Man kann das Formatierungsscript in sein Script kopieren, das Script starten und hat den neu kommentierten ASM-Code in der Zwischenablage.

    Voraussetzung ist allerdings dass der ASM-Code zwischen "#Region ASM-Code" und "#EndRegion" steht.

    Das ist jetzt zwar kein Tidy für ASM, aber zumindest zum ausrichten der Kommentare zu gebrauchen. Auskommentierte Zeilen werden nicht eingerückt.

    Hier mal mit ASM-Beispielcode (unformatierte Kommentare):

    AutoIt
    #Region ASM-Code
    #cs StringCompare
        Use32      ; 32Bit Modus!
        mov esi,[esp+4]     ; esi = String1 (Pointer)
        mov edi,[esp+8]             ; edi = String2 (Pointer)
    ;~     _asmdbg_()
        xor ecx,ecx ; ecx = Counter (auf 0 setzen)
        @loop:
            mov al,byte[esi+ecx]        ; al = ein Zeichen von String1 laden
            mov bl,byte[edi+ecx]        ; bl = ein Zeichen von String2 laden
            cmp al,0                      ; al = 0?
            je @end1        ; wenn ja, dann @end1
            cmp bl,0      ; bl = 0?
            je @end1     ; wenn ja, dann @end1
            cmp al,bl       ; al mit bl vergleichen
            jne @end2      ; wenn ungleich, dann @end2
            inc ecx         ; ecx++ (zum naechsten Zeichen)
            jmp @loop ;   Local $COPYDATA = DllStructCreate('Ptr;DWord;Ptr')
        @end1:
            cmp al,bl  ; al mit bl vergleichen
        @end2:
            jb @below    ; wenn al < bl, dann @below
            ja @above       ; wenn al > bl, dann @above
                mov eax,1      ; wenn al = bl, dann eax = 1
                ret
            @above:
                mov eax,2        ; wenn al > bl, dann eax = 2
                ret
            @below:
                mov eax,0     ; wenn al < bl, dann eax = 0
                ret
    #ce
    #EndRegion ASM-Code
    
    #Region ASM-Comment-Format
    Global Const $iCommentPos = 50 ; <- Position, an der die Kommentare ausgerichtet werden
    Global $sScript, $sASM_Code, $aLines, $aCol, $sOut = ''
    $sScript = FileRead(@ScriptFullPath) ; dieses Script einlesen
    If @error Then Exit MsgBox(16, 'ASM-Comment-Format', 'Script konnte nicht gelesen werden!')
    $sASM_Code = StringRegExpReplace($sScript, '(?s).*#Region ASM-Code\v+(.+?)#EndRegion.+', '$1') ; nur den Bereich zwischen "#Region ASM-Code" und "EndRegion" extrahieren
    If $sASM_Code = $sScript Then Exit MsgBox(16, 'ASM-Comment-Format', '"#Region ASM-Code" konnte nicht gefunden werden!')
    $aLines = StringSplit($sASM_Code, @CRLF, 3) ; in einzelne Zeilen aufsplitten
    For $i = 0 To UBound($aLines) - 2
        If StringLeft($aLines[$i], 2) = ';~' Then ContinueLoop ; auskommentierte Zeilen ueberspringen
        $aCol = StringSplit($aLines[$i], ';', 2) ; die Zeilen an der Kommentarposition splitten
        If Not @error Then ; wenn ein Kommentar gefunden wurde, dann...
            $aCol[0] = StringStripWS($aCol[0], 2) ; evtl. vorhandene Leerzeichen hinter dem ASM-Befehl entfernen
            While _StringLen($aCol[0]) < $iCommentPos ; und dann bis zu der gewaehlten Kommentarposition
                $aCol[0] &= ' ' ; Leerzeichen hinzufuegen
            WEnd
            $aLines[$i] = $aCol[0]
            For $j = 1 To UBound($aCol) - 1 ; falls es mehrere Semikolons im Kommentar gab
                $aLines[$i] &= ';' & $aCol[$j] ; die Zeile wieder zusammensetzen
            Next
        EndIf
    Next
    For $i = 0 To UBound($aLines) - 2
        $sOut &= $aLines[$i] & @CRLF ; hier den Ausgabestring zusammensetzen
    Next
    ClipPut($sOut) ; und in die Zwischenablage kopieren
    MsgBox(64, 'ASM-Comment-Format', 'Die Kommentare wurden formatiert.' & @CRLF & 'Das Ergebnis befindet sich in der Zwischenablage.')
    Exit
    
    Func _StringLen(ByRef $sString) ; eigenes StringLen, weil das Standard-Stringlen die TABs nur als 1 Zeichen zaehlt
        StringReplace($sString, @TAB, '') ; wird keiner Variablen zugewiesen, weil nur die Anzahl der TABs interessieren (@extended)
        Local $iTab = @extended
        Return StringLen($sString) + $iTab * 3 ; hier werden die TABs als 4 Zeichen gezaehlt (evtl. anpassen!)
    EndFunc
    #EndRegion ASM-Comment-Format
    Alles anzeigen
  • DllStructCreate mit align

    • Oscar
    • 4. Januar 2018 um 19:12
    Zitat von Andy

    Wenn ich da ein DWORD; BYTE; UINT haben wollte, dann hab ich auch 9 Bytes bekommen. Aktuell ist die Struct 12 Bytes lang, und der UINT hat das Offset 8!

    Ja, weil "align 8" der Standardwert ist:

    Zitat

    To use a different alignment prefix the structure with the align keyword. The default value for n is 8.

    Willst Du Deine 9 Bytes haben, dann musst Du explizit "align 1" angeben:

    AutoIt
    $tStruct = DllStructCreate('DWORD;BYTE;UINT')
    $iSize = DllStructGetSize($tStruct)
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $iSize = ' & $iSize & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
    $tStruct = DllStructCreate('align 1;DWORD;BYTE;UINT')
    $iSize = DllStructGetSize($tStruct)
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $iSize = ' & $iSize & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
  • Fehler in der deutschen Hilfe bitte hier melden (Hilfedatei 3.3.14.2 2017.11.12)

    • Oscar
    • 4. Januar 2018 um 17:48
    Zitat von fakeraol

    PS: Unter ConsoleWrite wird übrigens Scite zwar erwähnt, aber F5 nicht. Hielte ich auch für ne sinnvolle Verbesserung.

    Nein, F5 hat absolut nichts mit ConsoleWrite zu tun, sondern ist ein Tastenkürzel von SciTE zum starten des angezeigten Scripts.

    Und genau dort (in der Hilfe zu SciTE -> ja, es gibt außer der AutoIt-Hilfe auch noch eine Hilfe zu SciTE) steht das gleich unter "Getting Started":

    SciTE_Screenshot.png

  • Fehler in der deutschen Hilfe bitte hier melden (Hilfedatei 3.3.14.2 2017.11.12)

    • Oscar
    • 4. Januar 2018 um 15:55
    Zitat von alpines

    Außerdem wie führst du denn die Beispiele aus der Hilfeaus? Du klickst auf 'Open Script' und es öffnet sich ein neues Tab in SciTE mit dem Beispiel.


    F5 drücken und in die Console schauen ist nicht wirklich schwierig.

    fakeraol: Auf diesen Teil von Alpines bist Du nicht wirklich eingegangen. SciTE ist der AutoIt-Standard, nicht Notepad++!

    Zu jeder "normalen" Installation gehört auch SciTE, weswegen der Link auch in der Downloadbox vorhanden ist. Einem Anfänger jetzt zu Notepad++ zu raten, halte ich für falsch.

    Und, wie Alpines bereits geschrieben hat, F5 zu drücken und nach unten in die Console von SciTE zu schauen sollte jeder hinbekommen.

  • Fehler in der deutschen Hilfe bitte hier melden (Hilfedatei 3.3.14.2 2017.11.12)

    • Oscar
    • 4. Januar 2018 um 13:41
    Zitat von fakeraol

    Eben drum schrieb ich, die Ausgabe dieser Scripte solle in MsgBox'en oder eine Gui (oder mit _ArrayDisplay() ) gemacht werden, damit die tatsächlich direkt aus der Hilfe aufgerufen werden können.

    Das halte ich für total überflüssig!

    Wer (noch) nicht verstanden hat, was ConsoleWrite macht, der versteht den Rest der Befehle auch nicht.

    So viel Eigeninitiative darf man von den angehenden Programmierern doch wohl erwarten.

    Ich werde jedenfalls meine Beispielscripte nicht derart "aufmotzen", wenn es nur darum geht, anzuzeigen, was eine Funktion zurückgibt.

    Nicht falsch verstehen, ich helfe gern, aber das geht doch wirklich zu weit.

  • DllStructCreate mit align

    • Oscar
    • 4. Januar 2018 um 10:26

    Nein, laut: https://msdn.microsoft.com/en-us/library/…7(v=vs.85).aspx kann man mit "_WinAPI_GetSystemInfo" genauere Informationen über den virtuellen Speicher des Systems bekommen.

    Die WinAPI-Funktion gibt bei mir als Array-Element 7 eine Adresse von 65536 (hex: 0x10000) aus und das bedeutet laut Hilfe: "The granularity for the starting address at which virtual memory can be allocated." Somit heißt das wohl, dass der angeforderte Speicher immer auf eine solche Adresse liegt.

    Womit meine bisherigen Versuche bestätigt werden, bei denen die Adresse immer auf 0x....0000 enden.

    Aber das heißt dann auch, dass ich mir, bei virtuellen Speicher, um die 16-Byte-Ausrichtung keine Gedanken machen muss, da der Speicher ja sogar auf 64k ausgerichtet ist.

  • DllStructCreate mit align

    • Oscar
    • 3. Januar 2018 um 10:18

    Ich habe mir gerade nochmal die Hilfe mehrfach durchgelesen.

    Eigentlich steht da gar nichts von der Speicherausrichtung des Pointers auf die Struktur. Bezieht sich das "align" nur auf die Ausrichtung mehrerer Elemente innerhalb der Struktur?

    In dem Fall muss man ja den Speicher erst extern anfordern und dann per Pointer übergeben.

    Wenn ich den Speicher per "_MemVirtualAlloc" anfordere, dann bekomme ich immer Adressen, bei denen die letzten 4 Stellen Nullen sind. Ist das normal?

    Dann bräuchte man gar nicht 16 Byte mehr anfordern und den Pointer umrechnen.

    AutoIt
    #include <Memory.au3>
    $sText = 'Test bla bla bla bla bla bla bla bla'
    ;~ $tStruct1 = _String2Struct($sText)
    $tStruct1 = _String2StructAlign16($sText)
    $pStruct1 = DllStructGetPtr($tStruct1)
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $pStruct1 = ' & $pStruct1 & @CRLF) ;### Debug Console
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : Structsize = ' & DllStructGetSize($tStruct1) & @CRLF) ;### Debug Console
    $eax = BitShift($pStruct1, 4) ; / 16
    $eax = BitShift($eax, -4) ; * 16
    $eax -= $pStruct1 ; - pointer
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $eax = ' & $eax & @CRLF) ;### Debug Console
    
    Func _String2StructAlign16($sString)
        $sString &= Chr(0)
        Local $iSize = StringLen($sString)
        ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $iSize = ' & $iSize & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
        Local $pMem = _MemVirtualAlloc(0, $iSize + 16, $MEM_COMMIT, $PAGE_READWRITE)
        ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $pMem = ' & $pMem & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
        $pMem += (Mod($pMem, 16) > 0 ? 16 - Mod($pMem, 16) : 0)
        ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $pMem = ' & $pMem & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
        Local $tStruct = DllStructCreate('char[' & $iSize & '];', $pMem)
        DllStructSetData($tStruct, 1, $sString)
        Return $tStruct
    EndFunc   ;==>_String2StructAlign16
    
    Func _String2Struct($sString)
        $sString &= Chr(0)
        Local $tStruct = DllStructCreate('align 16;char[' & StringLen($sString) & '];')
        DllStructSetData($tStruct, 1, $sString)
        Return $tStruct
    EndFunc   ;==>_String2Struct
    Alles anzeigen
  • DllStructCreate mit align

    • Oscar
    • 3. Januar 2018 um 09:41

    Ich weiß nicht mehr weiter! :/

    Entweder bin ich zu blöd, das zu verstehen oder es handelt sich um einen Bug. Vielleicht könnt ihr mich aufklären.

    Wenn ich bei DllStructCreate ein "align 16" verwende, dann sollte die Struktur doch an einer Speicheradresse liegen, die durch 16 teilbar ist, oder nicht?

    Manchmal klappt das, manchmal aber auch nicht. Ein kleines Testscript:

    AutoIt
    $sText = 'Test bla bla bla bla bla bla'
    $tStruct1 = _String2Struct($sText)
    $pStruct1 = DllStructGetPtr($tStruct1)
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $pStruct1 = ' & $pStruct1 & @CRLF) ;### Debug Console
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : Structsize = ' & DllStructGetSize($tStruct1) & @CRLF) ;### Debug Console
    $eax = BitShift($pStruct1, 4) ; / 16
    $eax = BitShift($eax, -4)     ; * 16
    $eax -= $pStruct1             ; - pointer
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $eax = ' & $eax & @CRLF) ;### Debug Console
    
    Func _String2Struct($sString)
        $sString &= Chr(0)
        Local $tStruct = DllStructCreate('align 16;char[' & StringLen($sString) & '];')
        DllStructSetData($tStruct, 1, $sString)
        Return $tStruct
    EndFunc
    Alles anzeigen

    Dabei kommt manchmal sowas raus:

    Code
    @@ Debug(4) : $pStruct1 = 0x008E91F8
    @@ Debug(5) : Structsize = 29
    @@ Debug(9) : $eax = -8

    $eax müsste aber "0" sein, wenn es eine 16-Byte-Aligned-Adresse ist.

    Manchmal stimmt es aber auch:

    Code
    @@ Debug(4) : $pStruct1 = 0x00BEAC90
    @@ Debug(5) : Structsize = 29
    @@ Debug(9) : $eax = 0
  • StringCompare in ASM

    • Oscar
    • 2. Januar 2018 um 16:16

    Ach Mist, das vergleichen von Strings geht ja noch viel einfacher. :S

    Wenn man die Schleife selbst macht, dann braucht man vorher gar nicht die Stringlänge ermitteln.

    Und fairerweise muss man StringCompare unter AutoIt auch mit "1" oder "2" als dritten Parameter starten (geht schneller).

    Somit liegt die ASM-Version nur knapp vor der AutoIt-Version (5.9 ms zu 6.7 ms).

    AutoIt
    #AutoIt3Wrapper_UseX64=n                          ; 32Bit-Modus!
    #include "AssembleIt2\assembleit2_64.au3"         ; <- Achtung! Pfad evtl. anpassen!
    #include <Memory.au3>
    
    #Region ASM-Code
    #cs StringCompare
        Use32                                         ; 32Bit Modus!
        mov esi,[esp+4]                               ; esi = String1 (Pointer)
        mov edi,[esp+8]                               ; edi = String2 (Pointer)
        xor ecx,ecx
        @loop:
            mov al,byte[esi+ecx]
            mov bl,byte[edi+ecx]
            cmp al,0
            je @end
            cmp bl,0
            je @end
            cmp al,bl
            jne @end
            inc ecx
            jmp @loop
        @end:
            cmp al,bl
            jb @below
            ja @above
                mov eax,1
                ret
            @above:
                mov eax,2
                ret
            @below:
                mov eax,0
                ret
    #ce
    #EndRegion ASM-Code
    
    #region AssembleIt ; wenn diese 3 Zeilen aktiv sind, dann wird der obige ASM-Code in Binaercode umgewandelt
    ;~ $binarycode = _AssembleIt2('retbinary', 'StringCompare') ; gibt nur den assemblierten code zurück
    ;~ ConsoleWrite('$binarycode = "' & $binarycode & '"' & @CRLF)
    ;~ Exit
    #EndRegion AssembleIt
    
    #Region ASM-Binaercode ; $__g_bASMCode entspricht dem obigen ASM-Code im Binaerformat
    Global Const $__g_bASMCode = '0x8B7424048B7C240831C98A040E8A1C0F3C00740C80FB00740738D8750341EBEA38D8720E7706B801000000C3B802000000C3B800000000C3'
    Global Const $__g_iMemSize = StringLen($__g_bASMCode) / 2 - 1 ; Codelaenge ermitteln
    Global Const $__g_pMem = _MemVirtualAlloc(0, $__g_iMemSize, $MEM_COMMIT, $PAGE_EXECUTE_READWRITE) ; Virtuellen Speicher reservieren
    If $__g_pMem = 0 Then Exit MsgBox(16, 'Error!', "Can't allocate virtual memory!")
    Global $__g_tASMCode = DllStructCreate('byte[' & $__g_iMemSize & ']', $__g_pMem) ; Structur fuer den Binaercode erstellen
    DllStructSetData($__g_tASMCode, 1, $__g_bASMCode) ; den Binaercode in die Structur schreiben
    Global $__g_pASMCode = DllStructGetPtr($__g_tASMCode) ; den Pointer der Structur holen
    ConsoleWrite(StringFormat('ASM-Code-Size:\t%i Bytes\n', $__g_iMemSize))
    #EndRegion ASM-Binaercode
    
    Global Const $aCompare[] = ['<', '=', '>']
    Global $sTest = ''
    ConsoleWrite(StringFormat('Erstelle Teststring. Bitte warten!\n'))
    For $i = 0 To 9999999
        $sTest &= Chr(Random(65, 122, 1))
    Next
    ConsoleWrite(StringFormat('Teststring:\t%i Chars\n\n', StringLen($sTest)))
    ;~ Global $aString[2] = ['Das ist ein Text.12', 'Das ist ein Text.1']
    Global $aString[2] = [$sTest, $sTest & '1']
    $tStruct1 = _String2Struct($aString[0])
    $pStruct1 = DllStructGetPtr($tStruct1)
    $tStruct2 = _String2Struct($aString[1])
    $pStruct2 = DllStructGetPtr($tStruct2)
    
    ConsoleWrite(StringFormat('AutoIt-StringCompare:\n'))
    $iTimer = TimerInit()
    $ret = StringCompare($aString[0], $aString[1], 1)
    ConsoleWrite(StringFormat('Zeit:    \t%.3f ms\n', Round(TimerDiff($iTimer), 3)))
    ConsoleWrite(StringFormat('Ergebnis:\tString1 %s String2\n\n', $aCompare[$ret+1]))
    
    ConsoleWrite(StringFormat('ASM-StringCompare:\n'))
    $iTimer = TimerInit()
    $ret = DllCallAddress('uint:cdecl', $__g_pASMCode, 'ptr', $pStruct1, 'ptr', $pStruct2)
    $ret = $ret[0]
    ;~ $ret = _AssembleIt2('dword', 'StringCompare', 'ptr', $pStruct1, 'ptr', $pStruct2)
    ConsoleWrite(StringFormat('Zeit:    \t%.3f ms\n', Round(TimerDiff($iTimer), 3)))
    ConsoleWrite(StringFormat('Ergebnis:\tString1 %s String2\n', $aCompare[$ret]))
    
    
    If $__g_pMem > 0 Then _MemVirtualFree($__g_pMem, $__g_iMemSize, $MEM_DECOMMIT)
    
    Func _String2Struct($sString)
        $sString &= Chr(0)
        Local $tStruct = DllStructCreate('char[' & StringLen($sString) & ']')
        DllStructSetData($tStruct, 1, $sString)
        Return $tStruct
    EndFunc
    Alles anzeigen

    Dateien

    StringCompare.au3 3,59 kB – 282 Downloads
  • StringCompare in ASM

    • Oscar
    • 2. Januar 2018 um 15:27

    Ich habe im Netz eine "strlenSSE2.asm" von Agner Fog gefunden. Die sieht recht gut aus!

    Damit habe ich jetzt mal ein Testprogramm geschrieben, welches 2 Strings (mit jeweils 10 Mio. Chars) vergleicht.

    Einmal mit dem Befehl StringCompare von AutoIt und einmal mit meiner ASM-Version davon. Und obwohl StringCompare ein interner AutoIt-Befehl ist, gewinnt die ASM-Version (6.7 ms zu 17.4 ms) deutlich. :)

    AutoIt
    #AutoIt3Wrapper_UseX64=n                          ; 32Bit-Modus!
    #include "AssembleIt2\assembleit2_64.au3"         ; <- Achtung! Pfad evtl. anpassen!
    #include <Memory.au3>
    
    #Region ASM-Code
    #cs StringCompare
        Use32                                         ; 32Bit Modus!
        mov esi,[esp+4]                               ; esi = String1 (Pointer)
        mov edi,[esp+8]                               ; edi = String2 (Pointer)
        mov eax,esi
        call strlen
        mov ebx,eax
    ;~     _asmdbg_()
        mov eax,edi
        call strlen
        mov ecx,eax
        cmp ecx,ebx
        ja @f
            mov ecx,ebx
        @@:
        cld                                           ; Direction-Flag loeschen
        repe cmpsb                                    ; die Strings vergleichen (repe = wiederhole so viele Zeichen, wie in ecx vorgegeben)
        jb @below                                     ; wenn kleiner, dann springe zu @below
        ja @above                                     ; wenn groesser, dann springe zu @above
            mov eax,1                                 ; wenn String1 = String2, dann eax = 1
            ret                                       ; zurueck zu AutoIt
        @above:
            mov eax,2                                 ; wenn String1 > String2, dann eax = 2
            ret                                       ; zurueck zu AutoIt
        @below:
            mov eax,0                                 ; wenn String1 < String2, dann eax = 0
            ret                                       ; zurueck zu AutoIt
    
        ; strlenSSE2.asm
        ; Author:           Agner Fog
        ; Date created:     2008-07-06
        ; Last modified:    2008-07-06
        strlen:
            mov ecx,eax                              ; copy pointer
            pxor xmm0,xmm0                           ; set to zero
            and ecx,15                               ; lower 4 bits indicate misalignment
            and eax,-16                              ; align pointer by 16
            movdqa xmm1,[eax]                        ; read from nearest preceding boundary
            pcmpeqb xmm1,xmm0                        ; compare 16 bytes with zero
            pmovmskb edx,xmm1                        ; get one bit for each byte result
            shr edx,cl                               ; shift out false bits
            shl edx,cl                               ; shift back again
            bsf edx,edx                              ; find first 1-bit
            jnz @L2                                  ; found
            @L1:                                     ; Main loop, search 16 bytes at a time
                add eax,16                           ; increment pointer by 16
                movdqa xmm1,[eax]                    ; read 16 bytes aligned
                pcmpeqb xmm1,xmm0                    ; compare 16 bytes with zero
                pmovmskb edx,xmm1                    ; get one bit for each byte result
                bsf edx,edx                          ; find first 1-bit
                jz @L1                               ; loop if not found
            @L2:                                     ; Zero-byte found. Compute string length
                sub eax,[esp+4]                      ; subtract start address
                add eax,edx                          ; add byte index
                ret
    #ce
    #EndRegion ASM-Code
    
    #region AssembleIt ; wenn diese 3 Zeilen aktiv sind, dann wird der obige ASM-Code in Binaercode umgewandelt
    ;~ $binarycode = _AssembleIt2('retbinary', 'StringCompare') ; gibt nur den assemblierten code zurück
    ;~ ConsoleWrite('$binarycode = "' & $binarycode & '"' & @CRLF)
    ;~ Exit
    #EndRegion AssembleIt
    
    #Region ASM-Binaercode ; $__g_bASMCode entspricht dem obigen ASM-Code im Binaerformat
    Global Const $__g_bASMCode = '0x8B7424048B7C240889F0E82A00000089C389F8E82100000089C139D9770289D9FCF3A6720E7706B801000000C3B802000000C3B800000000C389C1660FEFC083E10F83E0F0660F6F08660F74C8660FD7D1D3EAD3E20FBCD2751483C010660F6F08660F74C8660FD7D10FBCD274EC2B44240401D0C3'
    Global Const $__g_iMemSize = StringLen($__g_bASMCode) / 2 - 1 ; Codelaenge ermitteln
    Global Const $__g_pMem = _MemVirtualAlloc(0, $__g_iMemSize, $MEM_COMMIT, $PAGE_EXECUTE_READWRITE) ; Virtuellen Speicher reservieren
    If $__g_pMem = 0 Then Exit MsgBox(16, 'Error!', "Can't allocate virtual memory!")
    Global $__g_tASMCode = DllStructCreate('byte[' & $__g_iMemSize & ']', $__g_pMem) ; Structur fuer den Binaercode erstellen
    DllStructSetData($__g_tASMCode, 1, $__g_bASMCode) ; den Binaercode in die Structur schreiben
    Global $__g_pASMCode = DllStructGetPtr($__g_tASMCode) ; den Pointer der Structur holen
    ConsoleWrite(StringFormat('ASM-Code-Size:\t%i Bytes\n', $__g_iMemSize))
    #EndRegion ASM-Binaercode
    
    Global Const $aCompare[] = ['<', '=', '>']
    Global $sTest = ''
    For $i = 0 To 9999999
        $sTest &= Chr(Random(65, 122, 1))
    Next
    ConsoleWrite(StringFormat('Teststring:\t%i Chars\n\n', StringLen($sTest)))
    ;~ Global $aString[2] = ['Das ist ein Text.12', 'Das ist ein Text.1']
    Global $aString[2] = [$sTest, $sTest & '1']
    $tStruct1 = _String2Struct($aString[0])
    $pStruct1 = DllStructGetPtr($tStruct1)
    $tStruct2 = _String2Struct($aString[1])
    $pStruct2 = DllStructGetPtr($tStruct2)
    
    ConsoleWrite(StringFormat('AutoIt-StringCompare:\n'))
    $iTimer = TimerInit()
    $ret = StringCompare($aString[0], $aString[1])
    ConsoleWrite(StringFormat('Zeit:    \t%.3f ms\n', Round(TimerDiff($iTimer), 3)))
    ConsoleWrite(StringFormat('Ergebnis:\tString1 %s String2\n\n', $aCompare[$ret+1]))
    
    ConsoleWrite(StringFormat('ASM-StringCompare:\n'))
    $iTimer = TimerInit()
    $ret = DllCallAddress('uint:cdecl', $__g_pASMCode, 'ptr', $pStruct1, 'ptr', $pStruct2)
    $ret = $ret[0]
    ;~ $ret = _AssembleIt2('dword', 'StringCompare', 'ptr', $pStruct1, 'ptr', $pStruct2)
    ConsoleWrite(StringFormat('Zeit:    \t%.3f ms\n', Round(TimerDiff($iTimer), 3)))
    ConsoleWrite(StringFormat('Ergebnis:\tString1 %s String2\n', $aCompare[$ret]))
    
    
    If $__g_pMem > 0 Then _MemVirtualFree($__g_pMem, $__g_iMemSize, $MEM_DECOMMIT)
    
    Func _String2Struct($sString)
        $sString &= Chr(0)
        Local $tStruct = DllStructCreate('char[' & StringLen($sString) & ']')
        DllStructSetData($tStruct, 1, $sString)
        Return $tStruct
    EndFunc
    Alles anzeigen

    Dateien

    StringCompare.au3 5,95 kB – 272 Downloads

Spenden

Jeder Euro hilft uns, Euch zu helfen.

Download

AutoIt Tutorial
AutoIt Buch
Onlinehilfe
AutoIt Entwickler
  1. Datenschutzerklärung
  2. Impressum
  3. Shoutbox-Archiv
Community-Software: WoltLab Suite™