Jump to content
Ward

BinaryCall UDF - Write Subroutines In C, Call In AutoIt

Recommended Posts

This is a great tool for improving scripts that rely on complex equations.

Thanks, I might use it over compiling a .dll in some cases


"Just be fred, all we gotta do, just be fred."  -Vocaliod

"That is a Hadouken. A KAMEHAMEHA would have taken him 13 days and 54 episodes to form." - Roden Hoxha

@tabhooked

Clock made of cursors ♣ Desktop Widgets ♣ Water Simulation

Share this post


Link to post
Share on other sites

Thanks! In fact, I wrote code relocation generator, GAS To FASM string converter, and memory search routine in AutoIt at first. But I found they had terrible speed for large files. So I rewrote them in C. The embedded FASM, LZMA, and Base64 routines are generated by BinaryCall Tool, too.


新版 _ArrayAdd 的白痴作者,不管是誰,去死一死好了

 

Share this post


Link to post
Share on other sites

I searched the zip file for SQLite example but I guess that's not supposed to be there.

I was just thinking about combining this UDF with SQLite UDF, guess it will be much faster.

Also I will be so thankful if you could give a little more explaintion about converting the C source to this, I'm not so familiar with GCC compiler as I always use Microsoft Visual C++, could CodeBlocks be used?

I really like to use this, I want to convert some of my C functions and call them without having to export them in DLLs, but unfortunately I don't have enough knowledge to get this to work.

Thanks in advance.

Share this post


Link to post
Share on other sites

I finally managed to use it, seems interesting.

I convert some of my C functions to this and they are just awesome.

The only question I would like to ask is "Which method is faster and of course needs less memory? Using this UDF or exporting the functions in a Dll and using DllCall?"

Thanks Ward, it's a huge work, keep it up.

Share this post


Link to post
Share on other sites

Ward, I run in some problems while trying to convert this function:

#include <windows.h>
#include <iphlpapi.h>
#pragma comment(lib, "iphlpapi.lib")

BOOL IsConnectedToServer(DWORD dwProcessId)
{
    DWORD dwSize = 0;
    if (GetExtendedTcpTable(0, &dwSize, TRUE, AF_INET, TCP_TABLE_OWNER_PID_CONNECTIONS, 0) != ERROR_INSUFFICIENT_BUFFER)
        return FALSE;

    HANDLE hHeap = GetProcessHeap();

    LPVOID lpTcpTable = HeapAlloc(hHeap, 0, dwSize);
    if (lpTcpTable == NULL)
        return FALSE;

    if (GetExtendedTcpTable(lpTcpTable, &dwSize, TRUE, AF_INET, TCP_TABLE_OWNER_PID_CONNECTIONS, 0) != NO_ERROR)
    {
        HeapFree(hHeap, 0, lpTcpTable);
        return FALSE;
    }

    DWORD i;
    MIB_TCPROW_OWNER_PID TcpTable;
    for (i = 0; i < ((PMIB_TCPTABLE_OWNER_PID)lpTcpTable)->dwNumEntries; i++)
    {
        TcpTable = ((PMIB_TCPTABLE_OWNER_PID)lpTcpTable)->table[i];
        if (TcpTable.dwOwningPid == dwProcessId && TcpTable.dwRemotePort == 0xEF21)
        {
            HeapFree(hHeap, 0, lpTcpTable);
            return TRUE;
        }
    }

    HeapFree(hHeap, 0, lpTcpTable);
    return FALSE;
}

I have compiled it using GCC to this:

.file   "Test.c"
    .intel_syntax noprefix
    .text
    .globl  _IsConnectedToServer
    .def    _IsConnectedToServer;   .scl    2;  .type   32; .endef
_IsConnectedToServer:
    push    ebp
    mov ebp, esp
    push    edi
    push    esi
    push    ebx
    sub esp, 92
    mov DWORD PTR [ebp-40], 0
    mov DWORD PTR [esp+20], 0
    mov DWORD PTR [esp+16], 4
    mov DWORD PTR [esp+12], 2
    mov DWORD PTR [esp+8], 1
    lea eax, [ebp-40]
    mov DWORD PTR [esp+4], eax
    mov DWORD PTR [esp], 0
    call    _GetExtendedTcpTable
    cmp eax, 122
    je  L2
    mov eax, 0
    jmp L9
L2:
    call    _GetProcessHeap@0
    mov DWORD PTR [ebp-32], eax
    mov eax, DWORD PTR [ebp-40]
    mov DWORD PTR [esp+8], eax
    mov DWORD PTR [esp+4], 0
    mov eax, DWORD PTR [ebp-32]
    mov DWORD PTR [esp], eax
    call    _HeapAlloc@12
    sub esp, 12
    mov DWORD PTR [ebp-36], eax
    cmp DWORD PTR [ebp-36], 0
    jne L4
    mov eax, 0
    jmp L9
L4:
    mov DWORD PTR [esp+20], 0
    mov DWORD PTR [esp+16], 4
    mov DWORD PTR [esp+12], 2
    mov DWORD PTR [esp+8], 1
    lea eax, [ebp-40]
    mov DWORD PTR [esp+4], eax
    mov eax, DWORD PTR [ebp-36]
    mov DWORD PTR [esp], eax
    call    _GetExtendedTcpTable
    test    eax, eax
    je  L5
    mov eax, DWORD PTR [ebp-36]
    mov DWORD PTR [esp+8], eax
    mov DWORD PTR [esp+4], 0
    mov eax, DWORD PTR [ebp-32]
    mov DWORD PTR [esp], eax
    call    _HeapFree@12
    sub esp, 12
    mov eax, 0
    jmp L9
