Real4 vs int32 - detect type at assembly and/or runtime?

Started by jj2007, August 30, 2008, 01:03:52 PM

Previous topic - Next topic

jj2007

.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.

NightWare

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" ?

jj2007

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