Sign in to follow this  
Followers 0
trancexx

Slow AutoIt loops

31 posts in this topic

#1 ·  Posted (edited)

Another theoretical/practical contemplation. ;)

I've been working and playing with AutoIt for the past little over a year. We all know how great AutoIt is.

What I miss the most is the speed. I mean there is nothing particulary bed with anything (at least wouldn't be noticed) but loops. I'm aware this is caused by the interpretation process, but it sucks. And if you try to ask for an alternative you get banned :D (I'm kidding, but still don't ask :D , it's not allowed on grounds of motives).

Alternative to looping this high could be this relatively new technique of generating assembly code on the fly.

Idea is to push loops to assembly level and just wait for the results. Writting code that loops there is probably the fastest thing you will ever write. You are communicating with a processor directly.

Let's take one example. Will proccess code written for the purposes of one thread in General Help and Support forum. This is the link to the code and the code is this:

#include <GUIConstantsEx.au3>

Opt("GUIOnEventMode", 1)

Global Const $iWidth = 110
Global Const $iHeight = 70

GUICreate("", $iWidth, $iHeight)
GUISetOnEvent(-3, "_Quit")
GUISetBkColor(0x000000)

Global $Pic = GUICtrlCreatePic("", 0, 0, $iWidth, $iHeight)

Global Const $STM_SETIMAGE = 370

Global $iSize = $iWidth * $iHeight
Global $tBits = DllStructCreate("int[" & $iSize & "]")
Global $pBits = DllStructGetPtr($tBits)

Global $hBitmap, $aCall

GUISetState()


While 1

    For $i = 1 To $iSize
        DllStructSetData($tBits, 1, Random(0, 0xFFFFFF, 1), $i)
    Next

    DllCall("gdi32.dll", "int", "DeleteObject", "ptr", $hBitmap)

    $aCall = DllCall("gdi32.dll", "hwnd", "CreateBitmap", _
            "int", $iWidth, _
            "int", $iHeight, _
            "dword", 1, _
            "dword", 32, _
            "ptr", $pBits)

    $hBitmap = $aCall[0]

    DllCall("gdi32.dll", "int", "DeleteObject", "ptr", GUICtrlSendMsg($Pic, $STM_SETIMAGE, 0, $hBitmap))

    Sleep(0)

WEnd


Func _Quit()
    Exit
EndFunc;==>_Quit

What it does? It generates a bitmap with randomly colored pixels and displays that bitmap in GUI.

Every pixel is, as I said, colored differently. Part of the code that deals with that is:

For $i = 1 To $iSize
        DllStructSetData($tBits, 1, Random(0, 0xFFFFFF, 1), $i)
    Next

Value of $iSize in that case is 7700. That means that AutoIt will do 7700 times:

DllStructSetData($tBits, 1, Random(0, 0xFFFFFF, 1), $i)

If you run that code you will see that it takes almost 100% CPU (one processor) and that it's almose incredibly slow. I even had to add Sleep(0) to avoid total disaster.

It's the fastest you'll get using conventional AutoIt scripting.

So, how to speed it up?

First I'm going to rewrite it to use win api calls inside While... WEnd. This s needed and is essential for transformation to assembly.

Modified script would be this:

#include <GUIConstantsEx.au3>

Opt("GUIOnEventMode", 1)

Global Const $STM_SETIMAGE = 370

Global Const $iWidth = 110
Global Const $iHeight = 70

GUICreate("", $iWidth, $iHeight)
GUISetOnEvent(-3, "_Quit")
GUISetBkColor(0x000000)

Global $hPic = GUICtrlCreatePic("", 0, 0, $iWidth, $iHeight)

Global $iSize = $iWidth * $iHeight
Global $tBits = DllStructCreate("int[" & $iSize & "]")
Global $pBits = DllStructGetPtr($tBits)


Global $hBitmap, $aCall, $iHMsg
Global $hPicHandle = GUICtrlGetHandle($hPic)

Global $tRandom = DllStructCreate("dword")
Global $pRandom = DllStructGetPtr($tRandom)

GUISetState()

While 1

    For $i = 0 To $iSize - 1

        DllCall("ntdll.dll", "dword", "RtlRandomEx", "ptr", $pRandom)
        DllCall("kernel32.dll", "none", "RtlMoveMemory", _
                "ptr", $pBits + $i * 4, _
                "ptr", $pRandom, _
                "dword", 3)

    Next

;DllCall("gdi32.dll", "int", "DeleteObject", "ptr", $hBitmap)

    $aCall = DllCall("gdi32.dll", "hwnd", "CreateBitmap", _
            "int", $iWidth, _
            "int", $iHeight, _
            "dword", 1, _
            "dword", 32, _
            "ptr", $pBits)

    $hBitmap = $aCall[0]

    $aCall = DllCall("user32.dll", "ptr", "SendMessageW", _
            "hwnd", $hPicHandle, _
            "dword", $STM_SETIMAGE, _
            "dword", 0, _
            "ptr", $hBitmap)

    $iHMsg = $aCall[0]

    DllCall("gdi32.dll", "int", "DeleteObject", "ptr", $iHMsg)

    Sleep(0)

WEnd


Func _Quit()
    Exit
EndFunc ;==>_Quit

If you run it you will se that it's as CPU demanding as before only a bit slower.

That is not a concern righ now. It is what it is. Main thing is that inside While... WEnd is nothing but DllCall().

Now for why I'm writing this...

If you have some experience with assembly (maybe thru mine or monoceres's posts/threads) then you know that out of that code you can write something like this and doing that you will be a step closer to a moon:

#include <GUIConstantsEx.au3>
#include <Memory.au3>

Opt("GUIOnEventMode", 1)

Global Const $STM_SETIMAGE = 370

Global Const $iWidth = 110
Global Const $iHeight = 70

GUICreate("", $iWidth, $iHeight)
GUISetOnEvent(-3, "_Quit")
GUISetBkColor(0)

Global $hPic = GUICtrlCreatePic("", 0, 0, $iWidth, $iHeight)

Global $iSize = $iWidth * $iHeight
Global $tBits = DllStructCreate("int[" & $iSize & "]")
Global $pBits = DllStructGetPtr($tBits)


Global $hBitmap, $aCall, $iHMsg
Global $hPicHandle = GUICtrlGetHandle($hPic)

Global $tRandom = DllStructCreate("dword")
Global $pRandom = DllStructGetPtr($tRandom)

GUISetState()


Global $aRtlRandomEx = DllCall("kernel32.dll", "ptr", "GetProcAddress", "ptr", _WinAPI_GetModuleHandle("ntdll.dll"), "str", "RtlRandomEx")
Global $pRtlRandomEx = $aRtlRandomEx[0]

Global $aRtlMoveMemory = DllCall("kernel32.dll", "ptr", "GetProcAddress", "ptr", _WinAPI_GetModuleHandle("kernel32.dll"), "str", "RtlMoveMemory")
Global $pRtlMoveMemory = $aRtlMoveMemory[0]

Global $pRemoteCode = _MemVirtualAlloc(0, 512, $MEM_COMMIT, $PAGE_EXECUTE_READWRITE)

Local $tCodeBuffer = DllStructCreate("byte[512]", $pRemoteCode)


While 1

    #Region Assembly

    DllStructSetData($tCodeBuffer, 1, _
        "0x" & _
        "33DB" & _                                          ; xor ebx, ebx
        "68" & SwapEndian($pRandom) & _                       ; push $pRandom
        "B8" & SwapEndian($pRtlRandomEx) & _                     ; mov eax, RtlRandomEx
        "FFD0" & _                                          ; call eax
        "8BCB" & _                                          ; mov ecx, ebx
        "69C9" & SwapEndian(4) & _                          ; imul ecx, 4
        "81C1" & SwapEndian($pBits) & _                       ; add ecx, $pBits
        "68" & SwapEndian(3) & _                                 ; push 3 bytes
        "68" & SwapEndian($pRandom) & _                       ; push $pRandom
        "51" & _                                                 ; push ecx
        "B8" & SwapEndian($pRtlMoveMemory) & _              ; mov eax, RtlMoveMemory
        "FFD0" & _                                          ; call eax
        "43" & _                                                 ; inc ebx
        "81FB" & SwapEndian($iSize) & _                       ; cmp ebx, $iSize; <- compare ebx with $iSize
        "75" & Hex(256 - 53, 2) & _                           ; jne -53 bytes; <- this is saying go back and do it again if not equal
        "C3" _                                              ; ret
        )

        DllCall("user32.dll", "int", "CallWindowProcW", _
            "ptr", $pRemoteCode, _
            "int", 0, _
            "int", 0, _
            "int", 0, _
            "int", 0)

    #EndRegion Assembly

;DllCall("gdi32.dll", "int", "DeleteObject", "ptr", $hBitmap)

    $aCall = DllCall("gdi32.dll", "hwnd", "CreateBitmap", _
            "int", $iWidth, _
            "int", $iHeight, _
            "dword", 1, _
            "dword", 32, _
            "ptr", $pBits)

    $hBitmap = $aCall[0]

    $iHMsg = GUICtrlSendMsg($hPic, $STM_SETIMAGE, 0, $hBitmap)

    DllCall("gdi32.dll", "int", "DeleteObject", "ptr", $iHMsg)

    Sleep(10)

WEnd



Func SwapEndian($iValue)
    Return Hex(Binary($iValue))
EndFunc ;==>SwapEndian


Func _Quit()
    Exit
EndFunc ;==>_Quit

If you observe it you will see that there is no AutoIt loop (don't tease me with While... WEnd :P ). And if you run it the results will be visually the same as before. But check CPU usage! It should be 0%. And this time I'm slowing it down with Sleep(10). You can make it bigger now (110x70 is ridiculously small).

I'm closing this rather fast because the post is getting too big to follow.

Before the end here's another script. This one transforms even larger part of the code from AutoIt to assembly (just for fun):

#include <GUIConstantsEx.au3>
#include <Memory.au3>

Opt("GUIOnEventMode", 1)

Global Const $STM_SETIMAGE = 370

Global Const $iWidth = 810
Global Const $iHeight = 470

GUICreate("", $iWidth, $iHeight)
GUISetOnEvent(-3, "_Quit")
GUISetBkColor(0)

Global $hPic = GUICtrlCreatePic("", 0, 0, $iWidth, $iHeight)

Global $iSize = $iWidth * $iHeight
Global $tBits = DllStructCreate("int[" & $iSize & "]")
Global $pBits = DllStructGetPtr($tBits)


Global $hBitmap, $aCall, $iHMsg
Global $hPicHandle = GUICtrlGetHandle($hPic)

Global $tRandom = DllStructCreate("dword")
Global $pRandom = DllStructGetPtr($tRandom)

GUISetState()


Global $aRtlRandomEx = DllCall("kernel32.dll", "ptr", "GetProcAddress", "ptr", _WinAPI_GetModuleHandle("ntdll.dll"), "str", "RtlRandomEx")
Global $pRtlRandomEx = $aRtlRandomEx[0]

Global $aRtlMoveMemory = DllCall("kernel32.dll", "ptr", "GetProcAddress", "ptr", _WinAPI_GetModuleHandle("kernel32.dll"), "str", "RtlMoveMemory")
Global $pRtlMoveMemory = $aRtlMoveMemory[0]

Global $aSendMessageW = DllCall("kernel32.dll", "ptr", "GetProcAddress", "ptr", _WinAPI_GetModuleHandle("user32.dll"), "str", "SendMessageW")
Global $pSendMessageW = $aSendMessageW[0]

Global $aDeleteObject = DllCall("kernel32.dll", "ptr", "GetProcAddress", "ptr", _WinAPI_GetModuleHandle("gdi32.dll"), "str", "DeleteObject")
Global $pDeleteObject = $aDeleteObject[0]

Global $aCreateBitmap = DllCall("kernel32.dll", "ptr", "GetProcAddress", "ptr", _WinAPI_GetModuleHandle("gdi32.dll"), "str", "CreateBitmap")
Global $pCreateBitmap = $aCreateBitmap[0]

Global $pRemoteCode = _MemVirtualAlloc(0, 512, $MEM_COMMIT, $PAGE_EXECUTE_READWRITE)

Local $tCodeBuffer = DllStructCreate("byte[512]", $pRemoteCode)


While 1

    #region Assembly

    DllStructSetData($tCodeBuffer, 1, _
            "0x" & _
            "33DB" & _                                          ; xor ebx, ebx
            "68" & SwapEndian($pRandom) & _                       ; push $pRandom
            "B8" & SwapEndian($pRtlRandomEx) & _                     ; mov eax, RtlRandomEx
            "FFD0" & _                                          ; call eax
            "8BCB" & _                                          ; mov ecx, ebx
            "69C9" & SwapEndian(4) & _                          ; imul ecx, 4
            "81C1" & SwapEndian($pBits) & _                       ; add ecx, $pBits
            "68" & SwapEndian(3) & _                                 ; push 3 bytes
            "68" & SwapEndian($pRandom) & _                       ; push $pRandom
            "51" & _                                                 ; push ecx
            "B8" & SwapEndian($pRtlMoveMemory) & _              ; mov eax, RtlMoveMemory
            "FFD0" & _                                          ; call eax
            "43" & _                                                 ; inc ebx
            "81FB" & SwapEndian($iSize) & _                       ; cmp ebx, $iSize; <- compare ebx with $iSize
            "75" & Hex(256 - 53, 2) & _                           ; jne -53 bytes; <- this is saying go back and do it again if not equal
            "68" & SwapEndian($pBits) & _                           ; push $pBits
            "68" & SwapEndian(32) & _                               ; push BitsPerPel
            "68" & SwapEndian(1) & _                                 ; push Planes
            "68" & SwapEndian($iHeight) & _                       ; push $iHeight
            "68" & SwapEndian($iWidth) & _                      ; push $iWidth
            "B8" & SwapEndian($pCreateBitmap) & _                   ; mov eax, CreateBitmap
            "FFD0" & _                                          ; call eax
            "50" & _                                                 ; push eax
            "68" & SwapEndian(0) & _                                 ; push IMAGE_BITMAP
            "68" & SwapEndian($STM_SETIMAGE) & _                     ; push STM_SETIMAGE
            "68" & SwapEndian($hPicHandle) & _                  ; push $hPicHandle
            "B8" & SwapEndian($pSendMessageW) & _                   ; mov eax, SendMessageW
            "FFD0" & _                                          ; call eax
            "50" & _                                                 ; push eax
            "B8" & SwapEndian($pDeleteObject) & _                   ; mov eax, DeleteObject
            "FFD0" & _                                          ; call eax
            "C3" _                                              ; ret
            )

    DllCall("user32.dll", "int", "CallWindowProcW", _
            "ptr", $pRemoteCode, _
            "int", 0, _
            "int", 0, _
            "int", 0, _
            "int", 0)

    #endregion Assembly

    Sleep(10)

WEnd



Func SwapEndian($iValue)
    Return Hex(Binary($iValue))
EndFunc ;==>SwapEndian


Func _Quit()
    Exit
EndFunc ;==>_Quit

It's 810x470 and not even close to heating up your processor as the original script.

Btw, I'm no expert in functions that deals with generating random numbers, so maybe seed needs changing with new run (on Vista not).

Assembly code is executed using CallWindowProc function in these examples.

edit: corrected most of the misspellings

Edited by trancexx

♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites



are you sure it's random? cause i definately see some patterns here:) other than that nice job

Share this post


Link to post
Share on other sites

@trancexx

you didn't mention that it's about 60 times faster!

BTW Sleep(0) is the same as Sleep(10)

Can you make a little udf so that we can have

_TXLoop("Function", $from, $to, $step)

or something near that? Me want :D


Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

Nice work as usual trancexx, this whole machine code stuff is a newly opened gold mine, maybe we should start making an assembler soon? :D

BTW Sleep(0) is the same as Sleep(10)

Actually no, Sleep(0) is a very special case, more info here in the remarks section.

Can you make a little udf so that we can have

_TXLoop("Function", $from, $to, $step)

The problem is that for this to get the positive effect the code inside the function needs to be converted to assembly code and then to raw machine code. So what this actually means is to create a true compiler for autoit, something that is extremely hard, time consuming and is in fact the same as creating a new language.

Of course your request could be done with a DllCallbackRegister() method, but that would mean that the optimized part of the loop would only be the start (example: While $a=1).

Edited by monoceres

Broken link? PM me and I'll send you the file!

Share this post


Link to post
Share on other sites

That's absolutely crazy :D (idea born from here?)

To understand it I need to learn assembler 'cause it gives me new ideas about graphical stuff...

Respectfull work!!!

Btw, how can I set the pixel size? Currently 1x1.

Keep your good work up trancexx!

UEZ


Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

I have seen calling assembly code from AutoIt already but this is nicely commented valuable example for the masses :-)

My skills in ASM are quite poor so I doubt I will use it but it's good to see the possibilities :-)

Five stars from me  :D

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

Wow... :D

Just awesome, that speed... you just gave me a project this summer, to learn Assembly.

and just curious, how much speed do you actually get in % of processor Ghz (with something simple, such as adding counting 1,2,3...)

Btw very well written post, i've seen this stuff before but i haven't even tried to get my mind into it, but these examples and the comments really help.

Edited by colafrysen

[font="Impact"]Use the helpfile, It´s one of the best exlusive features of Autoit.[/font]http://support.microsoft.com/kb/q555375ALIBI Run - a replacement for the windows run promptPC Controller - an application for controlling other PCs[size="1"]Science flies us to the moon. Religion flies us into buildings.[/size][size="1"]http://bit.ly/cAMPZV[/size]

Share this post


Link to post
Share on other sites

Nice work as usual trancexx, this whole machine code stuff is a newly opened gold mine, maybe we should start making an assembler soon? :D

Actually no, Sleep(0) is a very special case, more info here in the remarks section.

Oh, thanks. I thought the minimum sleep was 10 and in fact sleep(1) is the same as sleep(10), but I ddn't realize sleep(0) was different.

The problem is that for this to get the positive effect we want the code inside the function needs to be converted to assembly code and then to raw machine code. So what this actually means is to create a true compiler for autoit, something that is extremely hard, time consuming and is in fact the same as creating a new language.

Of course your request could be done with a DllCallbackRegister() method, but that would mean that the optimized part of the loop would only be the start (example: While $a=1).

Yes, I see. I got a little over excited there. :D

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites

#9 ·  Posted (edited)

and just curious, how much speed do you actually get in % of processor Ghz (with something simple, such as adding counting 1,2,3...)

The ADD instruction is one of the most fundamental instruction in the x86 tool set (and in all processors) and for Intel Pentium processors it only require 1 or 2 clock cycles to complete (lets say 1). This mean that a Intel Pentium 4 processor @ 2.40 GHz can in theory do 2.4 billion add operations per second. Quite impressive I have to say.

However in practice you need to have the processor keep going and you will probably do this with the JMP instruction, this is a much more greedy instruction (7 cycles).

So in practice it will reach a speed at (2'400'000'000 / 8)= 300 million adds per second.

Edit: Instruction, not function

Edited by monoceres

Broken link? PM me and I'll send you the file!

Share this post


Link to post
Share on other sites

I have to say that 300 million is extreme, 0.3 million is much. and i thought my 1.7 Ghz computer was slow,

Well I am convinced. I'll learn assembly, you guys got any tips or resources? how did you learn? give me a PM (I do not want to hijack the thread)


[font="Impact"]Use the helpfile, It´s one of the best exlusive features of Autoit.[/font]http://support.microsoft.com/kb/q555375ALIBI Run - a replacement for the windows run promptPC Controller - an application for controlling other PCs[size="1"]Science flies us to the moon. Religion flies us into buildings.[/size][size="1"]http://bit.ly/cAMPZV[/size]

Share this post


Link to post
Share on other sites

Nice work

Thanks

Share this post


Link to post
Share on other sites

#12 ·  Posted (edited)

@trancexx

It would be awesome to have ASM optimized version of some (just few) core functions from standard array include file

like _ArraySearch(), _ArrayMaxIndex(), _ArrayMinIndex(), _ArrayToString(), ...

all thouse functions containing very simple FOR NEXT loops which may be very slow on large arrays.

I think arrays are often used by scripters (including me) and in some cases are source of slow scripts.

So end scripters doesn't need to have knowledge of ASM, they just recompile their script with ASM optimized array include file.

EDIT:

Maybe something like AddressOf($var) should be added to AutoIt to have full power of this ASM optimizations

See my old rejected request for AddressOf($var) on Trac:

http://www.autoitscript.com/trac/autoit/ticket/279

EDIT2:

Another functions candidate for ASM optimization are some from File include:

_FileCountLines() - maybe using filemapping?

_FileListToArray()

_FileReadToArray()

_FileWriteFromArray()

_ReplaceStringInFile()

Edited by Zedna

Share this post


Link to post
Share on other sites

@trancexx

It would be awesome to have ASM optimized version of some (just few) core functions from standard array include file

like _ArraySearch(), _ArrayMaxIndex(), _ArrayMinIndex(), _ArrayToString(), ...

all thouse functions containing very simple FOR NEXT loops which may be very slow on large arrays.

I think arrays are often used by scripters (including me) and in some cases are source of slow scripts.

So end scripters doesn't need to have knowledge of ASM, they just recompile their script with ASM optimized array include file.

EDIT:

Maybe something like AddressOf($var) should be added to AutoIt to have full power of this ASM optimizations

See my old rejected request for AddressOf($var) on Trac:

http://www.autoitscript.com/trac/autoit/ticket/279

EDIT2:

Another functions candidate for ASM optimization are some from File include:

_FileCountLines() - maybe using filemapping?

_FileListToArray()

_FileReadToArray()

_FileWriteFromArray()

_ReplaceStringInFile()

If you answer what some array is you will see that it's almost impossible to do it. Even if sombody does it, it would never be included in standard UDFs, not to mention that it would also probably resulted in a permanent ban from the forums for the coder. Am I exaggerating?

File functions are differnt and that could be done (not array parts). But for example, I think _ReplaceStringInFile() would be just fine without assembly part.

Acidut sees patterns. I see them too on XP. I wrote that script on Vista (to check for DEP issues) and there are no patterns there. Likely used algorithm in RtlRandomEx is changed with Vista. Someone with experience with that function or randomizing generally could give us the answer. There is also a possibility that I'm not using that function right. But it's not that important.

UEZ asks about the site of pixel... again. Color four in a row and do the same thing in three following lines with the same color to get 4x4.

Thanks for the comments.

... and nobody noticed Hex(256 - 53, 2)? :D

@monoceres, I hope to see some gold from you now.


♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

I've seen the other threads about using asm directly and it leaves a bitter taste in my mouth. This looks bad. If you want to use asm, you can assemble+link an asm dll and call its functions.

Share this post


Link to post
Share on other sites

Truly mindblowing stuff. However, if I can reduce everything to DllCall then I'm probably thinking that I'd just write it in C/C++ and use DllCall (or COM) to call the functionality anyway. I'm a bit too long in the tooth to be learning Assembler :-)

WBD

Share this post


Link to post
Share on other sites

Truly mindblowing stuff. However, if I can reduce everything to DllCall then I'm probably thinking that I'd just write it in C/C++ and use DllCall (or COM) to call the functionality anyway. I'm a bit too long in the tooth to be learning Assembler :-)

WBD

No.

It's pretty because you can use AutoIt for whole project and assembler only for core part (sensitive to speed) - optimize just few lines but speed-up application dramatically. Did you get the point now? :-)

Share this post


Link to post
Share on other sites

#17 ·  Posted (edited)

...

UEZ asks about the site of pixel... again. Color four in a row and do the same thing in three following lines with the same color to get 4x4.

...

Sorry that I bored you again with the same question!

Anyway, can you explain me/us more about the assembler code?

...
      DllStructSetData($tCodeBuffer, 1, _
          "0x" & _
          "33DB" & _                                          ; xor ebx, ebx
          "68" & SwapEndian($pRandom) & _                       ; push $pRandom
          "B8" & SwapEndian($pRtlRandomEx) & _                 ; mov eax, RtlRandomEx
          "FFD0" & _                                          ; call eax
          "8BCB" & _                                          ; mov ecx, ebx
          "69C9" & SwapEndian(4) & _                          ; imul ecx, 4
          "81C1" & SwapEndian($pBits) & _                       ; add ecx, $pBits
          "68" & SwapEndian(3) & _                             ; push 3 bytes
          "68" & SwapEndian($pRandom) & _                       ; push $pRandom
          "51" & _                                             ; push ecx
          "B8" & SwapEndian($pRtlMoveMemory) & _              ; mov eax, RtlMoveMemory
          "FFD0" & _                                          ; call eax
          "43" & _                                             ; inc ebx
          "81FB" & SwapEndian($iSize) & _                       ; cmp ebx, $iSize; <- compare ebx with $iSize
          "75"  & Hex(256 - 53, 2) & _                          ; jne -53  bytes; <- this is saying go back and do it again if not equal
          "C3" _                                              ; ret
          )
  ...

I mean not the command itself (this is more or less clear) but the why you used this in that way (meaning)!

E.g, why you made a xor in the 1st line, call eax (what is called?), etc.?

I'm trying to understand that code :D but without success :D

THANKS,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

#18 ·  Posted (edited)

@ UEZ

Each line is commented, they are assembly commands, some are concatenated with addresses of memory pointers, which are in turn reversed (because they are stored in memory in reverse order)

The guys just used a assembler to see what bytes make up what commands. For example you can use the Olly debugger and just start assembling commands and look at the bytes.

The XOR command is the known bitwise operation, in the first line they XOR the EBX register with itself to make it zero (less bytes than mov ebx,0)

"call eax" calls the address of eax, which is RtlMoveMemory, they could have used call dword ptr []

After the call is done, it returns at the next command with aligned stack.

Anyway, if you want to wield the awesome power of assembly, start here :

http://www.masm32.com/

(and ask serious question at the forum there)

And check the tutorial series here :

http://win32assembly.online.fr/

Edited by Inverted

Share this post


Link to post
Share on other sites

@ UEZ

Each line is commented, they are assembly commands, some are concatenated with addresses of memory pointers, which are in turn reversed (because they are stored in memory in reverse order)

The guys just used a assembler to see what bytes make up what commands. For example you can use the Olly debugger and just start assembling commands and look at the bytes.

The XOR command is the known bitwise operation, in the first line they XOR the EBX register with itself to make it zero (less bytes than mov ebx,0)

"call eax" calls the address of eax, which is RtlMoveMemory, they could have used call dword ptr []

After the call is done, it returns at the next command with aligned stack.

Anyway, if you want to wield the awesome power of assembly, start here :

http://www.masm32.com/

(and ask serious question at the forum there)

And check the tutorial series here :

http://win32assembly.online.fr/

Sorry, but the comments in each line are not really understandable for me and that's why I asked although the commands are clear to me.

Currently I don't want to learn assembler but I want to understand here the code roughly. Thanks for your explanations.

UEZ


Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

#20 ·  Posted (edited)

Sorry that I bored you again with the same question!

Anyway, can you explain me/us more about the assembler code?

...
      DllStructSetData($tCodeBuffer, 1, _
          "0x" & _
          "33DB" & _                                ; xor ebx, ebx
          "68" & SwapEndian($pRandom) & _       ; push $pRandom
          "B8" & SwapEndian($pRtlRandomEx) & _          ; mov eax, RtlRandomEx
          "FFD0" & _                                ; call eax
          "8BCB" & _                                ; mov ecx, ebx
          "69C9" & SwapEndian(4) & _                ; imul ecx, 4
          "81C1" & SwapEndian($pBits) & _       ; add ecx, $pBits
          "68" & SwapEndian(3) & _                      ; push 3 bytes
          "68" & SwapEndian($pRandom) & _       ; push $pRandom
          "51" & _                                      ; push ecx
          "B8" & SwapEndian($pRtlMoveMemory) & _    ; mov eax, RtlMoveMemory
          "FFD0" & _                                ; call eax
          "43" & _                                      ; inc ebx
          "81FB" & SwapEndian($iSize) & _       ; cmp ebx, $iSize; <- compare ebx with $iSize
          "75"  & Hex(256 - 53, 2) & _          ; jne -53  bytes; <- this is saying go back and do it again if not equal
          "C3" _                                    ; ret
          )
  ...

I mean not the command itself (this is more or less clear) but the why you used this in that way (meaning)!

E.g, why you made a xor in the 1st line, call eax (what is called?), etc.?

I'm trying to understand that code :D but without success :D

THANKS,

UEZ

You were not boring me.

Inverted explained something (though he is making some wrong assumptions), but I'm gonna go line by line comparing it with AutoIt.

First of all I wanna say that no assembler would assemble it this way. It looks like this to resemble the AutoIt as much as possible.

Here goes:

Line 1

"33DB" & _                              ; xor ebx, ebx

This is the same as:

Local $b = 0

Line 2, 3, 4

"68" & SwapEndian($pRandom) & _                 ; push $pRandom
          "B8" & SwapEndian($pRtlRandomEx) & _          ; mov eax, RtlRandomEx
          "FFD0" & _                                ; call eax

This is procedure for calling function RtlRandomEx. We already have the addres of that function (that is done in AutoIt few line of code up).

Several techniques could be used for this. In this case moving addres of function to eax register and calling it later is used.

Line 5

"8BCB" & _                                  ; mov ecx, ebx

Introducing, assigning new variable. It's:

$c = $b

Line 6

"69C9" & SwapEndian(4) & _                  ; imul ecx, 4

That is multiplying:

$c = $c * 4

Line 7

"81C1" & SwapEndian($pBits) & _                     ; add ecx, $pBits

Adding $pBits to $c.

$c += $pBits

Line 8, 9, 10, 11, 12

"68" & SwapEndian(3) & _                            ; push 3 bytes
        "68" & SwapEndian($pRandom) & _                     ; push $pRandom
        "51" & _                                            ; push ecx
        "B8" & SwapEndian($pRtlMoveMemory) & _      ; mov eax, RtlMoveMemory
        "FFD0" & _                                  ; call eax

Calling function RtlMoveMemory. In AutoIt that is:

DllCall("kernel32.dll", "none", "RtlMoveMemory", _
                "ptr", $pBits + $i * 4, _
                "ptr", $pRandom, _
                "dword", 3)

Line 13

"43" & _                                            ; inc ebx

Incrementing $b by 1:

$b += 1

Line 14

"81FB" & SwapEndian($iSize) & _                     ; cmp ebx, $iSize; <- compare ebx with $iSize

Comment there explains it.

Line 15

"75" & Hex(-53, 2) & _                              ; jne -53 bytes; <- this is saying go back and do it again if not equal

This is causing it to loop until $b equals $iSize. When it's equal code continues. Until then it will return 53 bytes back (to line 2 of the code). $b will be increased by one (of course) and new calculations and calls done.

Line 16

"C3" _                                      ; ret

Return:

Return
Edited by trancexx

♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0