﻿#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