The MASM Forum

General => The Campus => Topic started by: 2B||!2B on May 06, 2019, 07:04:40 PM

Title: Invoke an external procedure on a memory address?
Post by: 2B||!2B on May 06, 2019, 07:04:40 PM
Hello,

Does anyone have an idea how to make invoke works on an external function that resides in a memory address?

Example:

.Data?
MyFunction          dd       ?

Mov EAX,MyMemAddress   ;[MyMemAdress contains a pointer to an external function lets say GetTickCount]
MOV MyFunction,EAX
invoke [MyFunction]
Title: Re: Invoke an external procedure on a memory address?
Post by: hutch-- on May 06, 2019, 07:12:46 PM
Why not just use the CALL mnemonic ?
Title: Re: Invoke an external procedure on a memory address?
Post by: jj2007 on May 06, 2019, 07:15:56 PM
Exactly! There are a number of more or less acrobatic methods to do that, including the Declare (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1017) macro, but why bother? Just push the arguments in inverse order and call the function. If you are keen on complicated things: The jinvoke macro does exactly what you want, it's in \Masm32\MasmBasic\Res\JBasic.inc - only 325 lines and 6.8 kBytes.
Title: Re: Invoke an external procedure on a memory address?
Post by: 2B||!2B on May 06, 2019, 07:17:14 PM
Using Call must push all arguments in a reverse order and also makes code very unreadable.
Title: Re: Invoke an external procedure on a memory address?
Post by: 2B||!2B on May 06, 2019, 07:26:29 PM
Quote from: jj2007 on May 06, 2019, 07:15:56 PM
Exactly! There are a number of more or less acrobatic methods to do that, including the Declare (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1017) macro, but why bother? Just push the arguments in inverse order and call the function. If you are keen on complicated things: The jinvoke macro does exactly what you want, it's in \Masm32\MasmBasic\Res\JBasic.inc - only 325 lines and 6.8 kBytes.

Hi jj,

Thanks for the tip but i can not seem to find the 32bit version of this macro. Is this a 64bit only?
Title: Re: Invoke an external procedure on a memory address?
Post by: jj2007 on May 06, 2019, 07:41:35 PM
No, JBasic is a package that builds both 32- and 64-bit code from the same identical source. Simple example:

include \Masm32\MasmBasic\Res\JBasic.inc
Init           ; OPT_64 0      ; put 0 for 32 bit, 1 for 64 bit assembly
  PrintLine Chr$("This program was assembled with ", @AsmUsed$(1), " in ", jbit$, "-bit format.")
  jinvoke MessageBox, 0, Chr$("There are LoadLibrary and GetProcAddress under the hood"), Chr$("Just a test:"), MB_OK
EndOfCode


Output: This program was assembled with ml64 in 64-bit format. (plus the MsgBox, of course)

The macro works fine but it is damn complicated (inter alia, it checks the parameter count and type), and it requires also a tiny static library that cares for the LoadLibrary & GetProcAddress part. I am no longer working on it because I am not interested in 64-bit coding.
Title: Re: Invoke an external procedure on a memory address?
Post by: 2B||!2B on May 06, 2019, 08:03:21 PM
Thanks for the info. I couldn't compile your example though

Error A2102: Symbol not defined : iaApi

Its indeed sounds a complicated task. Might just stick with the SPROTO.
Title: Re: Invoke an external procedure on a memory address?
Post by: hutch-- on May 06, 2019, 08:22:55 PM
If you want it to look more high level, just write a macro for it. Push reverse order then call the procedure address. It is a trivial macro to write.
Title: Re: Invoke an external procedure on a memory address?
Post by: fearless on May 06, 2019, 08:42:08 PM
Lua_setglobalProto      TYPEDEF PROTO C luastate:DWORD, ptr_name:DWORD
Lua_setglobalPtr        TYPEDEF PTR Lua_setglobalProto

.data
F_Lua_setglobal         Lua_setglobalPtr 0 ; similar to defining F_Lua_setglobal as: F_Lua_setglobal DD 0
.code
...
; Assign the F_Lua_setglobal variable a function address value somewhere:
; mov eax, dwSomeAddress
; mov F_Lua_setglobal, eax
...
Invoke F_Lua_setglobal, g_lua, lpszFunctionName
...
Title: Re: Invoke an external procedure on a memory address?
Post by: aw27 on May 07, 2019, 12:37:01 AM
Try like this for a function with 2 ptr arguments:

