The MASM Forum

General => The Campus => Topic started by: LordAdef on January 14, 2025, 04:19:06 AM

Title: invoking an offset procedure
Post by: LordAdef on January 14, 2025, 04:19:06 AM
Hi guys,

I've got a struct, and I saved a proc offset in order to call it:
mov foo.init, offset blablabla

All is good and I can call the proc:
call foo.init

But I want to use invoke and send values. Prototyping the proc doesn't help:
invoke foo.init, 12, 34, 23

Any ideas?
Cheers
Alex

ps: I re-introduced myself in the welcome forum
Title: Re: invoking an offset procedure
Post by: Villuy on January 14, 2025, 05:45:12 AM
invoke must have name of proc to check params. No way.
Title: Re: invoking an offset procedure
Post by: Vortex on January 14, 2025, 06:04:15 AM
Hi LordAdef,

You can try this one :

.386
.model flat,stdcall
option casemap:none

include     \masm32\include\windows.inc
include     \masm32\include\kernel32.inc
includelib  \masm32\lib\kernel32.lib

.data

user32      db 'user32.dll',0
function    db 'MessageBoxA',0
caption     db 'Hello!',0
message     db 'MessageBoxA called via pointer',0

.data?

hLib dd ?
pMessageBox dd ?

.code

start:

    invoke  LoadLibrary,ADDR user32
    mov     hLib,eax

    invoke  GetProcAddress,eax,ADDR function
    mov     pMessageBox,eax

    mov     edx,pMessageBox
    invoke  pr4 PTR edx,0,ADDR message,\
            ADDR caption,0
           
    invoke  FreeLibrary,hLib
    invoke  ExitProcess,0

END start

    mov     edx,pMessageBox
    invoke  pr4 PTR edx,0,ADDR message,\
            ADDR caption,0

edx holds the pointer to MessageBoxA, you can specify the prX macro to call a function through a register.

Reading \masm32\include\windows.inc :

    ArgCount MACRO number
      LOCAL txt
      txt equ <typedef PROTO :DWORD>
        REPEAT number - 1
          txt CATSTR txt,<,:DWORD>
        ENDM
      EXITM <txt>
    ENDM

    pr0  typedef PROTO
    pr1  ArgCount(1)
    pr2  ArgCount(2)
   .
   .
    pr24 ArgCount(24)
    pr25 ArgCount(25)

If you want to call a function taking three parameters :

invoke  pr3 PTR ecx,param1,param2,param3
Title: Re: invoking an offset procedure
Post by: fearless on January 14, 2025, 06:36:47 AM
Declare your struct with defined pointers, which point to prototypes, like so:

Foo_Init_Proto TYPEDEF PROTO dwParam1:DWORD, dwParam2:DWORD, dwParam3:DWORD

Foo_Init_Ptr TYPEDEF PTR Foo_Init_Proto

Foo STRUCT
    Init Foo_Init_Ptr 0
Foo ENDS

Then

Invoke Foo.Init, 1, 2, 3
or

lea ebx, Foo
Invoke [ebx].Foo.Init, 1, 2, 3

Also, remember to update the Foo struct with address of Init at run time,  before calling it, or you can try setting it to an offset at compile time (not tried that myself)
Title: Re: invoking an offset procedure
Post by: LordAdef on January 14, 2025, 07:34:36 AM
Hi Fearless,

It worked beautifully!!!

Thank you so much. Saved the day!

Thanks everyone for chiming in too!
Title: Re: invoking an offset procedure
Post by: fearless on January 14, 2025, 07:46:16 AM
Nice! did u use an offset at compile time to point to a function (offset to proc), or did u update the struct at runtime with the address of function?:


lea eax, FuncInit
mov Foo.Init, eax
Title: Re: invoking an offset procedure
Post by: LordAdef on January 14, 2025, 07:57:32 AM
Quote from: fearless on January 14, 2025, 07:46:16 AMNice! did u use an offset at compile time to point to a function (offset to proc), or did u update the struct at runtime with the address of function?:


lea eax, FuncInit
mov Foo.Init, eax

Panel STRUCT 4
    hdc     dd  ?
    init    proc_Ptr  ?  <------- here
Panel ends


I use offset:
mov panel1.init, offset test_proc

calling:
invoke panel1.init, 10

Title: Re: invoking an offset procedure
Post by: HSE on January 14, 2025, 02:00:46 PM
But that only have sense if all offsets are from procedures with same number and type of arguments.  ??
Title: Re: invoking an offset procedure
Post by: jj2007 on January 14, 2025, 09:55:22 PM
include \masm32\include\masm32rt.inc

myvoke MACRO destination, args:VARARG
Local arg$, isL, isR, push$
  arg$ EQU <#>
  for arg, <args>
    arg$ CATSTR <arg>, <#>, arg$
  endm
  isL=0
  While 1
isR=isL+1
isL INSTR isR, arg$, <#>
IFE isL-isR
EXITM
endif
push$ SUBSTR arg$, isR, isL-isR
push push$
  ENDM
  call destination
ENDM

.code
MyTest:
  mov ecx, [esp+4]
  mov edx, [esp+8]
  invoke MessageBox, 0, ecx, edx, MB_OK
  retn 8

start:
  mov edx, offset MyTest
  myvoke edx, chr$("Seems to work"), chr$("That's the title")
  exit

end start
Title: Re: invoking an offset procedure
Post by: LordAdef on January 15, 2025, 05:38:42 AM
Quote from: HSE on January 14, 2025, 02:00:46 PMBut that only have sense if all offsets are from procedures with same number and type of arguments.  ??
Hi HSE!! it's been a long time.

Sure, but it fits well with the design I intend to implement. And it would not be expensive to define more protos to fulfill other procs. 
Title: Re: invoking an offset procedure
Post by: LordAdef on January 15, 2025, 05:57:48 AM
Quote from: jj2007 on January 14, 2025, 09:55:22 PMinclude \masm32\include\masm32rt.inc

myvoke MACRO destination, args:VARARG
Local arg$, isL, isR, push$
  arg$ EQU <#>
  for arg, <args>
    arg$ CATSTR <arg>, <#>, arg$
  endm
  isL=0
  While 1
isR=isL+1
isL INSTR isR, arg$, <#>
IFE isL-isR
EXITM
endif
push$ SUBSTR arg$, isR, isL-isR
push push$
  ENDM
  call destination
ENDM

.code
MyTest:
  mov ecx, [esp+4]
  mov edx, [esp+8]
  invoke MessageBox, 0, ecx, edx, MB_OK
  retn 8

start:
  mov edx, offset MyTest
  myvoke edx, chr$("Seems to work"), chr$("That's the title")
  exit

end start

Hi Johen!
I loved the "myvoke" name !