As discussed earlier in this thread (http://www.masm32.com/board/index.php?topic=14253.msg113377#msg113377), 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 (http://www.japheth.de/JWasm.html):
JWasm: offset MyString is an unsigned dword
If Japheth has time to do it, this will probably be fixed in the next release.
just an littel addition:
...
IF @Version GE 800
IF type (arg) EQ SQWORD
...
ENDIF
...
:P
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
Quote from: jj2007 on July 01, 2010, 08:20:06 AMWhat about this solution?
:thumbu
but why declaring it as an pointer?
qWord
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
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.
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
:U