News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

MACRO for determining the type of a variable

Started by jj2007, July 01, 2010, 07:46:20 AM

Previous topic - Next topic

jj2007

As discussed earlier in this thread, it is difficult but not impossible to get not only the size but also the type of a variable. For example, DWORD and REAL4 have the same size but different uses. The following macro demonstrates how to do it; it will not assemble but rather show the characteristics of variables in the assembly output window.

include \masm32\include\masm32rt.inc

TrueType MACRO arg
if type (arg) eq DWORD
echo &arg& is an unsigned dword ;; <<<<<<<<<<<<<<
elseif type (arg) eq REAL8
echo &arg& is a real 8
elseif type (arg) eq REAL4
echo &arg& is a real 4
elseif type (arg) eq REAL10
echo &arg& is a real 10
elseif type (arg) eq BYTE
echo &arg& is a byte array
elseif type (arg) eq SDWORD
echo &arg& is a signed dword
elseif type (arg) eq WORD
echo &arg& is an unsigned word
elseif type (arg) eq SWORD
echo &arg& is a signed word
elseif type (arg) eq QWORD
echo &arg& is an unsigned Qword
else
oa = (opattr arg) AND 127
if oa eq 38
is INSTR <arg>, < >
tmp$ CATSTR <arg>, < is memory with a size of >, %sizeof @SubStr(<arg>, is+1) ;; <<<<<<<<<<<<<<
% echo tmp$
else
; echo no idea what &arg& is...
oa = (opattr arg) AND 127
tmp$ CATSTR <arg>, < has an opattr of >, %oa
% echo tmp$
endif
endif
ENDM

.data?
MyWord word ?
MySword sword ?
MyDword dd ?
MySdword sdword ?
MyQword qword ?
MyReal4 REAL4 ?
MyReal8 REAL8 ?
MyReal10 REAL10 ?
MyTbyte TBYTE ?

.data
MyStringPtr dd MyString
MyString db "That's a 28 character string", 0

.code
start:
echo
TrueType MyReal4
TrueType MyReal8
TrueType MyReal10
TrueType MyDword
TrueType MySdword
TrueType MyWord
TrueType MySword
TrueType MyQword
TrueType MyStringPtr
TrueType MyString
TrueType offset MyString ;; <<<<<<<<<<<<<<
TrueType eax
TrueType "test"
TrueType [esp]
TrueType [esp+20]
TrueType [ebp]
TrueType [ebp+20]
TrueType [ebx]
TrueType [ebx+20]
TrueType MyTbyte
echo
.err
ret
end start


Output with Masm:
QuoteMyReal4 is a real 4
MyReal8 is a real 8
MyReal10 is a real 10
MyDword is an unsigned dword
MySdword is a signed dword
MyWord is an unsigned word
MySword is a signed word
MyQword is an unsigned Qword
MyStringPtr is an unsigned dword
MyString is a byte array
offset MyString is memory with a size of 29
eax is an unsigned dword
"test" has an opattr of 36
[esp] has an opattr of 98
[esp+20] has an opattr of 98
[ebp] has an opattr of 98
[ebp+20] has an opattr of 98
[ebx] has an opattr of 34
[ebx+20] has an opattr of 34
MyTbyte has an opattr of 42
The test marked in red still yields a different result when using the latest JWasm build, 2.03:
JWasm: offset MyString is an unsigned dword
If Japheth has time to do it, this will probably be fixed in the next release.

qWord

just an littel addition:
...
IF @Version GE 800
IF type (arg) EQ SQWORD
...
ENDIF
...

:P
FPU in a trice: SmplMath
It's that simple!

jj2007

Good idea, but it causes some trouble with the elseif logic. What about this solution?

include \masm32\include\masm32rt.inc ; Masm32 thread

