I looked and I could not find the thread but one of our members posted some useful research that yielded a more useful range of results from the built in masm macro OPATTR which made it possible to distinguish between LOCAL and GLOBAL variable and a number of other useful types.
This is the test macro using this capacity and what I am working on as time allows is enough reusable macro code to be able to routinely build more compex macros that can do more things. What I would be interested with in this macro is if there is anyting else that is worth chasing to add additional return values. I have not for example tested an EXTERNDEF data value.
I used te following code to test for return values with OPATTR
mov eax, opattr(start)
print str$(eax)," entry lbl",13,10
This is the test piece
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
comment * -----------------------------------------------------
Build this template with
"CONSOLE ASSEMBLE AND LINK"
----------------------------------------------------- *
operand_type MACRO arg:REQ
LOCAL result
result = opattr(arg)
IF result eq 37 ;; label, either local or global
EXITM %1
ELSEIF result eq 42 ;; GLOBAL var
EXITM %2
ELSEIF result eq 98 ;; LOCAL var
EXITM %3
ELSEIF result eq 36 ;; immediate operand
EXITM %4
ELSEIF result eq 48 ;; register
EXITM %5
ELSEIF result eq 36 ;; constant as in an equate
EXITM %6
ELSEIF result eq 805 ;; procedure in code
EXITM %7
ELSEIF result eq 933 ;; API call
EXITM %8
ENDIF
EXITM %0 ;; anything else
ENDM
.data
item dd 0
.code
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
call main
inkey
exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
main proc
LOCAL var :DWORD
lbl1:
mov eax, operand_type(non_operand)
print str$(eax),13,10
mov eax, operand_type(lbl1)
print str$(eax),13,10
mov eax, operand_type(item)
print str$(eax),13,10
mov eax, operand_type(var)
print str$(eax),13,10
mov eax, operand_type(edi)
print str$(eax),13,10
mov eax, operand_type(WM_COMMAND)
print str$(eax),13,10
mov eax, operand_type(main)
print str$(eax),13,10
mov eax, operand_type(GetWindowText)
print str$(eax),13,10
ret
main endp
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start
result = opattr(arg)
IF result eq 37 ;; label, either local or global
EXITM %1
Now I'm confused. The documentation says that bit 0 indicates a label. I've always used
if (opattr(arg)) and 01y ;; if it is a label
and it seems to work. What am I missing now??
and it will work. the numbers hutch uses will include definition errors (this symbol is also defined) and whatnot. you wouldnt want to see if a symbol is a label without knowing it exists right?
That's good to know. I always assumed it wouldn't return bit zero on if it was an error, i.e. Masm wouldn't know it was a label if it was an error.
and likewise, it wouldn't know it was a register, etc. if there was an error.
Quote
"If <expression> is not valid or is forward-referenced, OPATTR returns a 0."
So---
Bit Set If
Position <expression>
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
4 Is a register expression
5 References no undefined symbols and is without error
6 Is an SS-relative memory expression
7 References an external label
8-10 Language type: (011=STDCALL)
IF result eq 100101y ;;37 ;; label, either local or global
EXITM %1 ; label, immediate expression, no error
ELSEIF result eq 101010y ;;42 ;; GLOBAL var
EXITM %2 ; memory or data label, direct memory addressing, no error
ELSEIF result eq 1100010y ;;98 ;; LOCAL var
EXITM %3 ; memory or data label, no error, stack variable
ELSEIF result eq 100100y ;;36 ;; immediate operand
EXITM %4 ; immediate expression, no error
ELSEIF result eq 110000y ;;48 ;; register
EXITM %5 ; register, no error
ELSEIF result eq 100100y ;;36 ;; constant as in an equate
EXITM %6 ; immediate expression, no error **** repeat of type 4???????
ELSEIF result eq 1100100101y ;;805 ;; procedure in code STDCALL,
EXITM %7 ; label, immediate, no error, STDCALL
ELSEIF result eq 1110100101y ;;933 ;; API call
EXITM %8 ; label, immediate, no error, external label, STDCALL
ENDIF
EXITM %0 ;; anything else
There was an obvious blunder in the first macro, a duplcate of an immediate operand and a constant that ends up te same thing so I removed one of the duplicates. This is the current form. What I am interested in is if there are any other return values I have missed that would be useful for parameter evaluation.
operand_type MACRO arg:REQ
LOCAL result
result = opattr(arg)
IF result eq 37 ;; label, either local or global
EXITM %1
ELSEIF result eq 42 ;; GLOBAL var
EXITM %2
ELSEIF result eq 98 ;; LOCAL var
EXITM %3
ELSEIF result eq 36 ;; immediate operand or constant
EXITM %4
ELSEIF result eq 48 ;; register
EXITM %5
ELSEIF result eq 805 ;; local procedure in code
EXITM %6
ELSEIF result eq 933 ;; external procedure or API call
EXITM %7
ENDIF
EXITM %0 ;; anything else
ENDM
Hear a quick macro to show you what any type is:
look MACRO i:REQ
local temp
temp TEXTEQU %OPATTR (i)
%ECHO temp
ENDM
you can do things like:
look [esp-5]
And get all the bits that are set.
Hi Hutch-
Just a suggestion, which I tried to hint at unsuccessfully with my previous post- It's much more obvious what you are doing if you use binary notation for the tests, or at least hex. Sorry, just a personal preference when working with bits. Anything to make it easier for someone trying to figure out what's going on.