News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Macro

Started by JK, July 13, 2020, 02:48:55 AM

Previous topic - Next topic

JK

I think i must have missed something, but it seems i cannot get it to work...

Suppose i have a macro, which does different things to it´s argument. If it´s a number - do this, if it´s text - do that.


test macro arg:req
local r$, c$

  r$ TEXTEQU <>
  r$ catstr r$, <arg>                                 ;stringize arg

  c$ SUBSTR r$, 1, 1

  ifidn c$,<0>           
; process number

  else
; process text

  endif

endm


"ifidn c$,<0> tells me, if the first character is "0". But how could i tell, if it´s in the range from "0" to "9" in one line. I want to avoid a lot of "elseifidn" branches.


JK

TouEnMasm

in masm32\macros\macros.asm
you have a set of macros who can help you,this one in particular:
Quote
  ; -------------------------
  ; determine an operand type
  ; -------------------------
    op_type MACRO arg:REQ
      LOCAL result
      result = opattr(arg)
        IF result eq 37         ;; label, either local or global
          EXITM %1
        ELSEIF result eq 42     ;; GLOBAL var
          EXITM %2
        ELSEIF result eq 98     ;; LOCAL  var
          EXITM %3
        ELSEIF result eq 36     ;; immediate operand or constant
          EXITM %4
        ELSEIF result eq 48     ;; register
          EXITM %5
        ELSEIF result eq 805    ;; local procedure in code
          EXITM %6
        ELSEIF result eq 933    ;; external procedure or API call
          EXITM %7
        ENDIF
      EXITM %0                  ;; anything else
    ENDM

    ; *************************************
    ; Return a register size in BYTES or  *
    ; 0 if the argument is not a register *
    ; *************************************
    regsize MACRO item
      LOCAL rval,ln
      rval = 0
      ln SIZESTR <item>
   
      IF ln EQ 2
        goto two
      ELSEIF ln EQ 3
        goto three
      ELSEIF ln EQ 4
        goto four
      ELSEIF ln EQ 5
        goto five
      ELSEIF ln EQ 6
        goto six
      ELSEIF ln EQ 8
        goto eight
      ELSE
        goto notreg
      ENDIF
   
    :two
      for arg,<al,ah,bl,bh,cl,ch,dl,dh>
        IFIDNI <arg>,<item>
          rval = 1
          EXITM
        ENDIF
      ENDM
      IF rval NE 0
        EXITM %rval
      ENDIF
   
      for arg,<ax,bx,cx,dx,sp,bp,si,di>
        IFIDNI <arg>,<item>
          rval = 2
          EXITM
        ENDIF
      ENDM
      IF rval NE 0
        EXITM %rval
      ENDIF
      goto notreg
   
    :three
      for arg,<eax,ebx,ecx,edx,esp,ebp,esi,edi>
        IFIDNI <arg>,<item>
          rval = 4
          EXITM
        ENDIF
      ENDM
      IF rval NE 0
        EXITM %rval
      ENDIF
   
      for arg,<st0,st1,st2,st3,st4,st5,st6,st7>
        IFIDNI <arg>,<item>
          rval = 10
          EXITM
        ENDIF
      ENDM
      IF rval NE 0
        EXITM %rval
      ENDIF
   
      for arg,<mm0,mm1,mm2,mm3,mm4,mm5,mm6,mm7>
        IFIDNI <arg>,<item>
          rval = 8
          EXITM
        ENDIF
      ENDM
      IF rval NE 0
        EXITM %rval
      ENDIF
      goto notreg
   
    :four
      for arg,<xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7>
        IFIDNI <arg>,<item>
          rval = 16
          EXITM
        ENDIF
      ENDM
      IF rval NE 0
        EXITM %rval
      ENDIF
      goto notreg
   
    :five
      for arg,<mm(0),mm(1),mm(2),mm(3),mm(4),mm(5),mm(6),mm(7)>
        IFIDNI <arg>,<item>
          rval = 8
          EXITM
        ENDIF
      ENDM
      IF rval NE 0
        EXITM %rval
      ENDIF
   
      for arg,<st(0),st(1),st(2),st(3),st(4),st(5),st(6),st(7)>
        IFIDNI <arg>,<item>
          rval = 10
          EXITM
        ENDIF
      ENDM
      IF rval NE 0
        EXITM %rval
      ENDIF
      goto notreg
   
    :six
      for arg,<xmm(0),xmm(1),xmm(2),xmm(3),xmm(4),xmm(5),xmm(6),xmm(7)>
        IFIDNI <arg>,<item>
          rval = 16
          EXITM
        ENDIF
      ENDM
      IF rval NE 0
        EXITM %rval
      ENDIF
     
    :eight
      for arg,<edx::eax,ecx::ebx>
        IFIDNI <arg>,<item>
          rval = 8
          EXITM
        ENDIF
      ENDM
      IF rval NE 0
        EXITM %rval
      ENDIF 
   
    :notreg
      EXITM %rval
    ENDM

;---------------------------------------------------


here the informations you find in msdn

Quote
OPATTR, opérateur
08/01/2020 • 2 minutes to read • Edit Online
Syntaxe
Voiraussi
Retourne un mot définissant le modeet la portée del' expression.L'octet de poids faibleest identiqueà l'octet
retourné par .TAPEZ.L'octet de poids fort contient des informations supplémentaires.
Expression opattr,
Informations deréférencesur les opé
It is in french!,you lose nothing...very cool and very short

To test the numbers returned by opattr,use ECHO or %ECHO




Fa is a musical note to play with CL

JK

Thanks, i see, i can use opattr. A result of 36 indicates an immediate value or a constant. This might solve my problem, but it doesn´t answer the original question: How could i make a comparison to a range of charcters in one single line ?

JK

Ok, i found a good solution. I could use another macro: "if is_number(arg) eq 1" ..., where is_number returns <1>, if arg is a number. Inside is_number multiple if, elseif would be necessary, but in the main macro it´s only one line - exactly, what i wanted.

jj2007

#4
include \masm32\include\masm32rt.inc
testme macro arg:req
local c$, ins
  c$ SUBSTR <arg>, 1, 1
  ins INSTR <0123456789>, c$
  if ins
% echo arg is a number
  else
% echo arg is not a number
  endif
endm

.code
start:
  testme 1
  testme eax
  testme 9
  inkey "ok"
  exit
  .err ; for testing: don't let it succeed, we just want to see the echos
end start


Since test is an instruction and therefore cannot be used as a macro name, it means that you didn't test your own macro before asking for help. That won't get you very far :cool:

JK

Hi jj2007,


thanks for your solution! You are right, the code i supplied was pseudo code just for demonstrating the problem. It´s kind of a reduced to the minimum version of what i was working with. Thanks again.


JK


added: currently my code has more than 2000 lines, a bit too much for demonstrating a specific problem ...