ifndef SQWORD
SQWORD TYPEDEF PTR QWORD
endif
TrueType MACRO arg
if type (arg) eq DWORD
echo &arg& is an unsigned dword ;; <<<<<<<<<<<<<<
elseif type (arg) eq REAL8
echo &arg& is a real 8
elseif type (arg) eq REAL4
echo &arg& is a real 4
elseif type (arg) eq REAL10
echo &arg& is a real 10
elseif type (arg) eq BYTE
echo &arg& is a byte array
elseif type (arg) eq SDWORD
echo &arg& is a signed dword
elseif type (arg) eq WORD
echo &arg& is an unsigned word
elseif type (arg) eq SWORD
echo &arg& is a signed word
elseif type (arg) eq QWORD
echo &arg& is an unsigned Qword
elseif type (arg) eq SQWORD
echo &arg& is a SIGNED QWORD
else
oa = (opattr arg) AND 127
if oa eq 38
is INSTR <arg>, < >
tmp$ CATSTR <arg>, < is memory with a size of >, %sizeof @SubStr(<arg>, is+1) ;; <<<<<<<<<<<<<<
% echo tmp$
else
; echo no idea what &arg& is...
oa = (opattr arg) AND 127
tmp$ CATSTR <arg>, < has an opattr of >, %oa
% echo tmp$
endif
endif
ENDM

.data?
MyWord word ?
MySword sword ?
MyDword dd ?
MySdword sdword ?
MyQword qword ?
MySQword SQWORD ?
MyReal4 REAL4 ?
MyReal8 REAL8 ?
MyReal10 REAL10 ?
MyTbyte TBYTE ?

.data
MyStringPtr dd MyString
MyString db "That's a 28 character string", 0

.code
start:
echo
TrueType MyReal4
TrueType MyReal8
TrueType MyReal10
TrueType MyDword
TrueType MySdword
TrueType MyWord
TrueType MySword
TrueType MyQword
TrueType MySQword ; <<<<<<<<<<<<
TrueType MyStringPtr
TrueType MyString
TrueType offset MyString ;; <<<<<<<<<<<<<<
TrueType eax
TrueType "test"
TrueType [esp]
TrueType [esp+20]
TrueType [ebp]
TrueType [ebp+20]
TrueType [ebx]
TrueType [ebx+20]
TrueType MyTbyte
echo
.err
ret
end start

qWord

FPU in a trice: SmplMath
It's that simple!

Ficko

