News:

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

Main Menu

What am I doing wrong in the creation and use of this macro?

Started by Rav, June 28, 2022, 05:44:10 AM

Previous topic - Next topic

Rav

I'm using Visual Studio version 17.2.5 (the latest as of this moment).  I'm trying to create a simple macro to delete a leading blank, if any, off of one of the arguments to the macro, and I'm having trouble getting it to even assemble (let alone work).  I'm pretty new to writing macros.  Here's the relevant fragment of my test program:

; ==================================================
.model flat, stdcall

.DATA
.CODE

MyProc   proc   near


mTest MACRO mystr

char SUBSTR <mystr>,1,1   ; Get first char.
IFIDN char,< >         ; If first char is blank ...
%mystr% SUBSTR <mystr>,2   ; ... delete leading blank.
ENDIF

xor eax,eax ; (Any instruction before - irrelevant what)
mystr      ; This line in the assembled code should be   cmp eax,123   with NO leading blank.
xor eax,eax ; (Any instruction after - irrelevant what)
      
ENDM


mTest < cmp eax,123> ; Argument has a leading blank.
ret

MyProc endp
end MyProc

; ==================================================

When I attempt to assemble it, I get "syntax error: SUBSTR".  Here's what the macro expanded to when I invoked it:

% cmp eax,123% SUBSTR < cmp eax,123>,2

Which is obviously wrong.  What am I doing wrong?  And is there a better way to do what I'm trying to do?  Thanks  / Rav

jj2007

A few Rules for the Forum
Quote* Post your complete code. Some believe that older members are eager to construct the missing headers around your snippets, but this belief is FALSE

Rav

Quote from: jj2007 on June 28, 2022, 06:18:31 AM
A few Rules for the Forum
Quote* Post your complete code. Some believe that older members are eager to construct the missing headers around your snippets, but this belief is FALSE

Hi, jj2007.  This is the complete code.  It attempts to do just what I mentioned, which is delete the (possibly) leading blank from a macro argument.  That's all I need it to do.  Aside from the single line that errors out, the rest assembles fine.  Thanks.

HSE

.386
.model flat, stdcall
.CODE

mTest MACRO mystr

  xor eax,eax ; (Any instruction before - irrelevant what)
  char SUBSTR <mystr>,1,1   ; Get first char.
  IFIDN char,< >         ; If first char is blank ...
     mystr2 SUBSTR <mystr>,2   ; ... delete leading blank.
     mystr2      ; This line in the assembled code should be   cmp eax,123   with NO leading blank.
  ELSE
     mystr
  ENDIF
  xor eax,eax ; (Any instruction after - irrelevant what)
ENDM

MyProc   proc
   mTest < cmp eax,123> ; Argument has a leading blank.
   ret
MyProc endp
end MyProc
Equations in Assembly: SmplMath

jj2007

Quote from: Rav on June 28, 2022, 06:27:22 AMHi, jj2007.  This is the complete code.

Oh, really? Why does the assembler spit out so many error messages then?

*** Assemble using mlv614  ***
Assembling: tmp_file.asm
tmp_file.asm(2) : error A2085: instruction or register not accepted in current CPU mode
tmp_file.asm(4) : error A2013: .MODEL must precede this directive
tmp_file.asm(5) : error A2013: .MODEL must precede this directive
tmp_file.asm(7) : error A2034: must be in segment block : MyProc
tmp_file.asm(24) : error A2085: instruction or register not accepted in current CPU mode
mTest(4): Macro Called From
  tmp_file.asm(24): Main Line Code
tmp_file.asm(24) : error A2034: must be in segment block
mTest(7): Macro Called From
  tmp_file.asm(24): Main Line Code
tmp_file.asm(24) : error A2085: instruction or register not accepted in current CPU mode
mTest(8): Macro Called From
  tmp_file.asm(24): Main Line Code
tmp_file.asm(24) : error A2034: must be in segment block
mTest(9): Macro Called From
  tmp_file.asm(24): Main Line Code
