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?
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
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
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....
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
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
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
.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
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
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
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!
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 ?
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.
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
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)
Hi tilman,
The _invoke macro does not perform any checking. Assemblers SolAsm and Fasm don't do any type of checking too.
Oh dear, let's up I won't have to use them any time soon ;0
Fasm does checking the count of parameters in procedure calls if you include extended headers ( win32axp.inc or win32wxp.inc )
in your file...
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
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