hello, i didn't like the code masm generates with invoke, if the routine is in an external dll (kernel32, user32,...). The source code, say

      invoke ExitProcess,eax

is translated to:

      push   eax
      call   ExitProcess

so far, so good. But the linker adds to this code:

ExitProcess:
      jmp   dword ptr [_imp__ExitProcess@4]
So every call to a win32 function goes trough 2 levels of indirection, which is one too much in my eyes. Therefore I have created a macro @invoke:

@invoke macro name:req,parms:vararg
        i = 0
fparms  catstr <>
        for parname,
        i = i + 4
fparms  catstr fparms,<,:dword>
        endm
ii      textequ %i
iatname catstr <_imp__>,,<@>,ii
t&name& typedef proto stdcall fparms
externdef iatname:ptr t&name&
        invoke iatname,parms
        endm
Now the example looks like:

      @invoke ExitProcess,eax

and the generated code is:
  
      push   eax
      call   dword ptr [_imp__ExitProcess@4]

and the linker will add nothing to this code. The macro should work with all Win32 functions This message was edited by japheth, on 7/3/2001 4:32:18 AM
Posted on 2001-07-03 04:28:00 by japheth
Wayne Radburn shows another way to do it, by using a different style of API declaration (not PROTO): www.magma.ca/~wjr/Skeleton.zip
Posted on 2001-07-03 05:06:00 by Larry Hammick
I have forgotten about common redefinitions in MASM32-include files to get rid of the suffix like: GetProfileString equ so in the macro there should be a evaluation of the procedure name first. The corrected macro looks like:

@invoke macro name:req,parms:vararg
local i,fparms,ii,iatname,tname
        i = 0
fparms  catstr <>
        for parname,
        i = i + 4
fparms  catstr fparms,<,:dword>
        endm
ii      textequ %i
tname   textequ <&name&>
iatname catstr <_imp__>,tname,<@>,ii
t&name& typedef proto stdcall fparms
externdef iatname:ptr t&name&
        invoke iatname,parms
        endm
Posted on 2001-07-03 07:15:00 by japheth
Japeth, I tested the macro and as long as you don't try and use ADDR and use line continuations with "\" it works fine. Compliments on a clever macro. I played with the EXTERDEF directive for a while and found there is a way to get standard INVOKE syntax to work with DLL functions.

    API equ 

    pr2 API :DWORD,:DWORD

    externdef _imp__LoadIconA@8:PTR pr2
    LoadIcon equ <_imp__LoadIconA@8>
Then use the normal "invoke"

      invoke LoadIcon,hInstance,500    ; icon ID
      mov hIcon, eax
This approach requires creating a set of include files in this format but I think it can be done. Regards, hutch@pbq.com.au
Posted on 2001-07-03 08:56:00 by hutch--
Where am i supposed to put this macro so that masm uses this one instead of its default 'invoke' code? Why dont u submit this code on icz's site so that it can be the 'standard' invoke macro instead of the default one?
Posted on 2001-07-03 09:09:00 by MovingFulcrum
Of course, there is always one more bug in your code. The macro works fine until you invoke a procedure without any parameters (like GetCommandLine). So there is a modification needed:

@invoke macro name:req,parms:vararg
local i,fparms,ii,iatname,tname
        i = 0
fparms  catstr <>
        for parname,
        i = i + 4
fparms  catstr fparms,<,:dword>
        endm
ii      textequ %i
tname   textequ <&name&>
iatname catstr <_imp__>,tname,<@>,ii
t&name& typedef proto stdcall fparms
externdef iatname:ptr t&name&
ifnb 
        invoke iatname,parms
else
        invoke iatname
endif
        endm
to MovingFulcrum: put the macro at the start of your code and change all related invoke's to @invoke. japheth This message was edited by japheth, on 7/3/2001 9:23:07 AM
Posted on 2001-07-03 09:16:00 by japheth
Guys, Elicz did a wonderful job wit well written macros. I'm using them everyday and they just work fine: EliAsm
Posted on 2001-07-03 17:43:00 by Amokila
If no one has heard me before (:D), I'd like to second Amokila's comment.
Posted on 2001-07-04 00:26:00 by bitRAKE
The only problem I can see with the method Japheth is using is that it has no type checking. His macro works and the code that is built does what he set out to do but where the PROTO in the macro has its parameters determined by the number of parameters in the function call, an error in the parameter count will be assembled with no easy way to check it when it crashes. It is no big deal to get a complete list of decorated names from the Microsoft Libraries and build a new set of include files based on the method the Japheth has used to directly call the functions. While the performance gains are dubious, the format is flexible in that it can be adapted to handle DLLs that do not have a library attached to them. This method uses "invoke" with the normal type checking and conveniences like ADDR so the end result is a lot more reliable and easier to use. Regards, hutch@pbq.com.au
Posted on 2001-07-04 03:04:00 by hutch--
Hutch, I keep forgetting that ADDR is lacking in Elicz's implementation. Also, I'll certainly agree that it's a few steps away from the standard 'invoke' - it takes a little practice to get used to all the macro names.
Posted on 2001-07-04 03:34:00 by bitRAKE
hutch, I would also prefer to extend the tool (L2INC?) which generates the masm32 include files . The "macro solution" has some disadvantages, as you have already stated. japheth
Posted on 2001-07-04 03:55:00 by japheth