News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Macro usage and tricks

Started by zemtex, April 06, 2012, 04:02:47 AM

Previous topic - Next topic

zemtex

I am reading the macro include files and help files in masm32 directory, but if there is something I don't understand well, it's macros. I seldom use them. It was under DOS that I went into it for the first time, but like I said I seldom use it under masm32. Sometimes I use the macros that comes with masm32 and sometimes I create simple macros for plotting pixels and that sort of stuff.

Can anyone produce (5-6-7-8-9 or 10) small examples, very tiny examples with different usage of macros. How to insert literal text, how to insert values to registers, how to differentiate between text, numbers and so forth. Can you produce a few small samples, they must be very very tiny samples so that I can grasp it with ease. I appreciate wide variety of usage, so the more examples the better. The less complex the better.

Many small, but wide variety that covers most in as little text as possible. Be very accurate, keep text clean, use proper naming convention, organize your work, keep it clean above everything.

(Btw, I understand the definition of macros, they are pseudo instructions for the assembler, I need only to learn how to use them properly)

EDIT: I realized it may be better to ask for specific type of examples. I can give a few suggestions..

1: Macro to insert text into the .asm file, let's say I need to replace an argument inside an INVOKE, how can I use a macro to replace parameters?
2: How to create variables in a macro and perform some calculations (perhaps)
....
I have been puzzling with lego bricks all my life. I know how to do this. When Peter, at age 6 is competing with me, I find it extremely neccessary to show him that I can puzzle bricks better than him, because he is so damn talented that all that is called rational has gone haywire.

dedndave

i have gotten a little better with them   :P

watching jj2007 and qWord helps a lot - so you might use advanced search, the term "macro", and limit the results to either of those ID's
of course, other members are good at macros, as well - those two just come to mind   :P
also - the masm programmers guide is a must-read - it has a pretty good section on macros

http://www.4shared.com/zip/39MdNf_v/MASMProgGuide.html

this is a good example of how to replace a parm in INVOKE
      len MACRO lpString
        invoke szLen,reparg(lpString)
        EXITM <eax>
      ENDM

notice the EXITM <eax> line
also important to understand that both the macro and the function preserve all other registers, including ECX and EDX
that way, if...
        INVOKE  SomeFunction,ecx,len(offset szString)
the contents of ECX are not destroyed by the macro before it is pushed onto the stack by INVOKE

zemtex

Thanks, I am now a certified macro professional.
I have been puzzling with lego bricks all my life. I know how to do this. When Peter, at age 6 is competing with me, I find it extremely neccessary to show him that I can puzzle bricks better than him, because he is so damn talented that all that is called rational has gone haywire.

jj2007

