The MASM Forum

General => The Campus => Topic started by: Grincheux on December 02, 2015, 09:25:50 PM

Title: MACROS MASM
Post by: Grincheux on December 02, 2015, 09:25:50 PM
I would like to test if the <Arg>ument of a macro is a register.
I wrote :


MUL_BY_45 MACRO Arg:REQ
IF( (OPATTR(Arg)AND 4) EQ 0)
lea Arg,[Arg + 8 * Arg]
lea Arg,[Arg + 4 * Arg]
ELSE
.ERR <Invalid Argument>
EXITM
ENDM



The result always is <Invalid Argument>
I never use the macros for once I need them I am blocked.
Please help me
Title: Re: MACROS MASM
Post by: jj2007 on December 02, 2015, 11:02:10 PM
Little test...
include \masm32\include\masm32rt.inc
.686p
.xmm

MUL_BY_45 MACRO Arg:REQ
LOCAL oa, tmp$
  oa = (opattr Arg) AND 127
  tmp$ CATSTR <arg >, <Arg>, < is >, %oa
  % echo tmp$
;   IF( (OPATTR(Arg)AND 4) EQ 0)
; lea Arg,[Arg + 8 * Arg]
; lea Arg,[Arg + 4 * Arg]
;   ELSE
; .ERR <Invalid Argument>
;   ENDIF
  EXITM
ENDM

.data
somevar dd ?
.code
start:
MUL_BY_45 123
MUL_BY_45 eax
MUL_BY_45 xmm0
MUL_BY_45 somevar
MUL_BY_45 offset somevar

  .err
  exit

end start
Title: Re: MACROS MASM
Post by: Grincheux on December 02, 2015, 11:37:05 PM
You don't compute anything.
The argument must be a register, because of LEA
If it is not a register it must return the error message
Title: Re: MACROS MASM
Post by: jj2007 on December 03, 2015, 12:06:58 AM
Quote from: Grincheux on December 02, 2015, 11:37:05 PM
You don't compute anything.

If, instead of asking for spoonfeeding, you would have built the example, you would have seen this in your output window:
arg 123 is 36
arg eax is 48
arg XMM(0) is 48
arg somevar is 42
arg offset somevar is 38

To make it even clearer, here the binary presentation:
00000000000000000000000000100100
10987654321098765432109876543210        123
00000000000000000000000000110000        eax
00000000000000000000000000101010        globalvar
00000000000000000000000000100110        offset globalvar
00000000000000000000000001100010        localvar


Who told you that and 4 yields registers?
Title: Re: MACROS MASM
Post by: Grincheux on December 03, 2015, 03:24:33 AM
Masm manual
Title: Re: MACROS MASM
Post by: Grincheux on December 03, 2015, 03:54:26 AM
Quote
OPATTR/.TYPE Return Value
Bit(s)   Meaning
0   References a label in the code segment if set.
1   References a memory variable or relocatable data object if set.
2   Is an immediate (absolute/constant) value if set.
3   Uses direct memory addressing if set.
4   Is a register name, if set.
5   References no undefined symbols and there is no error, if set.
6   Is an SS: relative reference, if set.
7   References an external name.
8-10   000 - no language type

001 - C/C++ language type

010 - SYSCALL language type

011 - STDCALL language type

100 - Pascal language type

101 - FORTRAN language type

110 - BASIC language type
Title: Re: MACROS MASM
Post by: Grincheux on December 03, 2015, 04:27:36 AM
In fact 48 is the fourth bit not the value 4

MUL_BY_100 MACRO Arg:REQ
Temp = OPATTR(Arg)
IF(Temp EQ 48)
push ecx
mov ecx,Arg ;; Suppose EAX = 10 & ECX = 10
lea Arg,[ecx + 4 * ecx] ;; EAX = ECX + (4 * ECX) = 10 + (4 * 10) = 10 + 40 = 50
lea Arg,[Arg + 4 * Arg] ;; EAX = EAX + (4 * EAX) = 50 + (4 * 50) = 50 + 200 = 250
shl Arg,2 ;; EAX = EAX * 4 = 250 * 4 = 1000
pop ecx
ELSE
.ERR <Invalid argument parameter, not a register>
ENDIF
ENDM


IF(OPATTR(Arg) EQ 48) does not work we need to have a variable 'Temp'
Title: Re: MACROS MASM
Post by: rrr314159 on December 03, 2015, 04:38:54 AM
Hi Grincheux, instead of Temp use this syntax:

IF (OPATTR arg) EQ 48
Title: Re: MACROS MASM
Post by: jj2007 on December 03, 2015, 05:05:26 AM
Quote from: Grincheux on December 03, 2015, 04:27:36 AM
In fact 48 is the fourth bit not the value 4
:t
Title: Re: MACROS MASM
Post by: Grincheux on December 03, 2015, 06:42:51 AM

MUL_BY_100 MACRO Arg:REQ, redx:=<edx>

IF (OPATTR Arg) EQ 48
IFIDN <Arg>,<edx>
.ERR <EDX register value would be overwritten by macro>
EXITM
ENDIF

IFIDN <Arg>,<EDX>
.ERR <EDX register value would be overwritten by macro>
EXITM
ENDIF

push redx
mov redx,Arg ;; Suppose EAX = 10 & ECX = 10
lea Arg,[redx + 4 * redx] ;; EAX = ECX + (4 * ECX) = 10 + (4 * 10) = 10 + 40 = 50
lea Arg,[Arg + 4 * Arg] ;; EAX = EAX + (4 * EAX) = 50 + (4 * 50) = 50 + 200 = 250
shl Arg,2 ;; EAX = EAX * 4 = 250 * 4 = 1000
pop redx

Echo *** MUL_BY_100 : Result in Arg ***
ELSE
.ERR <Invalid argument parameter, not a register>
ENDIF

ENDM


In fact when

IFIDN <Arg>,<edx>
.ERR <EDX register value would be overwritten by macro>
EXITM
ENDIF


Initially redx is equal to EDX
I would like to replace redx by ecx
And I would like to uppercase the Arg.
Because eax != EAX

The goal would be to replace use ECX when EDX is the Arg and EDX when ECX is the Arg. For this reason I use REDX

I could use a local variable but if we are not in a PROC statment, a label for example, I cant do it.