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?
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
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 ",///
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
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.
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.
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 :)
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!
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:?
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.
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.
Wouldn't it be wonderful to fix all that :)
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.
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