You will understand about half of it (my success quote with qWord's macros :bg), but don't worry, that's more than enough for the certificate.

Theory:   Masm Programmer's Guide (search the forum, e.g. this post)
Usage:    \masm32\MasmBasic\MbGuide.rtf (>100 macros explained)
Macros:   \masm32\MasmBasic\MasmBasic.inc

The MasmBasic package is at http://www.masm32.com/board/index.php?topic=12460

Example:

Err$()
   Err$(1)      
; call GetLastError, and show a MessageBox with a formatted string if there was an error
   Err$(0)      
; call GetLastError, and show a MessageBox even if there was no error
   
PrintLine "Result=", Err$()   ; print the formatted string
   
void Err$()   ; no arg: returns <eax> plus the zero flag
   
.if !Zero?      ; for use with .if, .Break etc
      
MsgBox 0, eax, "Hey coder, there is an error:", MB_OK
   .else
      deb 4, "Loop C", $eax   ; will write The operation completed successfully to the console
   .endif
Rem   the blank argument version returns a pointer to the formatted error desription in eax

The macro from MasmBasic.inc:

Err$ MACRO dummy ; 0: show always, 1: show if error, (): .if e$()
  push ecx
  push ebx
  invoke GetLastError
  xchg eax, ebx
  mov edx, offset MbDebugBuffer+512 ; 1024/2
  push edx ; make a copy for the retval
  xor ecx, ecx
  push ecx ; no args
  push 512 ; size
  push edx ; pBuffer
  push ecx ; default language
  push ebx ; the error #
  push ecx ; no source, GetItFromSystem
  push FORMAT_MESSAGE_FROM_SYSTEM
  call FormatMessage
  ifnb <dummy>
mov eax, [esp] ; MbGpBuffer
ifidn <dummy>, <0>
.if ebx
invoke MessageBox, 0, eax, 0, MB_OK
.endif
else
invoke MessageBox, 0, eax, 0, MB_OK
endif
  endif
  pop eax ; offset MbGpBuffer
  test ebx, ebx ; allows void Err$(), .if !Zero?
  pop ebx
  pop ecx
  ifnb <dummy>
EXITM <>
  else
EXITM <eax>
  endif
ENDM



dedndave

i see you've taken up one of my favorite tricks   :bg
  xchg eax, ebx

ok, i have a question...

   void Err$()   ; no arg: returns <eax> plus the zero flag

wouldn't that just be
   Err$()   ; no arg: returns <eax> plus the zero flag

if you changed the end to this ?
  ifnb <dummy>
EXITM
  else
EXITM <eax>
  endif
ENDM


actually, i guess it would be this ?
  ifb <dummy>
EXITM <eax>
  endif
ENDM

qWord

dedndave,
that not possible: if your macro return something, it must be done for all paths. However, you have the option to return nothing: EXITM <>.
FPU in a trice: SmplMath
It's that simple!

zemtex

What exactly does EXITM do, I have forgotten, lol, all I remember is that it stands for exit macro? Also, can anyone explain or give an example of how to add two numbers in a macro and have the macro output the result as text into the source code.
I have been puzzling with lego bricks all my life. I know how to do this. When Peter, at age 6 is competing with me, I find it extremely neccessary to show him that I can puzzle bricks better than him, because he is so damn talented that all that is called rational has gone haywire.

jj2007

EXITM returns a string. This is e.g. the case for mov ecx, rv(GetTickCount).
The "standalone" macros such as print do not return anything, therefore no EXITM.
You can use a function macro in "standalone mode", e.g. for starting in MasmBasic the QueryPerformanceCounter:
  NanoTimer()
  ... do stuff ...
  Print Str$("%i ms needed", NanoTimer(ms))

The first call returns EXITM <>, the second one EXITM <eax>.

Here is a macro that adds two numbers and displays the result.

include \masm32\include\masm32rt.inc

Add2 MACRO arg1, arg2
LOCAL oa
  push arg1
  oa = opattr arg2
  if (oa eq 36) or (oa eq 48) ; immediate or register
add dword ptr [esp], arg2
  else
mov eax, arg2
add [esp], eax
  endif
  pop eax
  print str$(eax), 13, 10
ENDM 

.code
v1 dd 111
AppName db "Masm32:", 0

start: Add2 v1, 222
Add2 222, v1
mov eax, v1
Add2 eax, 222
inkey "bye"
exit

end start

zemtex

This is a proper example  :U
I have been puzzling with lego bricks all my life. I know how to do this. When Peter, at age 6 is competing with me, I find it extremely neccessary to show him that I can puzzle bricks better than him, because he is so damn talented that all that is called rational has gone haywire.

hutch--

EXITM allows you to return data to the caller of the macro, either inline in the source code text or called from another macro.


   EXITM <eax>


This allows you to place the data in EAX inline with the code that calls the macro that EXITM is contained in.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

zemtex

hutch, can you give an example of calling another macro and returning in that way. Something simple is preferrable.
I have been puzzling with lego bricks all my life. I know how to do this. When Peter, at age 6 is competing with me, I find it extremely neccessary to show him that I can puzzle bricks better than him, because he is so damn talented that all that is called rational has gone haywire.

hutch--

This should make sense.



IF 0  ; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                      Build this template with "CONSOLE ASSEMBLE AND LINK"
ENDIF ; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    include \masm32\include\masm32rt.inc

    addem MACRO int1,int2   ;; function style macro that returns a value
      mov eax, int1
      add eax, int2
      EXITM <eax>           ;; return data in EAX to caller
    endm

    .code

start:
   
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    call main
    inkey
    exit

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

main proc

    LOCAL retval1    :DWORD

    cls

    mov retval1, addem(1234,5678)

    print ustr$(retval1),13,10

    ret

main endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

end start


Nested like this.



IF 0  ; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                      Build this template with "CONSOLE ASSEMBLE AND LINK"
ENDIF ; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    include \masm32\include\masm32rt.inc

    addem MACRO int1,int2   ;; function style macro that returns a value
      mov eax, int1
      add eax, int2
      EXITM <eax>           ;; return data in EAX to caller
    endm

    .code

start:
   
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    call main
    inkey
    exit

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

main proc

    LOCAL retval1    :DWORD
    LOCAL retval2    :DWORD

    cls

    mov retval1, addem(1234,addem(1111,addem(9876,5432)))

    mov retval2, addem(retval1,retval1)

    print ustr$(retval2),13,10

    ret

main endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

end start
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

jj2007

Same as before but in function form. Actually, Hutch' solution
mov eax, arg1
add eax, arg2
is simpler and works fine, too.

include \masm32\include\masm32rt.inc

Add2 MACRO arg1, arg2
LOCAL oa, is, leftarg, rightarg
 is INSTR <arg1>, <+>
 if is
leftarg SUBSTR <arg1>, 1, is-1
rightarg SUBSTR <arg1>, is+1
push leftarg
oa = opattr rightarg
if (oa eq 36) or (oa eq 48) ; immediate or register
add dword ptr [esp], rightarg
else
mov eax, rightarg
add [esp], eax
endif
pop eax
EXITM <eax>
 else
push arg1
oa = opattr arg2
if (oa eq 36) or (oa eq 48) ; immediate or register
add dword ptr [esp], arg2
else
mov eax, arg2
add [esp], eax
endif
pop eax
print str$(eax), 13, 10
EXITM <>
 endif
ENDM  

.code
v1 dd 111
AppName db "Masm32:", 0

start: Add2(v1, 222) ; standalone usage
Add2(222, v1)
mov eax, v1
Add2(eax, 222)
mov ecx, 111
print str$(Add2(ecx+222)), 13, 10 ; used as function
inkey "bye"
exit

end start

zemtex

Thanks, nice and simple. I can live with this.  :lol
I have been puzzling with lego bricks all my life. I know how to do this. When Peter, at age 6 is competing with me, I find it extremely neccessary to show him that I can puzzle bricks better than him, because he is so damn talented that all that is called rational has gone haywire.

zemtex

Another example please.

I am aware of the rv macro, but how would you go ahead and do it if you wanted to

1: The macro should check if the returned value is NULL, if it is null the macro should jump to a label
2: The label should be passed as an argument to the macro.

Very often I use API function that could return NULL and then I usually need to jump somewhere. Can you make an example of this, the macro should jump to n1 on not null and n0 on null. Or at least jump to n0 on null and perhaps stay neutral otherwise. (no jump)

Example:    RVZ FunctionName Parameter1 Parameter2 n0

n0:  INVOKE ExitProcess, eax
I have been puzzling with lego bricks all my life. I know how to do this. When Peter, at age 6 is competing with me, I find it extremely neccessary to show him that I can puzzle bricks better than him, because he is so damn talented that all that is called rational has gone haywire.