tmp_file.asm(25) : error A2034: must be in segment block
tmp_file.asm(27) : fatal error A1010: unmatched block nesting : MyProc
*** Assembly error ***

NoCforMe

See, this is why I don't even bother with MASM macros unless my back is up against the wall. Learning the rules of using them makes my head hurt (even more than learning all the other rules of assembly-language programming). All that expansion and transformation crap ...
Assembly language programming should be fun. That's why I do it.

HSE

Quote from: NoCforMe on June 28, 2022, 07:24:55 AM
See, this is why I don't even bother with MASM macros unless my back is up against the wall. Learning the rules of using them makes my head hurt (even more than learning all the other rules of assembly-language programming). All that expansion and transformation crap ...

CPU was missing. It's a beginner common error.
Equations in Assembly: SmplMath

NoCforMe

Quote from: HSE on June 28, 2022, 07:34:33 AM
Quote from: NoCforMe on June 28, 2022, 07:24:55 AM
See, this is why I don't even bother with MASM macros unless my back is up against the wall. Learning the rules of using them makes my head hurt (even more than learning all the other rules of assembly-language programming). All that expansion and transformation crap ...

CPU was missing. It's a beginner common error.

You're referring to the CPU in my head, right? Well, gotta admit it's a bit obsolete, possibly partially damaged, prone to unexplained behavior, etc.
I'm not a beginner, but would almost be if I had to delve into the dark world of MASM macos ...
Assembly language programming should be fun. That's why I do it.

HSE

Equations in Assembly: SmplMath

Rav

Quote from: jj2007 on June 28, 2022, 07:12:47 AM
Quote from: Rav on June 28, 2022, 06:27:22 AMHi, jj2007.  This is the complete code.

Oh, really? Why does the assembler spit out so many error messages then?

*** Assemble using mlv614  ***
Assembling: tmp_file.asm
tmp_file.asm(2) : error A2085: instruction or register not accepted in current CPU mode
tmp_file.asm(4) : error A2013: .MODEL must precede this directive
tmp_file.asm(5) : error A2013: .MODEL must precede this directive
tmp_file.asm(7) : error A2034: must be in segment block : MyProc
tmp_file.asm(24) : error A2085: instruction or register not accepted in current CPU mode
mTest(4): Macro Called From
  tmp_file.asm(24): Main Line Code
tmp_file.asm(24) : error A2034: must be in segment block
mTest(7): Macro Called From
  tmp_file.asm(24): Main Line Code
tmp_file.asm(24) : error A2085: instruction or register not accepted in current CPU mode
mTest(8): Macro Called From
  tmp_file.asm(24): Main Line Code
tmp_file.asm(24) : error A2034: must be in segment block
mTest(9): Macro Called From
  tmp_file.asm(24): Main Line Code
tmp_file.asm(25) : error A2034: must be in segment block
tmp_file.asm(27) : fatal error A1010: unmatched block nesting : MyProc
*** Assembly error ***


I don't know why it does that for you, jj2007.  I get none of those errors here.  Only the "syntax error: SUBSTR".

Rav

Quote from: HSE on June 28, 2022, 06:54:13 AM
.386
.model flat, stdcall
.CODE

mTest MACRO mystr

  xor eax,eax ; (Any instruction before - irrelevant what)
  char SUBSTR <mystr>,1,1   ; Get first char.
  IFIDN char,< >         ; If first char is blank ...
     mystr2 SUBSTR <mystr>,2   ; ... delete leading blank.
     mystr2      ; This line in the assembled code should be   cmp eax,123   with NO leading blank.
  ELSE
     mystr
  ENDIF
  xor eax,eax ; (Any instruction after - irrelevant what)
ENDM

MyProc   proc
   mTest < cmp eax,123> ; Argument has a leading blank.
   ret
MyProc endp
end MyProc


Thank you, HSE.  While what you provided works (which is a great step in the right direction), the output isn't exactly what I had wanted.  When I use ML.EXE to assemble your routine (ML /Fl /c test.asm), the test.lst output file contains the following:

00000000         MyProc   proc
               mTest < cmp eax,123> ; Argument has a leading blank.