lea eax, funcToCall
FuncProto typedef PROTO :ptr, :ptr
assume eax : ptr FuncProto
invoke eax, dest, src
assume eax:nothing
Title: Re: Invoke an external procedure on a memory address?
Post by: 2B||!2B on May 07, 2019, 08:31:30 AM
Quote from: hutch-- on May 06, 2019, 08:22:55 PM
If you want it to look more high level, just write a macro for it. Push reverse order then call the procedure address. It is a trivial macro to write.

Very good solution! i have not thought of it. Do you know how to make the arguments variable in Macro? because not all API's have the same number of arguments.

Quote from: fearless on May 06, 2019, 08:42:08 PM
Lua_setglobalProto      TYPEDEF PROTO C luastate:DWORD, ptr_name:DWORD
Lua_setglobalPtr        TYPEDEF PTR Lua_setglobalProto

.data
F_Lua_setglobal         Lua_setglobalPtr 0 ; similar to defining F_Lua_setglobal as: F_Lua_setglobal DD 0
.code
...
; Assign the F_Lua_setglobal variable a function address value somewhere:
; mov eax, dwSomeAddress
; mov F_Lua_setglobal, eax
...
Invoke F_Lua_setglobal, g_lua, lpszFunctionName
...


Thanks fearless for the example but this will also call the function from within the address space of the compiled exe. Exactly like SPROTO.

Quote from: AW on May 07, 2019, 12:37:01 AM
Try like this for a function with 2 ptr arguments:

lea eax, funcToCall
FuncProto typedef PROTO :ptr, :ptr
assume eax : ptr FuncProto
invoke eax, dest, src
assume eax:nothing

Nice work AW.
Example works, very good method.
Title: Re: Invoke an external procedure on a memory address?
Post by: hutch-- on May 07, 2019, 02:38:32 PM
I still don't know what you are after, "invoke" works with a normal address, the SPROTO macro works on addresses and you can manually use the standard PUSH/CALL Notation. What else are you after ?
Title: Re: Invoke an external procedure on a memory address?
Post by: Vortex on May 08, 2019, 03:49:37 AM
Hi 2B||!2B,

You can use a macro simulating invoke to call functions through pointers :

include  InvkReg.inc

.data

user32   db 'user32.dll',0
ApiFunc  db 'MessageBoxA',0

.data?

hModule  dd ?
mbox     dd ?

.code

start:

    invoke  LoadLibrary,ADDR user32
    mov     hModule,eax
    invoke  GetProcAddress,eax,ADDR ApiFunc
    mov     mbox,eax

;   mbox can be replaced with eax

   _invoke  mbox,0,"MessageBox test","Hello",MB_OK

    invoke  FreeLibrary,hModule
               
    invoke ExitProcess,0

END start

Title: Re: Invoke an external procedure on a memory address?
Post by: Vortex on May 08, 2019, 04:49:20 AM
Thanks AW for your macro. Combining your code, the prX macros from Windows.inc and some previous code :

_invoke MACRO p:REQ,args:VARARG

LOCAL counter,p2,tmp

    counter=0

    FOR param,<args>

        counter=counter+1

    ENDM

    IF counter EQ 0

        call p

    ELSE

        tmp TEXTEQU %(OPATTR(p))

        IF tmp EQ 42

            mov ecx,p
            p2  TEXTEQU <ecx>

        ELSE

            p2  TEXTEQU <p>

        ENDIF

        FuncProto TYPEDEF @CatStr(<pr>,%counter)

        ASSUME p2:PTR FuncProto

        invoke p2,args

        ASSUME p2:NOTHING

    ENDIF

ENDM


include  InvkReg.inc

.data

user32   db 'user32.dll',0
ApiFunc  db 'MessageBoxA',0

.data?

hModule  dd ?
mbox     dd ?

.code

start:

    invoke  LoadLibrary,ADDR user32
    mov     hModule,eax
    invoke  GetProcAddress,eax,ADDR ApiFunc
    mov     mbox,eax

;   mbox can be replaced with eax

   _invoke  mbox,0,CTXT("MessageBox test"),\
    CTXT("Hello"),MB_OK

    invoke  FreeLibrary,hModule
               
    invoke ExitProcess,0

END start
Title: Re: Invoke an external procedure on a memory address?
Post by: aw27 on May 08, 2019, 05:00:47 AM
OK. No problem.
This is a more "modern" way of doing the same:

   lea eax, myCalledFunction
   FuncProto typedef PROTO :ptr, :ptr
   invoke FuncProto ptr eax, dest, source