The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: tilman on September 20, 2011, 02:09:05 PM

Title: How to invoke a pointer to a function.
Post by: tilman on September 20, 2011, 02:09:05 PM
So I'm trying to invoke a pointer to a function, but I'm failing. Could somebody please help?

I'm storing the function pointer like so:

mov pFunction,offset Function

I can actually get the call to work by doing this:

call pFunction

But when I try this:

invoke pFunction

I get "error A2190: INVOKE requires prototype for procedure".

And if I try this:

invoke Function pFunction

I get "error A2206: missing operator in expression".

Any ideas?
Title: Re: How to invoke a pointer to a function.
Post by: dedndave on September 20, 2011, 02:51:33 PM
FuncName EQU <pr0 PTR pFunction>


        INVOKE  FuncName


if it has parameters, chage the "pr0" to "pr1", "pr2", and so on

Erol gives a nice example where he actually creates a jump table entry for it
http://www.masm32.com/board/index.php?topic=11772.msg89003#msg89003

although, the jump should not be required
Title: Re: How to invoke a pointer to a function.
Post by: tilman on September 20, 2011, 03:10:21 PM
Hi dedndave,

Thanks for the speedy reply. Although this assembles it doesn't do what I want it to, i.e. it doesn't call Function, it calls 'offset pFunction'. Or am I misunderstanding something?

Here is the whole listing:

.386
.model flat,stdcall
   option       casemap: none
   include      d:\masm32\include\windows.inc
   include      d:\masm32\include\kernel32.inc
   includelib    d:\masm32\lib\kernel32.lib
   
   Function proto
.const
   FuncName EQU <pr0 PTR pFunction>
.data?
   pFunction   dd      ?
.code
start:
   mov pFunction,offset Function
   INVOKE  FuncName
   
   push   0
   call   ExitProcess
   
Function proc
   ret
Function endp
end start
Title: Re: How to invoke a pointer to a function.
Post by: dedndave on September 20, 2011, 03:23:54 PM
no - my mistake
it looks like the jump is required, although Erol's example may be dereferenced

let me play with it for a minute....
Title: Re: How to invoke a pointer to a function.
Post by: dedndave on September 20, 2011, 03:54:36 PM
well - i know there is a better way to do it - lol
but, for now, use Erol's method
i will play with it later today - or someone else will show us before then   :P
Title: Re: How to invoke a pointer to a function.
Post by: tilman on September 20, 2011, 04:01:29 PM
Thanks a lot for your help, I just found the answer here

http://webster.cs.ucr.edu/Page_TechDocs/MASMDoc/ProgrammersGuide/Chap_07.htm

although it seems a bit crackpot to me...

This is what you have to do:

.386
.model flat,stdcall
option casemap: none
include d:\masm32\include\windows.inc
include d:\masm32\include\kernel32.inc
includelib d:\masm32\lib\kernel32.lib

FUNCPROTO       TYPEDEF PROTO
FUNCPTR         TYPEDEF PTR FUNCPROTO
.data?
pFunction FUNCPTR ?
.code
start:
mov pFunction,offset Function
mov eax,offset pFunction
invoke FUNCPTR ptr [eax]

push 0
call ExitProcess

Function proc
ret
Function endp
end start
Title: Re: How to invoke a pointer to a function.
Post by: dedndave on September 20, 2011, 04:33:32 PM
well - that is less than ideal - you don't want to do all that every time - lol

the problem i was having is, there is no near absolute direct JMP instruction
but, with minimal effort, we can make a relative JMP work for us
we just have to add a SUB instruction to make the address relative

        .DATA

FuncBranch db 0E9h
pFunc      dd ?

FuncName    EQU <pr0 PTR FuncBranch>

        .CODE

;EAX = FunctionAddress

        sub     eax,offset pFunc+4
        mov     pFunc,eax

;then, to INVOKE the function...

        INVOKE  FuncName


you may be able to eliminate the SUB like this...

        mov     pFunc,offset Function-offset pFunc-4
Title: Re: How to invoke a pointer to a function.
Post by: dedndave on September 20, 2011, 04:39:16 PM
        .DATA

FuncBranch db 0E9h
pFunc      dd ?

FuncName    EQU <pr0 PTR FuncBranch>

        .CODE

;initialization

        mov     pFunc,offset Function-offset pFunc-4

;then, to INVOKE the function...

        INVOKE  FuncName
Title: Re: How to invoke a pointer to a function.
Post by: dedndave on September 20, 2011, 04:41:41 PM
because you can grab "offset Function", this should work - with no init code...
        .DATA

FuncBranch db 0E9h
pFunc      dd offset Function-offset pFunc-4

FuncName    EQU <pr0 PTR FuncBranch>

        .CODE

;then, to INVOKE the function...

        INVOKE  FuncName
Title: Re: How to invoke a pointer to a function.
Post by: dedndave on September 20, 2011, 04:43:37 PM
i am not sure why you are doing all this   :lol
unless you want to be able to change the function address in code
if that's the case, use the previous 2 posts

Function PROTO

        .CODE

        INVOKE  Function
;
;
;
Function PROC
        ret