L5:
    mov DWORD PTR [ebp-28], 0
    jmp L6
L8:
    mov ecx, DWORD PTR [ebp-36]
    mov edx, DWORD PTR [ebp-28]
    mov eax, edx
    sal eax
    add eax, edx
    sal eax, 3
    add eax, ecx
    lea edx, [ebp-64]
    lea ebx, [eax+4]
    mov eax, 6
    mov edi, edx
    mov esi, ebx
    mov ecx, eax
    rep movsd
    mov eax, DWORD PTR [ebp-44]
    cmp eax, DWORD PTR [ebp+8]
    jne L7
    mov eax, DWORD PTR [ebp-48]
    cmp eax, 61217
    jne L7
    mov eax, DWORD PTR [ebp-36]
    mov DWORD PTR [esp+8], eax
    mov DWORD PTR [esp+4], 0
    mov eax, DWORD PTR [ebp-32]
    mov DWORD PTR [esp], eax
    call    _HeapFree@12
    sub esp, 12
    mov eax, 1
    jmp L9
L7:
    inc DWORD PTR [ebp-28]
L6:
    mov eax, DWORD PTR [ebp-36]
    mov eax, DWORD PTR [eax]
    cmp eax, DWORD PTR [ebp-28]
    ja  L8
    mov eax, DWORD PTR [ebp-36]
    mov DWORD PTR [esp+8], eax
    mov DWORD PTR [esp+4], 0
    mov eax, DWORD PTR [ebp-32]
    mov DWORD PTR [esp], eax
    call    _HeapFree@12
    sub esp, 12
    mov eax, 0
L9:
    lea esp, [ebp-12]
    pop ebx
    pop esi
    pop edi
    pop ebp
    ret
    .def    _GetExtendedTcpTable;   .scl    2;  .type   32; .endef
    .def    _GetProcessHeap@0;  .scl    2;  .type   32; .endef
    .def    _HeapAlloc@12;  .scl    2;  .type   32; .endef
    .def    _HeapFree@12;   .scl    2;  .type   32; .endef

But your convertor says:

 

Unresolved external symbol: "_GetExtendedTcpTable"

and fails.

Share this post


Link to post
Share on other sites

Your code uses "GetExtendedTcpTable" API

According to MSDN, it requires "Iphlpapi.dll".

This dll is not declared in BinaryCall.inc by default.

To declare it, add following line to BinaryCall.inc

def_api iphlpapi.dll,10,GetExtendedTcpTable

新版 _ArrayAdd 的白痴作者,不管是誰,去死一死好了

 

Share this post


Link to post
Share on other sites

Yes, I already declared following frequency used DLL in BinaryCall.inc (number 1~9).

  1. kernel32.dll
  2. user32.dll
  3. gdi32.dll
  4. shell32.dll
  5. advapi32.dll
  6. comctl32.dll
  7. comdlg32.dll
  8. wsock32.dll
  9. msvcrt.dll
So, if the DLL you used is not here, you must declare it by yourself.
Edited by Ward

新版 _ArrayAdd 的白痴作者,不管是誰,去死一死好了

 

Share this post


Link to post
Share on other sites

I got an error when I tried to make this function to work:

// Credits to matwachich
// http://www.autoitscript.com/forum/topic/150905-need-advise-on-my-wsa-tcp-functions-c/?p=1078769

#define _WIN32_WINNT 0x501
#include <ws2tcpip.h>

int TCPConnect (const char* host, const char* port)
{
    struct addrinfo hints, *result = NULL;
    ZeroMemory(&hints, sizeof(hints));

    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    if (getaddrinfo(host, port, &hints, &result) != 0) {
        return 0;
    }

    SOCKET ConnectSocket = INVALID_SOCKET;
    ConnectSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
    if (ConnectSocket == INVALID_SOCKET) {
        freeaddrinfo(result);
        return 0;
    }

    if (connect(ConnectSocket, result->ai_addr, (int)result->ai_addrlen) != 0) {
        freeaddrinfo(result);
        return 0;
    }
    freeaddrinfo(result);

    unsigned long mode = 1;
    if (ioctlsocket(ConnectSocket, FIONBIO, &mode) != 0) {
        return 0;
    }

    return ConnectSocket;
}

Using gcc I got this asm file

.file   "prog.cpp"
    .intel_syntax noprefix
    .text
    .globl  __Z10TCPConnectPKcS0_
    .def    __Z10TCPConnectPKcS0_;  .scl    2;  .type   32; .endef
__Z10TCPConnectPKcS0_:
LFB8:
    .cfi_startproc
    .cfi_personality 0,___gxx_personality_v0
    .cfi_lsda 0,LLSDA8
    push    ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    mov ebp, esp
    .cfi_def_cfa_register 5
    sub esp, 72
    mov DWORD PTR [ebp-16], 0
    mov DWORD PTR [esp+8], 32
    mov DWORD PTR [esp+4], 0
    lea eax, [ebp-52]
    mov DWORD PTR [esp], eax
    call    _memset
    mov DWORD PTR [ebp-48], 2
    mov DWORD PTR [ebp-44], 1
    mov DWORD PTR [ebp-40], 6
    lea eax, [ebp-16]
    mov DWORD PTR [esp+12], eax
    lea eax, [ebp-52]
    mov DWORD PTR [esp+8], eax
    mov eax, DWORD PTR [ebp+12]
    mov DWORD PTR [esp+4], eax
    mov eax, DWORD PTR [ebp+8]
    mov DWORD PTR [esp], eax
LEHB0:
    call    _getaddrinfo@16
    sub esp, 16
    test    eax, eax
    setne   al
    test    al, al
    je  L2
    mov eax, 0
    jmp L10
