Hi friends,
Here is a macro example simulating invoke, the attachment contains an example.
_invoke MACRO funcname:REQ,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15,p16,p17,p18,p19,p20
local pos,counter
counter=0
FOR arg,<p20,p19,p18,p17,p16,p15,p14,p13,p12,p11,p10,p9,p8,p7,p6,p5,p4,p3,p2,p1>
IFNB <arg>
counter=counter+1
pos=@InStr(1,arg,<ADDR>) OR @InStr(1,arg,<addr>) OR @InStr(1,arg,<Addr>)
IF pos
IF (OPATTR(@SubStr(arg,%pos+5))) EQ 98
lea eax,@SubStr(<arg>,%pos+5)
push eax
ELSE
push OFFSET @SubStr(<arg>,%pos+5)
ENDIF
ELSE
push arg
ENDIF
ENDIF
ENDM
call funcname
ENDM
The variable counter holds the number of passed parameters.
[attachment deleted by admin]
Very nice.
Just to be annoying - how about a warning if eax gets over-written upon the lea? :bdg
Quote from: Tedd on December 22, 2004, 04:37:30 PM
Very nice.
Just to be annoying - how about a warning if eax gets over-written upon the lea? :bdg
Yes, you can insert the directive
echo to output warnings.
Just curious. What would be the advantage of using such a macro instead of the invoke statement?
Raymond
Quote from: raymond on December 23, 2004, 01:32:52 AM
Just curious. What would be the advantage of using such a macro instead of the invoke statement?
Raymond
The current invoke macro does not support calling a pointer to an address. If you have your own macro, you can modify it to support that.
Thanks
Raymond
If you overwrite completely, even you can automatically do the way how goasm (as I know) pass the addresses of locals :).
Here is my version of a INVOKE macro. Ratch
;*******************************************************************************
; @ArgRev : MACRO FUNCTION *
; *
; Called by: @ArgRev(P1,P2:VARARG) *
; *
; Returns : VARARG list in reverse order *
;-------------------------------------------------------------------------------
@ArgRev MACRO P1,P2:VARARG
LOCAL TXT
TXT TEXTEQU <P1>
FOR ARG,<P2>
TXT CATSTR <ARG>,<!,>,TXT
ENDM
EXITM <TXT>
ENDM
;*******************************************************************************
PUSHIT MACRO P1:VARARG
FOR arg,<P1>
PUSH arg
ENDM
ENDM
;*******************************************************************************
RPUSHIT MACRO P1:VARARG
%PUSHIT @ArgRev(P1)
ENDM
;-------------------------------------------------------------------------------
INVOKIT MACRO P1:REQ,P2:VARARG
IFNB <P2>
RPUSHIT P2
ENDIF
CALL P1
ENDM
;-
Quote from: Ratch on December 23, 2004, 04:44:51 AM
Here is my version of a INVOKE macro. Ratch
;*******************************************************************************
; @ArgRev : MACRO FUNCTION *
; *
; Called by: @ArgRev(P1,P2:VARARG) *
; *
; Returns : VARARG list in reverse order *
;-------------------------------------------------------------------------------
@ArgRev MACRO P1,P2:VARARG
LOCAL TXT
TXT TEXTEQU <P1>
FOR ARG,<P2>
TXT CATSTR <ARG>,<!,>,TXT
ENDM
EXITM <TXT>
ENDM
;*******************************************************************************
PUSHIT MACRO P1:VARARG
FOR arg,<P1>
PUSH arg
ENDM
ENDM
;*******************************************************************************
RPUSHIT MACRO P1:VARARG
%PUSHIT @ArgRev(P1)
ENDM
;-------------------------------------------------------------------------------
INVOKIT MACRO P1:REQ,P2:VARARG
IFNB <P2>
RPUSHIT P2
ENDIF
CALL P1
ENDM
;-
I'm not trying to be sarcastic but I don't like the macro name PUSHIT because it looks like.........well you can see what I mean.
To Robert Collins,
The MACRO's name is easily changed if it offends you. The complement to PUSHIT is POPIT. What do you think about the conciseness of the INVOKIT MACRO? Ratch
Quote from: Ratch on December 23, 2004, 06:09:47 AM
To Robert Collins,
The MACRO's name is easily changed if it offends you. The complement to PUSHIT is POPIT. What do you think about the conciseness of the INVOKIT MACRO? Ratch
The name is OK. I was just kidding about saying I dont like it. Its just that when I looked at it the last four letters stood out more profoundly. I have seen many names used in programming that just happen to fall into this category. I only said that because I know how some of the programmers where I work would use that name in their normal daily activities. Anyway, it's perfectly fine with me.
Hi Raymond,
With a macro simulating invoke, you don't need define function prototypes. A simple extrern directive is enough to declare an external function.
Quote
The current invoke macro does not support calling a pointer to an address. If you have your own macro, you can modify it to support that
This is not exactly the case, it all in the prototype. Quoting directly from the "macros.asm" file in MASM32,
comment * -----------------------------------------------------------------
NOTES on DDPROTO macro
This macro is for producing prototypes for functions where the start
address is known and the parameter count is known. It requires a named
DWORD sized entry in the .DATA or .DATA? section which has the start
address written to it before the function is called.
EXAMPLE:
.data?
user32_msgbox dd ? ; << The named variable
msgbox DDPROTO(user32_msgbox,4) ; create prototype
This is expanded to the following. The TYPEDEF refers to
the macro "pr4" in the WINDOWS.INC file.
pt4 TYPEDEF PTR pr4
msgbox equ <(TYPE pt4) PTR user32_msgbox>
The address must be written to the DWORD variable before it can
be called. This can be LoadLibrary/GetProcAddress or it can be
an address recovered from a virtual table in a DLL or any other
viable means of obtaining the start address of a function to call.
invoke msgbox,hWnd,ADDR message_text, ADDR title_text,MB_OK
----------------------------------------------------------------- *
If you have the start address you want to use and know the number of parameters, you create a prototype for it using this or a similar macro then use INVOKE like normal.
Here is a situation where an alternate invoke macro can be used
Tricks to use Masm with import libraries created directly from DLLs. These are:
i) Creating import libraries containing function names with no decoration
ii) Using the syscall convention
iii) Using an alternate invoke macro to call API functions
.386
.model flat, syscall ; SYSCALL convention
option casemap:none
include \masm32\include\windows.inc
include invoke.inc
extern ExitProcess:proc
extern MessageBoxA:proc
MessageBox equ <MessageBoxA>
includelib kernel32.lib
includelib user32.lib
.data
MsgCaption db "Iczelion's tutorial no.2",0
MsgBoxText db "Win32 Assembly is Great!",0
.code
_start:
_invoke MessageBox, NULL,addr MsgBoxText, addr MsgCaption, MB_OK
_invoke ExitProcess,NULL
END _start
[attachment deleted by admin]