News:

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

Trouble with MASM macro system

Started by key2k3, April 13, 2006, 10:58:02 AM

Previous topic - Next topic

key2k3

Apparently, it's impossible to resolve macro arguments indirectly when inside a FOR-Block.
Let me demonstrate this:

test MACRO _Eax:=<>, _Ebx:=<>, _Ecx:=<>, _Edx:=<>, _Edi:=<>, _Esi:=<>, _Eip:=<>, _Esp:=<>
...
assume eax :PTR CONTEXT
  FOR tmp, <__Eax, __Ebx, __Ecx, __Edx, __Edi, __Esi, __Eip, __Esp>
%   IFNB @SubStr(tmp, 2)
      mov @CatStr(<[eax].reg>, @SubStr(tmp, 2)), %@SubStr(tmp, 2)
    ENDIF
  ENDM
...
ENDM


The macro is supposed to fill a CONTEXT structure, as you can see. I had to
use two underscores for the arguments in the loop because otherwise they would
be evaluated in-place.

I don't know if the MOV line really is correct, but it doesn't even get there. IFNB throws
an error A2006 "undefined symbol" although these are the symbols that were passed
to the macro (e.g. _Eax  ... I checked this with ECHO).

However, it works when I would write this inside the FOR loop

IFNB <_Eax>


I've also tried numerous workarounds but it started telling me "macro nesting to deep"
and now - a few hours later - I'm giving up. I'm really frustrated from this problem
that looks so simple!

Thanks for ANY suggestion(s).

Regards
- Key2k3 -

drizz

no sweat when you separate text from arguments/variables

fillcontext MACRO _Eax,_Ebx,_Ecx,_Edx,_Edi,_Esi,_Eip,_Esp
LOCAL regstxt,arg,counter
ASSUME EAX:PTR CONTEXT
counter = 0
regstxt textequ <EaxEbxEcxEdxEdiEsiEipEsp>
FOR arg,<_Eax,_Ebx,_Ecx,_Edx,_Edi,_Esi,_Eip,_Esp>
IFNB <arg>
MOV @CatStr(<[EAX].reg>,@SubStr(%regstxt,%counter*3+1,3)),arg
ENDIF
counter = counter + 1
ENDM
ASSUME EAX:NOTHING
ENDM


:boohoo: have fun,
drizz
The truth cannot be learned ... it can only be recognized.

MazeGen

key2k3, if you want to debug macros, learn how to use assembly listing (command-line option /Fl). This way you can see macro expansion and each iteration of any loops.

key2k3

@drizz: Thanks for the workaround, at least it's possible *somehow*.
@MazeGen: Thanks to you as well, I'm using this directive already but it didn't help me here.

So does MASM resolve symbols in one single pass only? It knows about the symbols when I write
them but does not know when the name is generated by another macro.

This should be a bug then, shouldn't it?

MazeGen

I'm not sure what exactly is unclear for you, but let me start here.

I try to call your macro test1 with no arguments. Look at the listing:

00000000 .CODE
00000000 Start:
test1
     1
     1 assume eax :PTR CONTEXT
     1   FOR tmp, <__Eax, __Ebx, __Ecx, __Edx, __Edi, __Esi, __Eip, __Esp>
     1 %   IFNB @SubStr(tmp, 2)
     1       mov @CatStr(<[eax].reg>, @SubStr(tmp, 2)), %@SubStr(tmp, 2)
     1     ENDIF
     1   ENDM
     2 %   IFNB @SubStr(__Eax, 2)
tmp1.asm(22) : error A2006: undefined symbol : _Eax
MacroLoop(1): iteration 1: Macro Called From
  test1(7): Macro Called From
   tmp1.asm(22): Main Line Code


There's nothing like _Eax, because using _Eax:=<> you say "if there is no _Eax argument, pass a blank argument (nothing)". Because _Eax is not required, the assembler can't know something like _Eax in this case. (Sorry for my english, I'm not sure if  one can understand something from my description).

drizz's solution does seem to be clear and correct, doesn't it?

key2k3

MazeGen wrote:
> There's nothing like _Eax, because using _Eax:=<> you say
> "if there is no _Eax argument, pass a blank argument (nothing)".

_Eax is defined ! It has no content, but it is defined. So you can e.g. write ...

IFNB <_Eax>

... inside the macro and it will work: it executes the block if no argument was
passed for _Eax.

> drizz's solution does seem to be clear and correct, doesn't it?

It works, but it involves some more code, which is contraproductive. MASM
is not able to resolve defined symbols whose names are generated at macro
run-time... THIS is the problem, because it should work normally!

Regards,
- key2k3 -

MazeGen

I think about it same way as in case of run-time procedures with variable argument count: If you don't pass an optional argument to such procedure, you can't read it, because it is not present.

Your macro procedure has variable argument count too. You can't read _Eax, if it is not present.

Just take it like my point of view. :8)