L2:
    mov DWORD PTR [ebp-12], -1
    mov eax, DWORD PTR [ebp-16]
    mov ecx, DWORD PTR [eax+12]
    mov eax, DWORD PTR [ebp-16]
    mov edx, DWORD PTR [eax+8]
    mov eax, DWORD PTR [ebp-16]
    mov eax, DWORD PTR [eax+4]
    mov DWORD PTR [esp+8], ecx
    mov DWORD PTR [esp+4], edx
    mov DWORD PTR [esp], eax
    call    _socket@12
    sub esp, 12
    mov DWORD PTR [ebp-12], eax
    cmp DWORD PTR [ebp-12], -1
    jne L4
    mov eax, DWORD PTR [ebp-16]
    mov DWORD PTR [esp], eax
    call    _freeaddrinfo@4
    sub esp, 4
    mov eax, 0
    jmp L10
L4:
    mov eax, DWORD PTR [ebp-16]
    mov eax, DWORD PTR [eax+16]
    mov edx, eax
    mov eax, DWORD PTR [ebp-16]
    mov eax, DWORD PTR [eax+24]
    mov DWORD PTR [esp+8], edx
    mov DWORD PTR [esp+4], eax
    mov eax, DWORD PTR [ebp-12]
    mov DWORD PTR [esp], eax
    call    _connect@12
    sub esp, 12
    test    eax, eax
    setne   al
    test    al, al
    je  L5
    mov eax, DWORD PTR [ebp-16]
    mov DWORD PTR [esp], eax
    call    _freeaddrinfo@4
    sub esp, 4
    mov eax, 0
    jmp L10
L5:
    mov eax, DWORD PTR [ebp-16]
    mov DWORD PTR [esp], eax
    call    _freeaddrinfo@4
    sub esp, 4
    mov DWORD PTR [ebp-20], 1
    mov eax, 4
    and eax, 127
    sal eax, 16
    or  eax, -2147457410
    lea edx, [ebp-20]
    mov DWORD PTR [esp+8], edx
    mov DWORD PTR [esp+4], eax
    mov eax, DWORD PTR [ebp-12]
    mov DWORD PTR [esp], eax
    call    _ioctlsocket@12
LEHE0:
    sub esp, 12
    test    eax, eax
    setne   al
    test    al, al
    je  L6
    mov eax, 0
    jmp L10
L6:
    mov eax, DWORD PTR [ebp-12]
    jmp L10
L9:
    mov DWORD PTR [esp], eax
LEHB1:
    call    __Unwind_Resume
LEHE1:
L10:
    leave
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret
    .cfi_endproc
LFE8:
    .def    ___gxx_personality_v0;  .scl    2;  .type   32; .endef
    .section    .gcc_except_table,"w"
LLSDA8:
    .byte   0xff
    .byte   0xff
    .byte   0x1
    .uleb128 LLSDACSE8-LLSDACSB8
LLSDACSB8:
    .uleb128 LEHB0-LFB8
    .uleb128 LEHE0-LEHB0
    .uleb128 L9-LFB8
    .uleb128 0
    .uleb128 LEHB1-LFB8
    .uleb128 LEHE1-LEHB1
    .uleb128 0
    .uleb128 0
LLSDACSE8:
    .text
    .ident  "GCC: (GNU) 4.8.1"
    .def    _memset;    .scl    2;  .type   32; .endef
    .def    _getaddrinfo@16;    .scl    2;  .type   32; .endef
    .def    _socket@12; .scl    2;  .type   32; .endef
    .def    _freeaddrinfo@4;    .scl    2;  .type   32; .endef
    .def    _connect@12;    .scl    2;  .type   32; .endef
    .def    _ioctlsocket@12;    .scl    2;  .type   32; .endef
    .def    __Unwind_Resume;    .scl    2;  .type   32; .endef

I added manually in BinaryCall.inc this line

def_adr ws2_32.dll,10,getaddrinfo,socket,freeaddrinfo,connect,ioctlsocket

When I use GAS2AU3 Converter I got this error

 

---------------------------
Flat Assembler Error: -108
---------------------------
ILLEGAL_INSTRUCTION

LINE NUMBER: 3048

ERROR LINE: "    .uleb128 LLSDACSE8-LLSDACSB8"


When the words fail... music speaks

Share this post


Link to post
Share on other sites
  1. Try to use "gcc", not "g++" to compile the source code. (.uleb128 pseudo-op not yet support).
  2. You should use "def_api", not "def_adr". They are different.
  3. You use "ws2_32.dll", so the line "def_api wsock32.dll" may need be deleted (or add ";" to set as comment)
Edited by Ward

新版 _ArrayAdd 的白痴作者,不管是誰,去死一死好了

 

Share this post


Link to post
Share on other sites

This is very cool. Can you explain a bit more about the def_api (well, I think I get this one), def_api_ (with the extra _ ), def_adr, and def_label lines in the .inc file?

