I am trying to trick out MASM to use function MACRO both ways as function or proc.
I may doing it a hard way. :P
My theory is to return <COMMENT *Var*> if proc <%Var> if function.
It is working beautifuly but if I have a "LABEL:" in the same line calling the macro MASM is putting the label somehow after the call. :dazzled:
I don't know why is that and what I can do about it. ::)
.686p
.model flat, stdcall
option casemap :none
includelib kernel32.lib
include kernel32.inc
RtlZeroMemory PROTO :DWORD,:DWORD
Pilot MACRO
invoke RtlZeroMemory,eax,ebx
EXITM <COMMENT *eax*>
ENDM
.code
start: JMP L000
nop
nop
nop
nop
L000: Pilot()
int 3
end start
001A1000 /EB 0B JMP SHORT 001A100D ;Jumping to INT 3 Why????
001A1002 |90 NOP
001A1003 |90 NOP
001A1004 |90 NOP
001A1005 |90 NOP
001A1006 |53 PUSH EBX
001A1007 |50 PUSH EAX
001A1008 |E8 01000000 CALL 001A100E
001A100D \CC INT3
macro-generated code/data is allways inserted before the line the macro is called from.
EDIT: this only applies to function like macros
Quote from: qWord on June 22, 2010, 02:01:16 PM
macro-generated code/data is allways inserted before the line the macro is called from.
Ok.....I can see that.....
And is there a way to call a function macro and ignore the return value? ::)
simply return nothing :bg
EXITM <>
I did but still dosn't work on "LABEL" :bg :(
Quote from: qWord on June 22, 2010, 02:01:16 PM
macro-generated code/data is allways inserted before the line the macro is called from.
By the way this seem to be just 50% true because if the MACRO is not a function it works fine. :wink
Damn!!! :(
This dosn't work either:
option casemap :none
includelib kernel32.lib
include kernel32.inc
RtlZeroMemory PROTO :DWORD,:DWORD
Pilot MACRO
LOCAL A
A = 1
invoke RtlZeroMemory,eax,ebx
IF A
@CatStr(<EXITM !<!>>)
ENDIF
ENDM
.code
start: JMP L000
nop
nop
nop
nop
L000: Pilot()
int 3
end start
Quote from: Ficko on June 22, 2010, 02:39:49 PMBy the way this seem to be just 50% true because if the MACRO is not a function it works fine. :wink
yep, your right :U
However, I was takling about function like macros.
why not making two macros(?):
@Pilot() (function) and Pilot (Procedur)
why not making two macros(?)
Because I am working on wrappers for my routines in a lib. about 150 procs and I don't want to double the choices have to make. :bg
Ok, I may got something could work for me. :wink
It is actually the reverse but may I can achive the same result with it - having a return value or not having one -
.model flat, stdcall
option casemap :none
includelib kernel32.lib
include kernel32.inc
RtlZeroMemory PROTO :DWORD,:DWORD
Pilot MACRO
invoke RtlZeroMemory, eax, ebx
PilotF MACRO
LOCAL A
EXITM <>
ENDM
PilotF()
ENDM
.code
start: JMP L000
nop
nop
nop
nop
L000: Pilot
int 3
end start
Here is a Timer() macro that works both ways. The trick is to check the argument for "start"...
Note the .if 1 is not really necessary, but it forces the user to use Timer(start) ... Timer(whatever) together. That trick is to punish users who forget that the first macro puts the GetTickCount result on the stack with a nasty error message :bg
include \masm32\include\masm32rt.inc
Timer MACRO arg
push ecx ; save some regs
push edx
invoke GetTickCount
ifidni <arg>, <start>
.if 1
pop edx
pop ecx
push eax
EXITM <> ;; return an empty string for Timer(start)
else
pop edx
pop ecx
pop edx ;; get the value of Timer(start)
sub eax, edx ;; return elapsed milliseconds
.endif
EXITM <eax>
endif
ENDM
.data?
globdiff dd ?
gtcloops dd ?
.code
start: mov ebx, 20
.Repeat
imul esi, ebx, 10 ; esi=ebx*10
Timer(start)
invoke Sleep, esi
mov edi, Timer(end)
print str$(edi), 9, " expected: "
print str$(esi), ", abs(diff)="
sub edi, esi
.if Sign?
neg edi
.endif
add globdiff, edi
print str$(edi), 13, 10
dec ebx
.Until Zero?
print "Overall difference: "
print str$(globdiff), 13, 10, "wait loops: "
print str$(gtcloops)
getkey
exit
end start
did you try putting the label and the macro on seperate lines ?
start: JMP L000
nop
nop
nop
nop
L000:
Pilot()
int 3
Thanks JJ2007. :wink
But my scenario is a little different.
Here is a mock-up:
DoNeedOffset MACRO Var:REQ
IF ((.TYPE Var) EQ 42)
EXITM @CatStr(<offset >,Var)
ELSE
EXITM <Var>
ENDIF
ENDM
; ------------------------------------------------
IsNested MACRO Param:REQ
LOCAL CParam,Spos
Spos INSTR <Param>,<*>
IF Spos
CParam SUBSTR <Param>,Spos+1
CParam SUBSTR CParam,1,@SizeStr(%CParam)-1
ELSE
CParam TEXTEQU Param
ENDIF
EXITM CParam
ENDM
; ------------------------------------------------
ENDSTRING MACRO Var:=<EAX>
EXITM @CatStr(<COMMENT *>,<Var>,<*>)
ENDM
; ------------- NOT WORKING ON LINES BEGINNING WITH LABEL !! ---------------------
LEN$ MACRO pString
IFNB <pString>
invoke LEN$_,DoNeedOffset(IsNested(pString))
ELSE
call LEN$_
ENDIF
EXITM <COMMENT *EAX*>
ENDM
; ------------- SEEMS TO WORK -------------
LEN$ MACRO _String
LEN$F MACRO pString
IFNB <pString>
invoke LEN$_,DoNeedOffset(IsNested(pString))
ELSE
call LEN$_
ENDIF
EXITM <COMMENT *EAX*>
ENDM
LEN$F(_String)
ENDM
; ------------------------------------------------
FIRSTINDEXOF MACRO pString:REQ,pSearch:REQ,pos:=<1>
LOCAL cSearch
cSearch CATSTR cfm$(pSearch)
invoke FIRSTINDEXOF_,DoNeedOffset(pString),DoNeedOffset(cSearch),IsNested(pos)
EXITM <COMMENT *EAX*>
ENDM
So I can use:
LEN$(AnyString)
FIRSTINDEXOF(Source,Search,eax)
or
FIRSTINDEXOF(Source,Search,LEN$(AnyString))
Quote from: dedndave on June 22, 2010, 04:42:43 PM
did you try putting the label and the macro on seperate lines ?
Of course Dave but that would made the system very error prone.
I should have to pay attention anytime writing a label not to write a function after it. :wink
Quote from: Ficko on June 22, 2010, 04:49:57 PM
Quote from: dedndave on June 22, 2010, 04:42:43 PM
did you try putting the label and the macro on seperate lines ?
Of course Dave but that would made the system very error prone.
I should have to pay attention anytime writing a label not to write a function after it. :wink
or, you can simply never write anything else on the same line as a label, like normal people :)
truthfully, the label shouldn't have to be on a seperate line
the fact that the macro is expanded first kinda sux rox if you ask me :P
if i were a big-time macro user, i would bitch about it - lol
Quote
if i were a big-time macro user, i would bitch about it..
What you think I am doing now ? :lol :lol
But I have to stick to your proposal because there is no other way to circumvent it. :(
And if I look the things in a certain way there is every command a potential error trap if you don't know what you are doing. :wink
I tried everything even managed to get MASM into a dead loop. :green2
.686p
.model flat, stdcall
option casemap :none
MyMacro MACRO
@CatStr(<COMMENT !*>)
EXITM <>
@CatStr(<!*>)
ENDM
.code
start:MyMacro()
end start
My only hope left is to manage to get a way to report an error at least if the line has a label but that presuppose there is a way to get the line content somehow.
"@Line" gives the actual line and I am wondering may exist a public pointer to the actual line? ::)
OK, to summarise the problem here a testbed.
include \masm32\include\masm32rt.inc
zemac MACRO arg
ifb <arg>
tmp$ CATSTR <"I am a lonely macro with no arg called from line >, %@Line, <">
MsgBox 0, chr$(tmp$), "zemac:", MB_OK
EXITM <>
else
MsgBox 0, &arg&, "zemac:", MB_OK
EXITM <EAX>
endif
ENDM
.code
start: jmp L1 ; jmp L1 will work fine, jmp L2 will ignore the macro code
nop
L1:
L2: mov eax, zemac("Hello World, if you see me it's working!") ; this code will be generated before label L2
.if eax!=IDOK
MsgBox 0, "There was no box...!", "Hi", MB_OK
.endif
zemac() ; same macro "standalone"
exit
end start