Function ENDP
Title: Re: How to invoke a pointer to a function.
Post by: tilman on September 20, 2011, 05:07:39 PM
What I actually want to do is pass a callback to a function. (Isn't that a common task?) The example here is just simplification which demonstrated my problem.

I actually discovered another simplification of the official solution:

Instead of

mov pFunction,offset Function
mov eax,offset pFunction
invoke FUNCPTR ptr [eax]


i can just do

mov pFunction,offset Function
invoke FUNCPTR ptr pFunction


Now my main complaint is that I may have to define function prototypes twice. Oh vell...

Some questions about your solution:

a) Where does the magic 0e9h come from?
b) Does your code still do type checking on parameters?

Cheers!
Title: Re: How to invoke a pointer to a function.
Post by: dedndave on September 20, 2011, 05:16:38 PM
well - type checking is a matter of the "prN" definitions in windows.inc (or wherever they are defined)
for most 32-bit applications, they are always DWORD's of some sort

i am assuming that you have more than 0 parameters for this function
otherwise, a simple CALL would be easier

so - you want to pass the address of a callback and store it in a global variable ?
Title: Re: How to invoke a pointer to a function.
Post by: tilman on September 20, 2011, 05:31:05 PM
Quotewell - type checking is a matter of the "prN" definitions in windows.inc (or wherever they are defined)
for most 32-bit applications, they are always DWORD's of some sort

I actually switched to WinInc, because MASM32 was missing some COM structures. They use all sorts of types... ;)

Quoteso - you want to pass the address of a callback and store it in a global variable ?

That is correct. I've got the caller in a seperate file and I want to keep it general, so it doesn't know what to call at assemble time.
Title: Re: How to invoke a pointer to a function.
Post by: Vortex on September 20, 2011, 05:33:47 PM
Hi tilman,

You can also use a macro simulating invoke :


include     FuncPointer.inc

.data

capt        db 'Hello',0
message     db 'Function invoked through pointer',0


.data?

pFunction   dd ?


.code

start:

    mov     pFunction,OFFSET Function

    _invoke pFunction,ADDR message

    invoke  ExitProcess,0


Function PROC msg:DWORD

    invoke  MessageBox,0,msg,ADDR capt,MB_OK
    ret

Function ENDP


END start


_invoke mimics Masm's internal macro invoke
Title: Re: How to invoke a pointer to a function.
Post by: tilman on September 20, 2011, 05:49:33 PM
Hey Vortex,

Thanks for that. I'm not that hot on macros (yet), but does the macro check that the correct number and type of parameters were passed? Because, as I understand it, that's the whole point of using invoke over call (and yes, I tried to get by with just call and I failed and invoke saved my bacon  :bg)
Title: Re: How to invoke a pointer to a function.
Post by: Vortex on September 20, 2011, 05:56:23 PM
Hi tilman,

The _invoke macro does not perform any checking. Assemblers SolAsm and Fasm don't do any type of checking too.
Title: Re: How to invoke a pointer to a function.
Post by: tilman on September 20, 2011, 06:10:48 PM
Oh dear, let's up I won't have to use them any time soon ;0
Title: Re: How to invoke a pointer to a function.
Post by: dancho on September 20, 2011, 06:20:07 PM
Fasm does checking the count of parameters in procedure calls if you include extended headers ( win32axp.inc or win32wxp.inc )
in your file...

Title: Re: How to invoke a pointer to a function.
Post by: drizz on September 21, 2011, 08:35:04 AM
Hi,

Here are some examples:
http://www.masm32.com/board/index.php?topic=8134.msg59391#msg59391 (look here first)
http://www.masm32.com/board/index.php?topic=11110.msg82041#msg82041
http://www.masm32.com/board/index.php?topic=5299.msg39702#msg39702
http://www.masm32.com/board/index.php?topic=5302.msg39704#msg39704

Quote from: tilman on September 20, 2011, 04:01:29 PM
Thanks a lot for your help, I just found the answer here
...
I actually discovered another simplification of the official solution:
++ for answering your question by yourself

Quote from: tilman on September 20, 2011, 05:31:05 PMI actually switched to WinInc
+ for using WinInc

Quote from: tilman on September 20, 2011, 05:49:33 PMBecause, as I understand it, that's the whole point of using invoke over call (and yes, I tried to get by with just call and I failed and invoke saved my bacon :bg)
+ for stating why is masm/jwasm better than other assemblers

Quote from: tilman on September 20, 2011, 06:10:48 PM
Oh dear, let's up I won't have to use them any time soon ;0
+  :lol

Thats 5 pluses from me  :)  :U
Title: Re: How to invoke a pointer to a function.
Post by: ToutEnMasm on September 21, 2011, 09:07:01 AM

To use invoke with a pointer on a proc,you need just some declare
Quote
   TestProc PROTO  :DWORD    

   Pfunction TYPEDEF PROTO   :DWORD
   Ffunction TYPEDEF PTR Pfunction
   function TEXTEQU <Ffunction ptr ADRfunction>
.data
ADRfunction dd TestProc
.code
.....
                invoke function,NULL   
here is the function who is call
Quote
;################################################################
TestProc PROC  arg:DWORD
         Local  retour:DWORD
         mov retour,1
   
   invoke MessageBox,NULL,SADR("Succeed"),SADR("call to function"),MB_OK

FindeTestProc:
         mov eax,retour
         ret
TestProc endp