The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: sinsi on August 17, 2006, 06:02:05 AM

Title: Using _imp__ in a macro with INVOKE
Post by: sinsi on August 17, 2006, 06:02:05 AM
I wanted to use "mov esi,FindWindow" and then "call esi" a few times...
After much wailing and gnashing of teeth I made the following macro

xyzzy macro n,a,c
    local s,t,u,x,y
    y textequ <>
    ifnb <c>
     y textequ < :DWORD>
     rept (c/4)-1
      y catstr y,<,:DWORD>
     endm
    endif
    t CATSTR <pr>,<n>
    t TYPEDEF PROTO STDCALL y
    u CATSTR <P>,<n>
    u TYPEDEF PTR t
    s CATSTR <_imp__>,<n>,<a>,<@>,<c>
    EXTERNDEF s:u
    n TEXTEQU <s>
endm

So all I do in my windows.inc is

xyzzy GetClientRect,,8
xyzzy GetCommandLine,A,0

and I can use "INVOKE GetCommandLine"

Is this a good way of doing it?
The main reason was to do

push 0
jmp ExitProcess

instead of

INVOKE ExitProcess,0

which gets assembled as

push 0
call ExitProcess
ret

at the end of my main proc...
And it saves a byte here and there.

Then there is

push 0
call GetModuleHandle

which gets translated to

push 0
call jmp_GetModuleHandle
...
jmp_GetModuleHandle PROC
  jmp _imp__GetModuleHandleA@4
jmp_GetModuleHandle ENDP

which seems to be a bit indirect as well as wasting bytes...
Title: Re: Using _imp__ in a macro with INVOKE
Post by: ToutEnMasm on August 17, 2006, 09:25:06 AM
Hello,
Why don't use the FUNC macro


      FUNC MACRO parameters:VARARG
        invoke parameters
        EXITM <eax>
      ENDM


and then


mov esi,FUNC (FindWindow,addr ClassName,addr WindowName )
;return the handle of the window


                 ToutEnMasm

Title: Re: Using _imp__ in a macro with INVOKE
Post by: Boucly on August 17, 2006, 10:37:30 AM
ToutEnMasm, I think sinsi was talking about having to call API functions through jmp instructions. I was confused about that myself too. I found something on Google about it, but doesn't help me much... Calling Win32 API Routines from HLA (http://webster.cs.ucr.edu/Page_win32/win32API.html) Can someone explain what it means in plainner English?