SQWORD is not fully implemented in MASM. :(


.686p
.model flat, stdcall
option casemap :none
MySUB PROTO :SQWORD
.data
MyData SQWORD ?
.code
start:
invoke MySUB,MyData
end start


Quote
INVOKE argument type mismatch : argument : 1

jj2007

Quote from: qWord on July 01, 2010, 08:24:58 AM
but why declaring it as an pointer?

Without the PTR, earlier versions of Masm show no effect, i.e. (mlv615) "MySQword is an unsigned Qword" instead of "MySQword is a SIGNED QWORD". With ML 9.0 and JWasm it works without the PTR, too.

drizz

Quote from: jj2007 on July 01, 2010, 07:46:20 AM

...
oa = (opattr arg) AND 127
if oa eq 38
...
"test" has an opattr of 36
[esp] has an opattr of 98
[esp+20] has an opattr of 98
[ebp] has an opattr of 98
[ebp+20] has an opattr of 98
[ebx] has an opattr of 34
[ebx+20] has an opattr of 34
MyTbyte has an opattr of 42


that's just ugly to look at  :snooty:

Here something more informative.
?IsLbl macro op:req
exitm %( ( (.TYPE (op)) SHR 0 ) AND 1)
endm

?IsMem macro op:req
exitm %( ( (.TYPE (op)) SHR 1 ) AND 1)
endm

?IsImm macro op:req
exitm %( ( (.TYPE (op)) SHR 2 ) AND 1)
endm

?IsOffs macro op:req
exitm %( ( (.TYPE (op)) AND 00000110b ) EQ 00000110b)
endm

?IsSSRel macro op:req
exitm %( ( (.TYPE (op)) SHR 6 ) AND 1)
endm

?IsMemd macro op:req
exitm %( ( (.TYPE (op)) SHR 3 ) AND 1)
endm

?IsReg macro op:req
exitm %( ( (.TYPE (op)) SHR 4 ) AND 1)
endm

?IsExtrn macro op:req
exitm %( ( (.TYPE (op)) SHR 7 ) AND 1)
endm

?Language macro op:req
LOCAL lang
lang = ( (OPATTR (op)) SHR 8 ) AND 111b
if lang eq 0
exitm <>
elseif lang eq 1
exitm <C>
elseif lang eq 2
exitm <SYSCALL>
elseif lang eq 3
exitm <STDCALL>
elseif lang eq 4
exitm <PASCAL>
elseif lang eq 5
exitm <FORTRAN>
elseif lang eq 6
exitm <BASIC>
else; lang eq 7
exitm <UNKNOWN>
endif
exitm <>
endm

?Type macro typ:req
LOCAL typtxt
typtxt equ <>
for arg,<BYTE,SBYTE,WORD,SWORD,FWORD,DWORD,SDWORD,QWORD,SQWORD,OWORD,REAL4,REAL8,REAL10,TBYTE>
%if (type (typ)) eq arg
typtxt equ arg
exitm <>
endif
endm
exitm typtxt
endm

@RadixStr macro value:req, nradix:req
LOCAL rstr, rval
rval = value
pushcontext radix
.radix nradix
%rstr textequ <@CatStr(%(rval))>
popcontext radix
exitm rstr
endm

@RadixStrlz macro value:req, nradix:req, lzcnt:req
LOCAL i, rstr
%rstr textequ <@RadixStr(value, nradix)>
i sizestr rstr
while i lt lzcnt
rstr catstr <0>,rstr
i = i + 1
endm
exitm rstr
endm

@BinStr macro value:req
exitm @RadixStrlz(value,2d,0)
endm

@BinStrlz macro value:req, lzcnt:req
exitm @RadixStrlz(value,2d,lzcnt)
endm

@DecStr macro value:req
exitm @RadixStrlz(value,10d,0)
endm

@DecStrlz macro value:req, lzcnt:req
exitm @RadixStrlz(value,10d,lzcnt)
endm

@HexStr macro value:req
exitm @RadixStrlz(value,16d,0)
endm

@HexStrlz macro value:req, lzcnt:req
exitm @RadixStrlz(value,16d,lzcnt)
endm

?OpAttr macro op:req
%echo @BinStrlz(opattr op, 11) OPATTR op
echo |_/||||||||
echo |  |||||||°- References a code label
echo |  ||||||°-- Is a memory variable or has a relocatable data label
echo |  |||||°--- Is an immediate value
echo |  ||||°---- Uses direct memory addressing
echo |  |||°----- Is a register value
echo |  ||°------ References no undefined symbols and is without error
echo |  |°------- Is relative to SS
echo |  °-------- References an external label
echo |_
echo | | Has the following language type:
echo | |
echo 000 — No language type
echo 001 — C
echo 010 — SYSCALL
echo 011 — STDCALL
echo 100 — PASCAL
echo 101 — FORTRAN
echo 110 — BASIC
endm

?Analyze macro anything
local i
ifb <anything>
exitm
endif
echo
% echo INPUT        : anything
if ?IsMem(anything)
if ?IsExtrn(anything)
echo OPERAND TYPE : MEMORY (EXTERNAL)
else
echo OPERAND TYPE : MEMORY
endif
if ?IsMemd(anything)
if (LENGTHOF anything) eq 0
% echo TYPE         : ?Type(anything) LABEL
% echo SIZE         : @DecStr(SIZEOF(TYPE(anything)))
echo LENGTH       : 0
else
% echo TYPE         : ?Type(anything)
% echo SIZE         : @DecStr(SIZEOF(TYPE(anything)))
% echo LENGTH       : @DecStr(LENGTHOF anything)
endif
elseif ?IsImm(anything)
echo TYPE         : OFFSET
% echo SIZE         : @DecStr(@WordSize)
echo LENGTH       : 1
else; mem or ss relative
echo TYPE         : N/A
echo SIZE         : N/A
echo LENGTH       : N/A
endif
elseif ?IsReg(anything)
echo OPERAND TYPE : REGISTER
% echo TYPE         : ?Type(anything)
% echo SIZE         : @DecStr(SIZEOF(TYPE(anything)))
elseif ?IsImm(anything)
echo OPERAND TYPE : IMMEDIATE
if ?IsLbl(anything)
echo TYPE         : CODE LABEL
else
% echo TYPE         : N/A
endif
% echo SIZE         : N/A
endif
ifnb ?Language(anything)
% echo LANGUAGE     : ?Language(anything)
else
echo LANGUAGE     : N/A
endif
; echo OPATTR       :
; ?OpAttr anything
endm


?Analyze stuff
?OpAttr stuff

:eek
The truth cannot be learned ... it can only be recognized.