News:

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

Main Menu

MACROS MASM

Started by Grincheux, December 02, 2015, 09:25:50 PM

Previous topic - Next topic

Grincheux

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

jj2007

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

Grincheux

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

jj2007

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?

Grincheux


Grincheux

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

Grincheux

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'

rrr314159

Hi Grincheux, instead of Temp use this syntax:

IF (OPATTR arg) EQ 48
I am NaN ;)

jj2007


Grincheux


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.