.data?
MyReal4 REAL4 ?
MyInt32 dd ?
Is there any way to know the difference, either at assembly (for a macro) or at runtime? Size is 4 for both, of course.
Opattr seems to fail on this. Any advice appreciated.
none i know, "real4 equ dword" and all values are possible, so i don't see how to proceed... :(
EDIT : with macros, maybe by testing if the value finish with "f" ?
Yeah, I think some decoration is needed. Here is the output of a test:
GetArgType @MyReal4 ; decoration as last resort to distinguish Real4 from DWORD
GetArgType MyReal8
GetArgType MyReal10
GetArgType MyInt4
GetArgType MyInt2
GetArgType MyStr ; ambiguous:
GetArgType MyStr8 ; should be a string...
GetArgType My$ ; suffix means pointer to a string
GetArgType ecx
GetArgType cx
GetArgType cl
GetArgType ch
GetArgType 12345
GetArgType 123.45
GetArgType -123.45e33
GetArgType "This is a string"
GetArgType 'These are "double quotes"'
> MyReal4 is REAL4
> MyReal8 is REAL8
> MyReal10 is REAL10
> MyInt4 is DWORD
> MyInt2 is WORD
> MyStr is BYTE <--- ok but only by chance
> MyStr8 is REAL8 <---wrong
> My$ is ptr to STRING
> ecx is DWORD reg
> cx is WORD reg
> cl is BYTE reg
> ch is BYTE reg
> 12345 is immediate DWORD
> 123.45 is immediate Real8
> -123.45e33 is immediate Real8
> "This is a string" is quoted string
> 'These are "double quotes"' is quoted string
So I use @MyReal4 to indicate it's a Real4 (rare case), and good ol' ThisIsMy$ for indicating it's a pointer to a string.
Any better ideas?
It's a stupid problem because at assembly time Masm knows pretty well the true type of all these args, it just won't tell us.
include \masm32\include\masm32rt.inc
; OPATTR guide
; Bit Set If...
; 0 References a code label
; 1 Is a memory expression or has a relocatable data label
; 2 Is an immediate expression
; 3 Uses direct memory addressing, i.e. is an absolute memory reference
; 4 Is a register expression
; 5 References no undefined symbols and is without error
; 6 References a stack location (usually a LOCAL variable or parameter)
; 7 References an external label
; 8-10 Language type (0=no type)
; 76543210
atImmediate equ 36 ; 00100100
atGlobal equ 42 ; 00101010
atRegister equ 48 ; 00110000
atLocal equ 98 ; 01100010
GetArgType MACRO argX
LOCAL ArgType, ArgSize, tmp$, aw, arg, fc$, t$, nustr, quotes, FF$, nu8, dot
ArgSize = -1
arg equ <argX>
fc$ SUBSTR <argX>, 1, 1
ifidn <@>, fc$
t$ equ <REAL4>
arg SUBSTR arg, 2
ArgSize = 4 ;; REAL4
endif
quotes INSTR <argX>, <">
if quotes ne 1
quotes INSTR <argX>, <'>
endif
if quotes eq 1
FF$ equ <offset nustr> ;; we pass it as FF$
.data
nustr db argX, 0 ;; write arg to .DATA section
.code
ArgSize SIZESTR <nustr>
t$ equ <quoted string>
endif
dot INSTR <argX>, <$>
if dot eq @SizeStr(<argX>)
t$ equ <ptr to STRING>
ArgSize = 4
endif
dot INSTR <argX>, <.>
if dot
ptrR8 equ <offset nu8> ;; we pass it as FF$
.data
nu8 REAL8 argX ;; write arg to .DATA section
.code
ArgSize = 8
t$ equ <immediate Real8>
endif
ArgType=(opattr(arg)) AND 127 ;; 0 no vn$, 36 immediate, 42 global, 48 CPU register, 98 local
if ArgType eq atLocal or ArgType eq atGlobal
if ArgSize eq -1
ArgSize = SIZEOF arg ; 4 for DWORD, 10 for REAL10
; tmp$ CATSTR <New size is >, %ArgSize
; % echo tmp$
if ArgSize eq 8
t$ equ <REAL8>
elseif ArgSize eq 10
t$ equ <REAL10>
elseif ArgSize eq 4
t$ equ <DWORD>
elseif ArgSize eq 2
t$ equ <WORD>
else
t$ equ <BYTE>
endif
endif
elseif ArgType eq atImmediate
; tmp$ CATSTR <Immediate passed: >, arg
; % echo tmp$
ArgSize = 4 ;; immediate integer
ArgType = atRegister ;; we cheat, pushing an immediate is like push eax
t$ equ <immediate DWORD>
elseif ArgType eq atRegister
ArgSize SIZESTR arg
if ArgSize eq 3
ArgSize = 4 ;; e?x uses fild, so we flag an integer
t$ equ <DWORD reg>
else
ArgSize INSTR arg, <x>
if ArgSize eq 0
ArgSize=1 ;; al, else ax
t$ equ <BYTE reg>
else
t$ equ <WORD reg>
endif
endif
elseif ArgSize eq -1
t$ equ <unknown>
endif
; tmp$ catstr arg , < is >, %ArgType, <, >, t$, < with size >, %ArgSize
tmp$ catstr <!> >, arg , < is >, t$
% echo tmp$
ENDM
.data
MyReal4 REAL4 1.234
MyReal8 REAL8 1.234
MyReal10 REAL10 1.234
MyInt4 dd 12345678
MyInt2 dw 12345
MyStr8 db "Hi guys", 0 ; 8 bytes - trouble ahead!
MyStr db "Hello, I am a loooong string", 0
My$ db "Hello, I am a loooong string", 0
.code
AppName db "Masm32 console test", 0
start: echo
echo
GetArgType @MyReal4 ; decoration as last resort to distinguish Real4 from DWORD
GetArgType MyReal8
GetArgType MyReal10
GetArgType MyInt4
GetArgType MyInt2
GetArgType MyStr ; ambiguous:
GetArgType MyStr8 ; should be a string...
GetArgType My$ ; suffix means pointer to a string
GetArgType ecx
GetArgType cx
GetArgType cl
GetArgType ch
GetArgType 12345
GetArgType 123.45
GetArgType -123.45e33
GetArgType "This is a string"
GetArgType 'These are "double quotes"'
echo
echo
echo
.err ; <---- to show macro debug output
inkey "Press any key to say bye bye..."
exit
end start