I'm slowly learning this macro stuff. This snipet from the MASM manual confuses me:


IF CONST
mov bx, CONST ; If CONST > 0, move into BX
ELSE
sub bx, bx ; More efficient if CONST = 0
ENDIF

IF CONST(nothing)???

Where is it specify to test IF CONST>0? To me it looks like IF CONST=true, or something like that.

This make sense to me:


oad MACRO reg:REQ, adr:REQ
IF (OPATTR (adr)) AND 00010000y ;; Register
IFDIFI reg, adr ;; Don??t load register
mov reg, adr ;; onto itself
ENDIF
ELSEIF (OPATTR (adr)) AND 00000100y
mov reg, adr ;; Constant
ELSEIF (TYPE (adr) EQ BYTE) OR (TYPE (adr) EQ SBYTE)
mov reg, OFFSET adr ;; Bytes
ELSEIF (SIZE (TYPE (adr)) EQ 2
mov reg, adr ;; Near pointer
ELSEIF (SIZE (TYPE (adr)) EQ 4
mov reg, WORD PTR adr[0] ;; Far pointer
mov ds, WORD PTR adr[2]
ELSE
.ERR <Illegal argument>
ENDIF
ENDM


Thanks.
Posted on 2004-06-07 14:53:49 by ThoughtCriminal
"IF CONST" returns false when CONST is false, i.e. zero, and true when CONST is true, i.e. nonzero, what means greater than zero: if CONST > 0 ;)
In other words, CONST is interpreted as boolean, even though is it symbolic constant. Someone says it is bad coding practice, other says it's nothing wrong. As you can see, it can confuses you. Better would be
IF CONST GT 0

Hope it helps.
Posted on 2004-06-07 15:51:57 by MazeGen
Test for dword ptr and error if offset?

The meaning of the bits are not all clear to me:


Bit

Set If expression

0 References a code label

1 Is a memory variable or has a relocatable data label

2 Is an immediate value

3 Uses direct memory addressing

4 Is a register value

5 References no undefined symbols and is without error

6 Is relative to SS

7 References an external label

8 ? 10

Has the following language type:

000 ? No language type

001 ? C

010 ? SYSCALL

011 ? STDCALL

100 ? Pascal

101 ? FORTRAN

110 ? Basic

My silly test code: I want i:REQ to always be an offset and j:REQ to be a reg,imm,or dword ptr

foo and bar are both structures



_test MACRO i:REQ, j:REQ
mov eax,dword ptr[i]
push eax
mov eax,dword ptr[eax]
IF ((OPATTR (j)) AND 00010000y) OR ((OPATTR (j)) AND 00000100y)
add eax,j
ELSEIF (OPATTR (j)) AND 00001000y

add eax,dword ptr[j]
ELSE
.ERR <error>
ENDIF
pop edx
pushfd
mov dword ptr[edx],eax
pop dword ptr[edx+8]
ENDM


I'm trying to get any valid call to look like:

_test offset foo, dword ptr bar

_test offset foo, (reg)

_test offset foo, (imm)

So far the only thing I made error is:

_test offset foo, bar

Is it even possible to test if the macro parameter is an offset or a pointer?

Thanks.
Posted on 2004-06-08 16:18:46 by ThoughtCriminal
I had the same problem with addr. The only solution I've found...

$IsAddr MACRO Operand:REQ

IF @SizeStr(<Operand>) GT 5
IFIDNI <addr >, @SubStr(<Operand>, 1 , 5)
EXITM <-1>
ENDIF
ENDIF
EXITM <0>
ENDM

InitializeListHead MACRO ListHead:REQ
local a
IF $IsAddr(ListHead)
a SUBSTR <ListHead>, 6
IF (OPATTR (a)) AND 01000000y ;; Is relative to SS
lea eax, a
ELSE
mov eax, offset a
ENDIF
. . .
ENDM



You can't recognize the type of <offset something> or <dword ptr something> using OPATTR because <offset something> or <dword ptr something> have no type! You can use OPATTR for something not for <offset something>.

Try this (untested):

$IsOffset MACRO Operand:REQ

IF @SizeStr(<Operand>) GT 7
IFIDNI <offset >, @SubStr(<Operand>, 1 , 7)
EXITM <-1>
ENDIF
ENDIF
EXITM <0>
ENDM

$IsDwordPtr MACRO Operand:REQ
IF @SizeStr(<Operand>) GT 10
IFIDNI <dword ptr >, @SubStr(<Operand>, 1 , 10)
EXITM <-1>
ENDIF
ENDIF
EXITM <0>
ENDM

_test MACRO i:REQ
IF $IsOffset(i)
;; offset
ELSEIF $IsDwordPtr(i)
;; dword ptr
ELSE
.ERR
ENDIF
ENDM
Posted on 2004-06-09 17:35:37 by Four-F
Thanks. In another post I made a small mcro to look at the output of OPATTR with different types etc:
http://www.asmcommunity.net/board/index.php?topic=18513


look MACRO i:REQ
local temp
temp TEXTEQU %OPATTR (i)
%ECHO temp
ENDM



note foo and bar are STRUCTs:

look dword ptr foo ----> 42 or 101010b ;bit 0 References a code label
;bit 3 Uses direct memory addressing
;bit 5 References no undefined symbols and is without error

look offset bar ----> 38 or 100110 ;bit 1 Is a memory variable or has a relocatable data label
;bit 2 Is an immediate value<----This looks strange.
;bit 5 References no undefined symbols and is without error


look bar ----> 42 ; same as dword ptr foo
look bar.i ----> 42 ; same as dword ptr foo

I tried it in some code and it seems there is a difference.
Posted on 2004-06-09 23:34:59 by ThoughtCriminal
I'm following this thread with interest, this will be good improvement to many existing macros :)


;bit 2 Is an immediate value<----This looks strange.

IMHO it's correct, an OFFSET is calculated at assembly time, and is also an immediate value. For example:

add eax,offset foobar ;here "offset foobar" is an immediate like any other numeric value
Posted on 2004-06-10 12:19:35 by QvasiModo
Yes I had to think about for a bit then I realized why an offest was also marked as immediate.

Its an immediate offset :grin:
Posted on 2004-06-10 13:11:27 by ThoughtCriminal
Heres my test code using what I have learned:


_test MACRO i:REQ, j:REQ
local err_val

IF (OPATTR (i)) EQ 38
mov eax,[(i)]
ELSE
err_val TEXTEQU %OPATTR (i)
%ECHO err_val
.ERR <First parameter is not an offset>
ENDIF

push eax
mov eax,dword ptr[eax]

IF ((OPATTR (j)) EQ 36) OR ((OPATTR (j)) EQ 48)
add eax,j
ELSEIF ((OPATTR (j)) EQ 42)
add eax,dword ptr[j]
ELSE
err_val TEXTEQU %OPATTR (i)
%ECHO err_val
.ERR <Second parameter is not pointer, register or immediate>
ENDIF
pop edx
pushfd
mov dword ptr[edx],eax
pop dword ptr[edx+8]
ENDM

The first if block test if it is an offset type. If it is not, print what error type was entered,
and give an informative error.

The second block tests first if it is a register or immediate type,
if not test if it is a pointer type, if not print what error type was entered, and give
an informative error.

Even better might be to make some equates:

IMMEDIATE_TYPE = 36

REGISTER_TYPE = 48

GENERAL_TYPE = 42 ;data, structs,declared labels, and dword ptr are all same type.

So you cant test if it is a structure or just dword data in your data section with OPATTR .

Another problem is you cannot test which reg is used with OPATTR. If eax is used in the above,
you wont get what you expect.

Thanks.

Oops, forgot to post macro in this thred that I used to get type values from:


look MACRO i:REQ
local temp
temp TEXTEQU %OPATTR (i)
%ECHO temp
ENDM

Just use like:

look eax

look offset foobar
Posted on 2004-06-10 14:18:40 by ThoughtCriminal