Boucly
Title: Re: Using _imp__ in a macro with INVOKE
Post by: Tedd on August 17, 2006, 12:52:17 PM
What Sinsi is actually talking about:
When you build an exe (using ml and microsoft's link) calls to api functions are translated into a call to an-indirect-jump-to-the-function.
What he would prefer is to cut out this indirection and be able to either call the api function directly, or get its address and call it indirectly through a register (for a sequence of many calls to the same function.)

Sinsi:
Firstly, the reason it's done like this is down to the way the exe is built; the assembler doesn't know where the api functions will be so it produces a table for the linker to fix when it does its stuff. I seem to remember that there is a way around it, without needing to play around with a heap of macros, but I don't remember what that is off the top off my head.
You should also keep in mind that since the api functions come from dlls, and dlls are dynamic, the function entry-points themselves are not at known addresses until after your exe has been loaded. So some indirection is necessary (therefore, so is the table) otherwise the loading process could not be dynamic. However, this should not prevent you from obtaining the address out of the table (it's filled in before your program starts execution) and using the address directly. Though you wouldn't want to jmp to these functions, otherwise where would they return to?
Title: Re: Using _imp__ in a macro with INVOKE
Post by: Boucly on August 17, 2006, 01:07:45 PM
Tedd,
Calling Win32 API Routines from HLA (http://webster.cs.ucr.edu/Page_win32/win32API.html) The page that this link goes to says something about turning the pointer to the API instructions into an extern thingy to solve the problem. What does that mean?
Boucly
Title: Re: Using _imp__ in a macro with INVOKE
Post by: Tedd on August 17, 2006, 01:37:29 PM
Quote from: Boucly on August 17, 2006, 01:07:45 PM
The page that this link goes to says something about turning the pointer to the API instructions into an extern thingy to solve the problem. What does that mean?

It's how to solve the problem from HLA, using HLA specific features. What it means is that, normally, functions are called directly (you already know their address). But for api functions, you don't know the address in advance, so you have to call them indirectly, and have the address filled-in by the loader when it loads your exe. Specifying the api function as 'extenal' causes HLA to make the call indirect (you don't know the address of an external function in advance), and so it fixes the calls to the api functions.
(This is may not be precisely what it talks about - I only browsed the page, I'm not going to read it all :P)
Title: Re: Using _imp__ in a macro with INVOKE
Post by: ToutEnMasm on August 17, 2006, 01:52:33 PM

Masm use STANDARD call (stack return inchanged), HLA pascal call.See the agner site for explanation on this differents call.
For the first question, If it is to make a direct call (a jmp is not enough,there is always something to return) linking dynamically is needed.Use getprocadress.
                     
Title: Re: Using _imp__ in a macro with INVOKE
Post by: ToutEnMasm on August 17, 2006, 02:09:19 PM
HLA with is pascal call seem to have a problem
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore98/html/_core___stdcall.asp
                                ToutEnMasm

Obsolete Calling Conventions
Home |  Overview |  How Do I

The __pascal, __fortran, and __syscall calling conventions are no longer supported. You can emulate their functionality by using one of the supported calling conventions and appropriate linker options.

WINDOWS.H now supports the WINAPI macro, which translates to the appropriate calling convention for the target. Use WINAPI where you previously used PASCAL or __far __pascal.
Title: Re: Using _imp__ in a macro with INVOKE
Post by: Boucly on August 17, 2006, 02:19:03 PM
Tedd, Appreciate it and ToutEnMasm, I finally understood. But how does the API functions know where to return to even if I don't use a direct JMP. I mean, where is the pointer to the original calling instructions stored: in the stack, register?

Boucly
Title: Re: Using _imp__ in a macro with INVOKE
Post by: mnemonic on August 17, 2006, 02:27:34 PM
Quote from: Boucly on August 17, 2006, 02:19:03 PM
I mean, where is the pointer to the original calling instructions stored: in the stack, register?

You may have a further look at the CALL instruction.
CALL pushes EIP onto the stack and then JMPs to the label given to CALL. On the other side RET pops the value back to EIP and the execution continues there. That is the main reason why you have to watch out that the stack is always balanced when fiddling between procedures and functions. If your stack is not balanced you just JMP back to an "random" address and Windows will close down your App (or your Real-Mode OS crashes, DOS e.g.).
Title: Re: Using _imp__ in a macro with INVOKE
Post by: Boucly on August 17, 2006, 02:34:59 PM
If the ret function pop the next value in the stack into EIP (I thought it was forbidden to change EIP), doesn't that points to the instruction that called the function in the first place?

Boucly
Title: Re: Using _imp__ in a macro with INVOKE
Post by: ToutEnMasm on August 17, 2006, 02:51:32 PM

The better maner to see how it's work is to used a debugger.
First,follow a call (or invoke) to a proc in your source code and  then follow the call to a library function,debug it step by step.
You can also disassemble a little code that you have made with this two forms off call.
You will see that for calling a function in the library,the linker create a list at the end of the code.But the result is the same.
                                     ToutEnMasm
Title: Re: Using _imp__ in a macro with INVOKE
Post by: Boucly on August 17, 2006, 02:55:13 PM
Okay, thank you very much everyone.

With gratitude, Boucly
Title: Re: Using _imp__ in a macro with INVOKE
Post by: mnemonic on August 17, 2006, 03:10:08 PM
Boucly,

don't take my words as rules that are set in stone. I just wanted to keep it simple stupid. :wink
All I did was breaking the instructions CALL and RET down into instructions you might know (PUSH, JMP and POP).
And for sure you cannot PUSH or POP EIP manually, but that is the thing CALL and RET do internally.
And yes, the address that gets PUSHed is the address of the instruction after the RET.

But anyway, my first hint was to have a deeper look at the documentation for CALL (Intel Docs and the like), because that is the bible where CPUs live after.  :wink
Title: Re: Using _imp__ in a macro with INVOKE
Post by: Boucly on August 17, 2006, 03:54:17 PM
Okay. Mnemonic.

I have the Intel documents (http://www.intel.com/design/Pentium4/manuals/253665.htm). I will read every word. Its not like I won't have time to read a 4 × 500 pages of .pdf file.  :P

Anyway, this is what the manual said:

QuoteRET—Return from Procedure

Description

Transfers program control to a return address located on the top of the stack. The address is
usually placed on the stack by a CALL instruction, and the return is made to the instruction that
follows the CALL instruction.

The optional source operand specifies the number of stack bytes to be released after the return
address is popped; the default is none. This operand can be used to release parameters from the
stack that were passed to the called procedure and are no longer needed. It must be used when
the CALL instruction used to switch to a new procedure uses a call gate with a non-zero word
count to access the new procedure. Here, the source operand for the RET instruction must
specify the same number of bytes as is specified in the word count field of the call gate.

I should have read before I post. Sorry.

Last question, what is an opcode?

Boucly

Edit: it is mentioned in the manual
Title: Re: Using _imp__ in a macro with INVOKE
Post by: ToutEnMasm on August 17, 2006, 04:55:28 PM
opcodes are Hexadecimales and go with there Mnemonics (text instructions),you have the complet list of the instructions of the microprocessor in a help file in the masm32 package.
Intel Hex Opcodes And Mnemonics
                                        ToutEnMasm

Title: Re: Using _imp__ in a macro with INVOKE
Post by: Vortex on August 17, 2006, 05:07:20 PM
Sinsi,

If I undestand you correctly, you would like to use direct calls. Hutch's masm32 provides the l2extia tool :

QuoteL2EXTIA.EXE

This is an alternative method of creating include files that can be used
with MASM32. It produces include files in the EXTERNDEF format for system
DLL imports. This method allows direct calls to imported functions rather
that the lookup table that is the native format for MASM 32 bit EXE files.

C:\masm32\tools\l2extia
Title: Re: Using _imp__ in a macro with INVOKE
Post by: sinsi on August 18, 2006, 10:54:34 AM
Wow. Thanks for the replies.

As far as JMP goes, I only use it for ExitProcess (hey, it saves a RET byte).

My windows.inc works just fine, all I was wondering about was the main macro, because
it seems to be a bit of a mess (well, beers and code mix so well until the next day...)

Title: Re: Using _imp__ in a macro with INVOKE
Post by: dedndave on June 06, 2009, 10:38:00 AM
i realize this is a very old thread, but i am using it for reference and want it in my list

this code works

        mov     esi,labelA-4       ;get the relative address from INVOKE
        mov     esi,labelA[esi+2]  ;get the address part of the indirect JMP
        mov     eax,[esi]          ;get the API target refered to in the JMP
        call    eax
        exit

        INVOKE  GetCurrentProcess
labelA  label   dword