The MASM Forum

64 bit assembler => UASM Assembler Development => Topic started by: jimg on January 20, 2019, 10:08:06 AM

Title: Macro goto problem
Post by: jimg on January 20, 2019, 10:08:06 AM
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?


Title: Re: Macro goto problem
Post by: johnsa on January 21, 2019, 04:14:36 AM
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
Title: Re: Macro goto problem
Post by: jj2007 on January 21, 2019, 05:24:00 AM
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 ",///
Title: Re: Macro goto problem
Post by: KradMoonRa on January 21, 2019, 07:17:21 AM
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
Title: Re: Macro goto problem
Post by: HSE on January 21, 2019, 08:41:47 AM
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.
Title: Re: Macro goto problem
Post by: jimg on January 21, 2019, 10:06:18 AM
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.
Title: Re: Macro goto problem
Post by: johnsa on January 21, 2019, 10:14:53 PM
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 :)
Title: Re: Macro goto problem
Post by: jimg on January 22, 2019, 01:03:50 AM
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!
Title: Re: Macro goto problem
Post by: BugCatcher on January 22, 2019, 01:21:35 AM
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:?
Title: Re: Macro goto problem
Post by: johnsa on January 22, 2019, 03:32:58 AM
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.
Title: Re: Macro goto problem
Post by: hutch-- on January 22, 2019, 11:53:44 AM
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.
Title: Re: Macro goto problem
Post by: jimg on January 22, 2019, 01:31:03 PM
Wouldn't it be wonderful to fix all that :)
Title: Re: Macro goto problem
Post by: johnsa on January 22, 2019, 08:16:22 PM
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.

Title: Re: Macro goto problem
Post by: jj2007 on January 22, 2019, 08:36:39 PM
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