Edited by wraithdu

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

  • Similar Content

    • By Stew
      (Edited from original.  Please note that I AM NOT AN AUTOIT EXPERT.  I write code using Autoit frequently but I am no expert, especially when it comes to I/O.  So any remarks that start with "Why did you..." can be answered by referring to the first sentence.  This project was done in Autoit because of an interface I built to display the data.)
      Attached is a program and ascii input file I wrote to read stock price data, convert it to binary and then read it back into the program in binary.  The goal was to show increased performance for reading the files in binary and provide a demo on how to read/write binary for int32, int64, double and strings for anyone who might find it helpful.  The results on my PC show the following:
      Time to read ascii file only: 456.981951167202
      Ascii read & process time: 6061.83075631701
      Binary write file time: 14787.9184635239
      Time just to read binary file: 42.418867292311
      Binary read and process time: 4515.16129830537
      A couple things to note:
      1) The 32 MB ascii file took 10x longer to read than the 15 MB binary file.  Not entirely sure why.  Both were read into a buffer.
      2) The Binary write takes a long time but I made no effort to optimize this because the plan was to write this file one time only so I don't mind if it takes longer to write this file.  I care much more about how long it takes to read the file because I will be reading it many times.
      3) There was a modest gain in converting the ascii file to binary in terms of file size and reading speed.
      So big picture... not sure it's worth the effort to convert the files to binary even though most of the data is numerical data in the binary file.  That was actually surprising as I expected there would be more of a difference.  Any ideas on how to get the binary data to read at a faster rate would be great.
       
      binary.au3
      2019_02_08.zip
    • By Beege
      Years ago I tried to put some functionality together to do some of this here. I started off in the right direction but it ended up getting out of control. Any new thing I learned along the way (as I was creating it), I kept trying to add in and it all became a mess. One of my primary goals with that was to make sure the code could always be pre-compiled and still run. That part did work and I was able create a couple of good projects with it, but still a lot of parts I wouldn't consider correct now and certainly not manageable. 
      Here is a redo of what I was going for there only this time I'm not going to be generating any of the assembly code. That's all going to be done using the built in macro engine already within fasm.dll and the macros written by Tomasz Grysztar (creator of fasm) so this time I don't have to worry about any of the code that gets generated. Im not going to touch the source at all. In fact there is not even going to be _fasmadd or global variables tracking anything. None of that is needed with the added basic and extended headers that you can read more about in the fasm documentation. You can use almost all of whats in the documentation section for basic/extended headers but ignore the parts about import,exports,resources,text encoding. doesn't really apply here.
      Here are examples I came up with that covers a lot of core functionality to write assembly code in a manner that you already know how. If/while using multiple conditional logic statements,  multiple functions, local variables, global variables, structures, COM interfaces, strings as parameters, nesting function calls. These are all things you dont even have to think about when your doing it in autoit and I'm hoping this helps bring some of that same comfort to fasm. 
      These 3 simple callback functions will be used through out the examples  
      Global $gConsoleWriteCB = DllCallbackRegister('_ConsoleWriteCB', 'dword', 'str;dword'), $gpConsoleWriteCB = DllCallbackGetPtr($gConsoleWriteCB) Global $gDisplayStructCB = DllCallbackRegister('_DisplayStructCB', 'dword', 'ptr;str'), $gpDisplayStructCB = DllCallbackGetPtr($gDisplayStructCB) Global $gSleepCB = DllCallbackRegister('_SleepCB', 'dword', 'dword'), $gpSleepCB = DllCallbackGetPtr($gSleepCB) Func _ConsoleWriteCB($sMsg, $iVal) ConsoleWrite($sMsg & $iVal & @CRLF) EndFunc ;==>_ConsoleWriteCB Func _DisplayStructCB($pStruct, $sStr) _WinAPI_DisplayStruct(DllStructCreate($sStr, $pStruct), $sStr, 'def=' & $sStr) EndFunc ;==>_DisplayStructCB Func _SleepCB($iSleep) Sleep($iSleep) EndFunc ;==>_SleepCB  
      proc/endp - like func and endfunc with some extra options. "uses" statement will preserve the registers specified. stdcall is the default call type if not specified. DWORD is the default parameter size if not specified. ret value is also handled for you. You don't have to worry about adjusting a number every time you throw on an extra parameter. In fact you don't ever have to specify/touch ebp/esp at all with these macros. See Basic headers -> procedures for full description.
      force - just a macro I added for creating a anonymous label for the first/primary function to ensure the code gets generated. The problem we are getting around is this: in our example, _main is never actually called anywhere within fasm code and fasm engine detects that and thinks the code is doing nothing. Because of that it wants to skip generating that code and all code that was called by it leaving you with nothing. This is actually a great feature but we obviously want to make an exception for our main/initial/primary function that starts it all off so thats all this does.
      Func _Ex_Proc() $g_sFasm = '' _('force _main') _('proc _main uses ebx, parm1, parm2') ; _('proc _main stdcall uses ebx, parm1:DWORD, parm2:DWORD'); full statement _(' mov ebx, [parm1]') _(' add ebx, [parm2]') _(' mov eax, ebx') _(' ret') _('endp') Local $tBinary = _FasmAssemble($g_sFasm) If @error Then Exit (ConsoleWrite($tBinary & @CRLF)) Local $iAdd = DllCallAddress('dword', DllStructGetPtr($tBinary), 'dword', 5, 'dword', 5) ConsoleWrite('Parm1+Parm2=' & $iAdd[0] & @CRLF) EndFunc ;==>_Ex_Proc  
          Here Im showing you calling _ConsoleWriteCB autoit function we set up as a callback. Its how you would call any function in autoit from fasm.
          Strings - Notice Im creating and passing "edx = " string to the function on the fly. So helpful!
          invoke - same as a stdcall with brackets []. Use this for when calling autoit functions
       
      Func _Ex_Callback() $g_sFasm = '' _('force _main') _('proc _main, pConsoleWriteCB, parm1, parm2') _(' mov edx, [parm1]') _(' add edx, [parm2]') _(' invoke pConsoleWriteCB, "edx = ", edx') ; ;~ _(' stdcall [pConsoleWriteCB], "edx = ", edx') ; same as invoke _(' ret') _('endp') Local $tBinary = _FasmAssemble($g_sFasm) If @error Then Exit (ConsoleWrite($tBinary & @CRLF)) DllCallAddress('ptr', DllStructGetPtr($tBinary), 'ptr', $gpConsoleWriteCB, 'dword', 5, 'dword', 5) EndFunc ;==>_Ex_Callback  
      Showing .while/.endw, .if/.elseif/.else/.endif usage. .repeat .until are also macros you can use. See Extended Headers -> Structuring the source. Ignore .code, .data, .end - Those are gonna be more for a full exe.
      invokepcd/invokepd - these are macros I added that are the same as invoke, just preserve (push/pop) ECX or both ECX and EDX during the call. Below is also a good example of what can happen when you don't preserve registers that are caller saved (us calling the function) vs callie saved (us creating the function). EAX,ECX,EDX are all caller saved so when we call another function like the autoit callback _ConsoleWriteCB, those registers could have very different values then what was in them before the call. This function below should do at least two loops, but it doesn't (at least on my pc) without preserving ECX because ECX is no longer zero when the function returns.
      Keep the same thought in mind for registers EBX,ESI,EDI when you are creating assembly functions (callie saved). If your functions uses those registers, You need to preserve and restore them before your code returns back to autoit or else you could cause a similar effect to autoit. "trashing" registers is a term I've seen used alot when referring to these kind of mistakes
      Func _Ex_IfElseWhile() $g_sFasm = '' _('force _main') _('proc _main uses ebx, pConsoleWriteCB') _(' xor edx, edx') ; edx=0 _(' mov eax, 99') ; _(' mov ebx, 10') _(' xor ecx, ecx') ; ecx=0 _(' .while ecx = 0') _(' .if eax<=100 & ( ecx | edx )') ; not true on first loop _(' inc ebx') _(' invokepcd pConsoleWriteCB, "Something True - ebx=", ebx') _(' ret') _(' .elseif eax < 99') ; Just showing you the elseif statement _(' inc ebx') _(' .else') ;~ _(' invokepcd pConsoleWriteCB, "Nothing True - ebx=", ebx') ; comment this and uncomment the line below _(' invoke pConsoleWriteCB, "Nothing True - ebx=", ebx') _(' inc edx') ; this will make next loop true _(' .endif') _(' .endw') _(' ret') _('endp') Local $tBinary = _FasmAssemble($g_sFasm) If @error Then Exit (ConsoleWrite($tBinary & @CRLF)) DllCallAddress('dword', DllStructGetPtr($tBinary), 'ptr', $gpConsoleWriteCB) EndFunc ;==>_Ex_IfElseWhile  
          Sub Functions : You already understand this. Not really "sub", its just another function you call. And those functions call other functions and so on.
          fix : syntax sugar - Look how easy it was to replace invoke statement with our actual autoit function name
          ptr : more sugar - same thing as using brackets [parm1]
          Nesting : In subfunc1 we pass the results of two function calls to the same function we are calling
      Func _Ex_SubProc() $g_sFasm = '' ;replace all '_ConsoleWriteCB' statments with 'invoke pConsoleWriteCB' before* assembly _('_ConsoleWriteCB fix invoke pConsoleWriteCB') _('force _main') _('proc _main uses ebx, pConsoleWriteCB, parm1, parm2') _(' mov ebx, [parm1]') _(' add ebx, [parm2]') _(' _ConsoleWriteCB, "ebx start = ", ebx') _(' stdcall _subfunc1, [pConsoleWriteCB], [parm1], [parm2]') _(' _ConsoleWriteCB, "ebx end = ", ebx') _(' ret') _('endp') ; _('proc _subfunc1 uses ebx, pConsoleWriteCB, parm1, parm2') _(' mov ebx, [parm1]') _(' _ConsoleWriteCB, " subfunc1 ebx start = ", ebx') _(' stdcall _SubfuncAdd, <stdcall _SubfuncAdd, [parm1], [parm2]>, <stdcall _SubfuncAdd, ptr parm1, ptr parm2>') ; Nesting functions _(' _ConsoleWriteCB, " _SubfuncAdd nested <5+5><5+5> = ", eax') _(' _ConsoleWriteCB, " subfunc1 ebx end = ", ebx') _(' ret') _('endp') ; _('proc _SubfuncAdd uses ebx, parm1, parm2') _(' mov ebx, [parm1]') _(' add ebx, [parm2]') _(' mov eax, ebx') _(' ret') _('endp') Local $tBinary = _FasmAssemble($g_sFasm) If @error Then Exit (ConsoleWrite($tBinary & @CRLF)) DllCallAddress('dword', DllStructGetPtr($tBinary), 'ptr', $gpConsoleWriteCB, 'dword', 5, 'dword', 5) EndFunc ;==>_Ex_SubProc  
      This demonstrates the struct macro. See basic headers -> Structures for more info
      _FasmAu3StructDef will create an equivalent formated structure definition. All elements already have a sizeof.#name created internally. So in this example sizeof.AUTSTRUCT.x would equal 8. sizeof.AUTSTRUCT.z would equal 16 (2*8). I have added an additional one sot.#name (sizeoftype) for any array that gets created. Below is the source of what gets generate from 'dword x;dword y;short z[8]'. Also dont get confused that in fasm data definitions,  d is for data as in db (data byte) or dw (data word). Not double like it is in autoit's dword (double word). See intro -> assembly syntax -> data definitions
         
      struct AUTSTRUCT x dd ? y dd ? z dw 8 dup ? ends define sot.AUTSTRUCT.z 2 Func _Ex_AutDllStruct() $g_sFasm = '' Local Const $sTag = 'dword x;dword y;short z[8]' _(_FasmAu3StructDef('AUTSTRUCT', $sTag)) _('force _main') _('proc _main uses ebx, pDisplayStructCB, pAutStruct') _(' mov ebx, [pAutStruct]') ; place address of autoit structure in ebx _(' mov [ebx+AUTSTRUCT.x], 1234') _(' mov [ebx+AUTSTRUCT.y], 4321') _(' xor edx, edx') _(' mov ecx, 5') ; setup ecx for loop instruction _(' Next_Z_Index:') ; set elements 1-6 (0-5 here in fasm) _(' mov [ebx+AUTSTRUCT.z+(sot.AUTSTRUCT.z*ecx)], cx') ; cx _(' loop Next_Z_Index') _(' invoke pDisplayStructCB, [pAutStruct], "' & $sTag & '"') _(' mov [ebx+AUTSTRUCT.z+(sot.AUTSTRUCT.z*6)], 666') _(' mov [ebx+AUTSTRUCT.z+(sot.AUTSTRUCT.z*7)], 777') _(' ret') _('endp') Local $tBinary = _FasmAssemble($g_sFasm) If @error Then Exit (ConsoleWrite($tBinary & @CRLF)) Local $tAutStruct = DllStructCreate($sTag) DllCallAddress('ptr', DllStructGetPtr($tBinary), 'ptr', $gpDisplayStructCB, 'struct*', $tAutStruct) _WinAPI_DisplayStruct($tAutStruct, $sTag) EndFunc ;==>_Ex_AutDllStruct  
      Here shows the locals/endl macros for creating local variables. See basic headers -> procedures. We create a local string and the same dll structure as above. Notice that you can initialize all the values of the structure on creation. There is a catch to this though that I will show you in next example.
      addr macro - This will preform the LEA instruction in EDX and then push the address on to the stack. This is awesome, just remember its using EDX to perform that and does not preserve it. You'll pretty much want to use that for any local variables you are passing around.
      Edit: I shouldn't say things like that so causally.  Use the addr macro as much as you want but remember that it is adding a couple of extra instuctions each time you use it so if your calling invoke within a loop and ultimate performance is one of your goals, you should probably perform the LEA instructions before the loop and save the pointer to a separate variable that your would then use in the loop. 
      Func _Ex_LocalVarsStruct() $g_sFasm = '' Local Const $sTag = 'dword x;dword y;short z[8]' _(_FasmAu3StructDef('POINT', $sTag)) _('force _main') _('proc _main, pDisplayStructCB') _(' locals') _(' sTAG db "' & $sTag & '", 0') ; define local string. the ', 0' at the end is to terminate the string. _(' tPoint POINT 1,2,<0,1,2,3,4,5,6,7>') ; initalize values in struct _(' endl') _(' invoke pDisplayStructCB, addr tPoint, addr sTAG') _(' mov [tPoint+POINT.x], 4321') _(' mov [tPoint+POINT.z+sot.POINT.z*2], 678') _(' invoke pDisplayStructCB, addr tPoint, addr sTAG') _(' ret') _('endp') Local $tBinary = _FasmAssemble($g_sFasm) If @error Then Exit (ConsoleWrite($tBinary & @CRLF)) Local $ret = DllCallAddress('ptr', DllStructGetPtr($tBinary), 'ptr', $gpDisplayStructCB) EndFunc ;==>_Ex_LocalVarsStruct  
      Back to the catch. Alignment is the problem here but only with the initializes. I'm handling all the alignment ok so you don't have to worry about that for creating structures that need alignment, only if you are using the one liner initialize in locals. The problem comes from extra padding being defined to handle the alignment, but fasm doesn't really know its just padding so without adding extra comma's to the initiator statement, your data ends up in the padding or simply fails. The _FasmFixInit will throw in the extra commas needed to skip the padding.
      Func _Ex_LocalVarStructEx() $g_sFasm = '' $sTag = 'byte x;short y;char sNote[13];long odd[5];word w;dword p;char ext[3];word finish' _(_FasmAu3StructDef('POINT', $sTag)) _('force _main') _('proc _main, pDisplayStructCB') _(' locals') _(' tPoint POINT ' & _FasmFixInit('1,222,<"AutoItFASM",0>,<41,43,43,44,45>,6,7,"au3",12345', $sTag)) _(' endl') _(' invoke pDisplayStructCB, addr tPoint, "' & $sTag & '"') _(' ret') _('endp') Local $tBinary = _FasmAssemble($g_sFasm) If @error Then Exit (ConsoleWrite($tBinary & @CRLF)) DllCallAddress('dword', DllStructGetPtr($tBinary), 'ptr', $gpDisplayStructCB) EndFunc ;==>_Ex_LocalVarStructEx  
      I love this one and it is really not even that hard to explain. We got multiple functions and want to be able to call them individually. Here I simply use the primary function to tell me where all the functions are. I load all the offsets (byte distance from start of code) of each each function in to a dllstruct, then once its passed back to autoit, adjust all the offsets by where they are actually located in memory (pointer to dll). From there you can call each individual function as shown previously. full code is in the zip. 
      String functions came from link below. I ended up modifying strcmp to get a value I understand. CRC32 func is all mine. Made it so easy being able to call _strlen and then use while statements like I normally would    https://www.strchr.com/strcmp_and_strlen_using_sse_4.2
      Func _Ex_SSE4_Library() $g_sFasm = '' _('force _main') _('proc _main stdcall, pAdd') _(' mov eax, [pAdd]') _(' mov dword[eax], _crc32') _(' mov dword[eax+4], _strlen') _(' mov dword[eax+8], _strcmp') _(' mov dword[eax+12], _strstr') _(' ret') _('endp') _('proc _crc32 uses ebx ecx esi, pStr') ; _('endp') _('proc _strlen uses ecx edx, pStr') ; _('endp') _('proc _strcmp uses ebx ecx edx, pStr1, pStr2') ; ecx = string1, edx = string2' ; _('endp') _('proc _strstr uses ecx edx edi esi, sStrToSearch, sStrToFind') ; _('endp') Local $tBinary = _FasmAssemble($g_sFasm) If @error Then Exit (ConsoleWrite($tBinary & @CRLF)) Local $pBinary = DllStructGetPtr($tBinary) Local $sFunction_Offsets = 'dword crc32;dword strlen;dword strcmp;dword strstr' $tSSE42 = DllStructCreate($sFunction_Offsets) $ret = DllCallAddress('ptr', $pBinary, 'struct*', $tSSE42) _WinAPI_DisplayStruct($tSSE42, $sFunction_Offsets, 'Function Offsets') ;Correct all addresses $tSSE42.crc32 += $pBinary $tSSE42.strlen += $pBinary $tSSE42.strcmp += $pBinary $tSSE42.strstr += $pBinary $sTestStr = 'This is a test string!' ConsoleWrite('$sTestStr = ' & $sTestStr & @CRLF) $iCRC = DllCallAddress('int', $tSSE42.crc32, 'str', $sTestStr) ConsoleWrite('CRC32 = ' & Hex($iCRC[0]) & @CRLF) $aLen = DllCallAddress('int', $tSSE42.strlen, 'str', $sTestStr) ConsoleWrite('string len = ' & $aLen[0] & ' :1:' & @CRLF) $aFind = DllCallAddress('int', $tSSE42.strcmp, 'str', $sTestStr, 'str', 'This iXs a test') ConsoleWrite('+strcmp = ' & $aFind[0] & @CRLF) $aStr = DllCallAddress('int', $tSSE42.strstr, 'str', 'This is a test string!', 'str', 'test') ConsoleWrite('Strstr = ' & $aStr[0] & @CRLF) EndFunc ;==>_Ex_SSE4_Library  
      I'm extremely happy I got a com interface example working. I AM. That being said.. I'm pretty fucking annoyed I cant find the original pointer when using using built in ObjCreateInterface I've tired more than just whats commented out. It anyone has any input (I know someone here does!) that would be great. Using the __ptr__ from _autoitobject works below. Example will delete the tab a couple times.
      Edit: Got that part figured out. Thanks again trancexx!
      Func _Ex_ComObjInterface() $g_sFasm = '' ;~ _AutoItObject_StartUp() ;~ Local Const $sTagITaskbarList = "QueryInterface long(ptr;ptr;ptr);AddRef ulong();Release ulong(); HrInit hresult(); AddTab hresult(hwnd); DeleteTab hresult(hwnd); ActivateTab hresult(hwnd); SetActiveAlt hresult(hwnd);" ;~ Local $oList = _AutoItObject_ObjCreate($sCLSID_TaskbarList, $sIID_ITaskbarList, $sTagITaskbarList) Local Const $sCLSID_TaskbarList = "{56FDF344-FD6D-11D0-958A-006097C9A090}", $sIID_ITaskbarList = "{56FDF342-FD6D-11D0-958A-006097C9A090}" Local Const $sTagITaskbarList = "HrInit hresult(); AddTab hresult(hwnd); DeleteTab hresult(hwnd); ActivateTab hresult(hwnd); SetActiveAlt hresult(hwnd);" Local $oList = ObjCreateInterface($sCLSID_TaskbarList, $sIID_ITaskbarList, $sTagITaskbarList) _('interface ITaskBarList,QueryInterface,AddRef,Release,HrInit,AddTab,DeleteTab,ActivateTab,SetActiveAlt') ; _('force _main') _('proc _main uses ebx, pSleepCB, oList, pGUIHwnd') _(' comcall [oList],ITaskBarList,HrInit') _(' xor ebx, ebx') _(' .repeat') _(' invoke pSleepCB, 500') ; wait _(' comcall [oList],ITaskBarList,DeleteTab,[pGUIHwnd]') ; delete _(' invoke pSleepCB, 500') ; wait _(' comcall [oList],ITaskBarList,AddTab,[pGUIHwnd]') ; add back _(' comcall [oList],ITaskBarList,ActivateTab,[pGUIHwnd]') ; actvate _(' inc ebx') _(' .until ebx=4') _(' ret') _('endp') Local $tBinary = _FasmAssemble($g_sFasm) If @error Then Exit (ConsoleWrite($tBinary & @CRLF)) Local $GUI = GUICreate("_Ex_ComObjInterface ------ DeleteTab") GUISetState() ;~ DllCallAddress('ptr', DllStructGetPtr($tBinary), 'ptr', $gpSleepCB, 'ptr', $oList.__ptr__, 'dword', Number($GUI)) DllCallAddress('ptr', DllStructGetPtr($tBinary), 'ptr', $gpSleepCB, 'ptr', $oList(), 'dword', Number($GUI)) EndFunc ;==>_Ex_ComObjInterface  
      Lastly here is an example of how to use a global variable. Without using the org statement, this value is just an offset like the functions in the library example. In order for your code to know that location, it needs to know where the real starting address is so we have to pass that to our functions. Once you have it, if you write your code proper and preserve registers correctly, you can just leave in EBX. From what I understand, if all functions are following stdcall rules, that register shouldn't change in less you change it. Something cool and important to remember is these variables will hold whatever values left in them till you wipe the memory (dll structure) holding your code. keep that in mind if you made your dll structure with a static keyword. If thats the case treat them like static variables
      Func _Ex_GlobalVars() $g_sFasm = '' _('_ConsoleWriteCB fix invoke pConsoleWriteCB') ; _('force _main') _('proc _main uses ebx, pMem, pConsoleWriteCB, parm1') _(' mov ebx, [pMem]') ; This is where are code starts in memory. _(' mov [ebx + g_Var1], 111') _(' add [ebx + g_Var1], 222') _(' _ConsoleWriteCB, "g_Var1 = ", [ebx + g_Var1]') _(' stdcall subfunc1, [pMem], [pConsoleWriteCB], [parm1]') _(' mov eax, g_Var1') _(' ret') _('endp') ; _('proc subfunc1 uses ebx, pMem, pConsoleWriteCB, parm1') _(' mov ebx, [pMem]') _(' mov [ebx + g_Var1], 333') _(' _ConsoleWriteCB, "g_Var1 from subfunc1= ", [ebx + g_Var1]') _(' stdcall subfunc2, [pConsoleWriteCB], [parm1]') ; no memory ptr passed. ebx should be callie saved _(' _ConsoleWriteCB, "g_Var1 from subfunc1= ", [ebx + g_Var1]') _(' stdcall subfunc2, [pConsoleWriteCB], [parm1]') _(' ret') _('endp') ; _('proc subfunc2, pConsoleWriteCB, parm1') _(' add [ebx + g_Var1], 321') _(' _ConsoleWriteCB, "g_Var1 from subfunc2= ", [ebx + g_Var1]') _(' ret') _('endp') ; _('g_Var1 dd ?') ; <--------- Global Var Local $tBinary = _FasmAssemble($g_sFasm) If @error Then Exit (ConsoleWrite($tBinary & @CRLF)) Local $iOffset = DllCallAddress('dword', DllStructGetPtr($tBinary), 'struct*', $tBinary, 'ptr', $gpConsoleWriteCB, 'dword', 55)[0] ConsoleWrite('$iOffset = ' & $iOffset & @CRLF) Local $tGVar = DllStructCreate('dword g_Var1', DllStructGetPtr($tBinary) + $iOffset) ConsoleWrite('Directly access g_Var1 -> ' & $tGVar.g_Var1 & @CRLF) ; direct access EndFunc ;==>_Ex_GlobalVars  
      FasmEx.zip
    • By Beege
      Special thanks to Ward for his udf and Trancexx for her assembly examples as they have played a huge role in my learning of asm.    UDF Requires  >Beta version 3.3.9.19 or higher. Also Requires >Wards Fasm UDF.  Direct Download Link   FASMEx.zip   FasmEx 9-29-2013.zip   This is dead. See new version here : 
       
       
       
    • By argumentum
      AutoIt Machine Code Algorithm Collection
      By Ward, November 11, 2010 in AutoIt Example Scripts 
      Posted November 11, 2010 (edited) I have already published a lot of AutoIt UDF about algorithm, but all of them only support 32 bits or so called X86 system. Recently I got a computer with Windows 7 64 bits, so I finally added X64 support to most of my old projects. Besides, I also added some new. For example, some compression algorithm and SHA3 Candidates.
      Following are the algorithms list:
      Checksum   CRC16   CRC32   ADLER32 Compression   FastLZ   LZF   LZMA   LZMAT   MiniLZO   QuickLZ Encode   Base64   ARC4   XXTEA   DES   AES Hash   Checksums (CRC16/CRC32/ADLER32)   MD2   MD4   MD5   SHA1   SHA2 (SHA224/256/384/512)   SHA3 Candidates     BLAKE     BMW (Blue Midnight Wish)     CUBEHASH     ECHO     SHABAL     SKEIN Some points to mention:
      All of the subroutines have one or more examples to demonstrate the usage. Since the function and usage of subroutine are easy to understand. A complete subroutines and parameters list are unavailability now. Sorry for my lazy. All of the subroutines here invoked by Lazycat's method (through CallWindowProc API). My MemoryDLL UDF is not necessary this time. Although MemoryFuncCall (part of MemoryDLL) is still good, but inevitably, it is slower than CallWindowProc. Some subroutines have the same name with my old machine code version UDF. But for some reason, I rearrange the position of the parameters. Please not mix up. If you notice, yes, checksums are duplicated. But they receive different parameters. One is the old style, and another use the same interface as other hashes. Choose what you like, but don't use them in the same time. Some algorithm already supported by the standard UDF "Encryption.au3". But I still provide them, because some system lack of the full support of Windows Crypt Library. If you are looking for only one hash algorithm, for example, used in encryption, I suggested "SHABAL_TINY.au3". Although it is a bit slower then SHABAL, but it is smaller, and it supports different size of output (from 32 to 512 bits).
    • By FMS
      Hello,
      I'm trying to read a binary file to an array but couln't get it to work.
      Also I coul not find any help in the forum around this subject whish was helpfull.
      Is there any way it could be done?
      I tried a lot of ways but maybe somebody know's the right way?
      #AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #include <File.au3> #include <Array.au3> #include <AutoItConstants.au3> Local $in=FileOpen("TEST_labels.idx1-ubyte",16) ; 16+0=Read binary Local $data = FileRead($in) Local $FileArray = BinaryToString($data,4) ;~ $FileArray = StringSplit($BinarydData, @CRLF, 1+2) ;~ Local $FileArray = StringRegExp($BinarydData, "[^\r\n]+", 3) FileClose($in) _ArrayDisplay($FileArray,"$FileArray","",32) MsgBox($MB_SYSTEMMODAL, "", "$FileArray = " & $FileArray )  
      TEST_labels.idx1-ubyte
×
×
  • Create New...