00000000  33 C0        1     xor eax,eax ; (Any instruction before - irrelevant what)
00000002  83 F8 7B        1       mystr2      ; This line in the assembled code should be   cmp eax,123   with NO leading blank.
00000005  33 C0        1     xor eax,eax ; (Any instruction after - irrelevant what)
00000007  C3            ret
00000008         MyProc endp

So while the object code contains the correct instructions (83 F8 7B, which is cmp eax,123), the LISTING contains " mystr2" (notice the leading blank, by the way), not "cmp eax,123" as desired (and with no leading blank).  I want the listing to contain the source of the assembled code, not the name of the variable that contains it.  I hope that makes sense.  If this isn't possible I'll make do without it -- not the end of the world.

HSE

Try to force expansion, ej.: IFIDN char,< >         ; If first char is blank ...
     mystr2 SUBSTR <mystr>,2   ; ... delete leading blank.
     %mystr2      ; This line in the assembled code should be   cmp eax,123   with NO leading blank.
  ELSE
     mystr
  ENDIF
Equations in Assembly: SmplMath

Rav

Quote from: HSE on June 28, 2022, 09:31:03 AM
Try to force expansion, ej.: IFIDN char,< >         ; If first char is blank ...
     mystr2 SUBSTR <mystr>,2   ; ... delete leading blank.
     %mystr2      ; This line in the assembled code should be   cmp eax,123   with NO leading blank.
  ELSE
     mystr
  ENDIF


Thanks, but all that did was add the % character onto the front of the line, so now the line in the listing file is this:

%mystr2 ; This line in the assembled code should be   cmp eax,123   with NO leading blank.

No need to spend any more time on this.  I was just hoping it could be done.  It's not a show-stopper.  Thanks again.  / Rav

jj2007

Quote from: Rav on June 28, 2022, 08:28:56 AMI don't know why it does that for you, jj2007.  I get none of those errors here.  Only the "syntax error: SUBSTR".

You didn't post the complete code. You posted untested code that could never have assembled without errors on your machine, that's why I refuse to even look at such code.

Here is what works for you:

mTest MACRO mystr
  Local char, mystr2
  char SUBSTR <mystr>,1,1   ; Get first char.
  IFIDN char,< >         ; If first char is blank ...
mystr2 SUBSTR <mystr>,2   ; ... delete leading blank.
  ELSE
mystr2 equ <mystr>
  ENDIF

  xor eax,eax ; (Any instruction before - irrelevant what)
  mystr2      ; This line in the assembled code should be   cmp eax,123   with NO leading blank.
  xor eax,eax ; (Any instruction after - irrelevant what)
ENDM


You cannot change a macro argument.

Rav

Quote from: jj2007 on June 28, 2022, 10:08:36 AM
Quote from: Rav on June 28, 2022, 08:28:56 AMI don't know why it does that for you, jj2007.  I get none of those errors here.  Only the "syntax error: SUBSTR".

You didn't post the complete code. You posted untested code that could never have assembled without errors on your machine, that's why I refuse to even look at such code.

Here is what works for you:

mTest MACRO mystr
  Local char, mystr2
  char SUBSTR <mystr>,1,1   ; Get first char.
  IFIDN char,< >         ; If first char is blank ...
mystr2 SUBSTR <mystr>,2   ; ... delete leading blank.
  ELSE
mystr2 equ <mystr>
  ENDIF

  xor eax,eax ; (Any instruction before - irrelevant what)
  mystr2      ; This line in the assembled code should be   cmp eax,123   with NO leading blank.
  xor eax,eax ; (Any instruction after - irrelevant what)
ENDM


You cannot change a macro argument.

Once again:  I DID post complete code.  I DID test the code I posted.  There IS NO OTHER CODE.  The only error I got during assembly of the code that I posted was "syntax error: SUBSTR".  There were NO OTHER ERRORs.  And getting that ONE error was WHY I made my original post.  Why you got a bunch of errors that I did NOT get is unknown to me.  I did not get those errors.