News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Macro goto problem

Started by jimg, January 20, 2019, 10:08:06 AM

Previous topic - Next topic

jimg

When I try the following code-

.686
.model Flat, Stdcall
option Casemap :None   
.code

testxa macro ThingsToTest:VARARG
    for arg,<ThingsToTest>
        forc nnx,<&arg>  ;; get first character
        ifidni <&nnx>,</>   ;; check for line feeds
            crcnt=0
            dxflg = 6
            forc slashx,<&arg>
                ifidn <&slashx>,</>
                    crcnt = crcnt + 1
                endif
            endm
            mov dl,crcnt
            goto Doit
        endif
        ifidni <&nnx>,<.>   ;; check for spaces
            crcnt=0
            forc slashx,<&arg>
                ifidn <&slashx>,<.>
                    crcnt = crcnt + 1
                endif
            endm
            mov eax,crcnt
            goto Doit
        endif
        exitm  ; only want to test first character
    endm
    ; do a whole bunch of other stuff here   
      :Doit
        ; do more stuff here
    endm
endm

program:
    testxa .,d ecx,":",d eax,...,"test 3 < 4 ",///         
    ret
end program


I get the error- Error A2267: Macro label not defined: Doit

if I comment out the outer loop, it assembles without error.

I couldn't find anything saying it was illegal to nest for loops, it that a restriction?



johnsa

Hi,

Have you tried the same macro in ML and ASMC to see how it responds ?
(Useful to know if it's a common issue or UASM specific).

Thanks!
John

jj2007

It throws additional errors in various MASM versions (6.15 .. 10.0). Can you explain what you want to achieve?
testxa .,d ecx,":",d eax,...,"test 3 < 4 ",///

KradMoonRa

Common macro problem, it can't know the Label because it's declared after statement.

Not tested but I think it will work.


.686
.model Flat, Stdcall
option Casemap :None   
.code

testxa macro ThingsToTest:VARARG
    local Doit
    for arg,<ThingsToTest>
        forc nnx,<&arg>  ;; get first character
        ifidni <&nnx>,</>   ;; check for line feeds
            crcnt=0
            dxflg = 6
            forc slashx,<&arg>
                ifidn <&slashx>,</>
                    crcnt = crcnt + 1
                endif
            endm
            mov dl,crcnt
            goto Doit
        endif
        ifidni <&nnx>,<.>   ;; check for spaces
            crcnt=0
            forc slashx,<&arg>
                ifidn <&slashx>,<.>
                    crcnt = crcnt + 1
                endif
            endm
            mov eax,crcnt
            goto Doit
        endif
        exitm  ; only want to test first character
    endm
    ; do a whole bunch of other stuff here   
      :Doit
        ; do more stuff here
    endm
endm

program:
    testxa .,d ecx,":",d eax,...,"test 3 < 4 ",///         
    ret
end program
The uasmlib

HSE

There is a label inside a loop, and that means redefinition.
.686
.model Flat, Stdcall
option Casemap :None   
.code

tstxa macro ThingsToTst:VARARG
    cnt = 0
    FOR arg,<ThingsToTst>
        forc nnx,<&arg>  ;; get first character
        ifidni <&nnx>,</>   ;; check for line feeds
            crcnt=0
            dxflg = 6
            forc slashx,<&arg>
                ifidn <&slashx>,</>
                    crcnt = crcnt + 1
                endif
            endm
            mov dl,crcnt
%           goto @CatStr(Doit, %cnt)
        endif
        ifidni <&nnx>,<.>   ;; check for spaces
            crcnt=0
            forc slashx,<&arg>
                ifidn <&slashx>,<.>
                    crcnt = crcnt + 1
                endif
            endm
            mov eax,crcnt
%            goto @CatStr(Doit, %cnt)
        endif
        exitm <> ; only want to test first character
    endm
    ;; do a whole bunch of other stuff here   
    %  @CatStr(Doit,%cnt,<:>)
        ;; do more stuff here
        cnt = cnt+1
    ENDM
endm

program:
    tstxa  a,b ; .,d ecx,":",d eax,...,"test 3 < 4 ",///         
    ret
end program


NOTE: I have not a clue what you are trying to do.
Equations in Assembly: SmplMath

jimg

#5
I will try to respond to each one of you, bear with me, for some reason I've been having a hard time making myself understood lately-

Johnsa-
   There are so many things broken in Masm that are done right in UAsm that I've stopped trying to make them compatible.  Yes, it throws an error in Masm also, but I couldn't see any reason for it, so I thought I'd ask here if it seemed like a reasonable thing to do.

JJ-
This is part of my printing macros.  Primitive compared to MasmBasic, but I've been using and improving them for about 15 years.  The cryptic string is just directives to Printx.

KradMoonRa-
I've never had this problem before.  So far I've only seen it occur when in a nested loop.

HSE-
I didn't know that a loop would have local labels, variables, etc.   It seems like a rather restrictive requirement.


To everyone-
I have come to expect UAsm to be a better Masm.   I always hope for the best.

johnsa

My immediate guess (without looking) is that the macro label isn't stored during the evaluation of a for loop, only upon completion which is why it's not available.
My suggestion would be to perhaps rather than using a label expand out the cases into calls to different macros, the sort of usual HLL response you'd get from anyone who saw you using a GOTO :)

jimg

Thanks John, I've already found a simple work around.   The goto only fails in a nested loop, it works fine in an un-nested loop.   I thought this might be indicative of a deeper problem that should be addressed.
I really like UAsm, keep up the good work!

BugCatcher

I haven't used goto since my basic days 30yrs ago. So does "goto" go to a label with the colon on the left side? :Doit instead of right side Doit:?

johnsa

For macro labels yes, regular asm labels have the colon at the end, or if you're using scoped local labels then a :: at the end to put the label into global scope.

hutch--

I would not lose too much sleep over macro behaviour, the ancient pre-processor in MASM has all sorts of undocumented quirks. The various loop techniques do not always allow external macro instructions. Macros in MASM and compatible are closer to "Black Magic" than science.

jimg

Wouldn't it be wonderful to fix all that :)

johnsa

The only real way to achieve it would be to create a totally new asl / macro language to use, perhaps as a command line switchable option..
-masmMacro vs -newMacro

with a more rigorous and structured syntax that can be properly parsed.
The way macros work is all a bit sketchy, it's always been a 98% type of solution.


jj2007

Found the solution, it wasn't actually that difficult...

include \masm32\include\masm32rt.inc
.code

testxa macro ThingsToTest:VARARG
    for arg,<ThingsToTest>
        forc nnx,<&arg>  ;; get first character
        ifidni <&nnx>,</>   ;; check for line feeds
            crcnt=0
            dxflg = 6
            forc slashx,<&arg>
                ifidn <&slashx>,</>
                    crcnt = crcnt + 1
                endif
            endm
            mov dl,crcnt
            goto Doit
        endif
        ifidni <&nnx>,<.>   ;; check for spaces
            crcnt=0
            forc slashx,<&arg>
                ifidn <&slashx>,<.>
                    crcnt = crcnt + 1
                endif
            endm
            mov eax,crcnt
            goto Doit
        endif
:Doit
tmp$ CATSTR <found [>, <nnx>, <]>
% echo tmp$
exitm  ; only want to test first character
    endm
    ; do a whole bunch of other stuff here   
        ; do more stuff here
    endm
endm

program:
  if 1
    testxa .,d ecx,":",d eax,...,"test 3 < 4 ",///       ; works only with UAsm 
  else
    testxa .,d ecx,":",d eax,...,"test 3 lt 4 ",///       ; works with UAsm and ML 6.14+         
  endif
    ret
end program