News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

type of variable

Started by JK, April 04, 2021, 01:06:22 AM

Previous topic - Next topic

JK

How could i retrieve the type of a variable in code or in a macro?

The "TYPE" operator returns the size of a register or variable in bytes, but there are still ambiguities. A REAL4 returns 4, which is the same as for a DWORD. The same goes for REAL8 and QWORD and for REAL10 and TWORD. A structure of 16 bytes size (e.g RECT) cannot be distinguished from an OWORD.

So how to decide for sure what is what (a structure, a REAL4/8/10, an integer variable of DWORD, QWORD, TWORD or QWORD size)?


JK

Vortex

QuoteTesting for Argument Type and Environment

Macros can expand conditional blocks of code by testing for argument type with the OPATTR operator. OPATTR returns a single word constant that indicates the type and scope of an expression, like this:

OPATTR expression

If expression is not valid or is forward-referenced, OPATTR returns a 0. Otherwise, the return value incorporates the bit flags shown in the table below.

OPATTR serves as an enhanced version of the .TYPE operator, which returns only the low byte (bits 0 - 7) shown in the table. Bits 11 - 15 of the return value are undefined.

Bit Set If expression


0 References a code label

1 Is a memory variable or has a relocatable data label

2 Is an immediate value

3 Uses direct memory addressing

4 Is a register value

5 References no undefined symbols and is without error

6 Is relative to SS

7 References an external label

8 - 10 Has the following language type: 000 - No language type 001 - C 010 - SYSCALL 011 - STDCALL 100 - Pascal 101 - FORTRAN 110 - Basic

http://www.massmind.org/techref/language/masm/masmc09.htm

JK

Thanks, i know "OPATTR", but it cannot solve my problem.

Suppose i have an argument of a procedure and i want to process this argument in a macro. Different types of arguments would require different processing. I would like to tell from the argument alone, what type of argument it is. The "TYPE" operator allows only for a limited decision, i cannot distinguish e.g between "DWORD" and "REAL4", because "4" is returned for both.



jj2007

Check \Masm32\MasmBasic\MasmBasic.inc for the string elseif type(tmp$) eq

nidud

#4
deleted

jj2007

See http://masm32.com/board/index.php?topic=9283.msg101872#msg101872

JK

@nidud,

thanks, exactly what i need. "TYPEID" is ASMC specific i suppose ...


@jj,

thanks a lot, i finally got it! If i use "TYPE" like this:
var_type = TYPE var
then var_type is the same for DWORD, SDWORD and REAL4

but if i use it like this:
  if type(arg) eq DWORD
    echo arg is a    DWORD
  elseif type(arg) eq SDWORD
    echo arg is a    SDWORD
  elseif type(arg) eq REAL4
    echo arg is a    REAL4

then indeed i can keep those types apart - great! With this info i can create something similar to nidud´s TYPEID for ml/ml64 and UASM too.


BTW, where is this behavior documented?

MS´s documentation is lousy (https://docs.microsoft.com/en-us/cpp/assembler/masm/operator-type?view=msvc-160).
The funniest thing about it is this text at the bottom of the page
QuoteIs this page helpful?
Do they really ask this after presenting ... ehm - nothing?


Thanks again to both of you
JK

jj2007

Quote from: JK on April 04, 2021, 08:18:40 PMBTW, where is this behavior documented?

Nowhere afaik - I found it by trial and error. It's needed for Str$(any number) :cool:

nidud

#8
deleted

jj2007

Quote from: nidud on April 05, 2021, 12:03:56 AM
Quote from: JK on April 04, 2021, 08:18:40 PMBTW, where is this behavior documented?

The EQ operator compare type, size, and offset.

a dd 1.0
b dd 2.0

    %echo @CatStr(%(a eq a))
    %echo @CatStr(%(a[4] eq b))
    %echo @CatStr(%(a eq b))
    %echo @CatStr(%(typeof(a) eq typeof(b)))


Error A2102: Symbol not defined : typeof

nidud

#10
deleted

jj2007

Did you read what the post was all about? You are only demonstrating that MASM and AsmC are no longer compatible, thanks to your weird decision to abolish the MASM keyword type...

nidud

#12
deleted

jj2007

Your example is entirely useless. This is what we were discussing:

include \masm32\include\masm32rt.inc

.data
a dd 1
b REAL4 2.0

%echo @CatStr(%typeof(a))
%echo @CatStr(%typeof(b))

.code
start:
  exit
end start


Output: 2x4, which is not helpful when deciding if, for example, fld or fild should be used for these variables. What we were discussing is this sequence, which works like a charm but is not documented:
if type(a) eq DWORD
echo a is a DWORD
elseif type(a) eq REAL4
echo a is a REAL4
else
echo error
endif

if type(b) eq DWORD
echo b is a DWORD
elseif type(b) eq REAL4
echo b is a REAL4
else
echo error
endif


Output:
a is a DWORD
b is a REAL4


I hope you get it now.

Quote from: nidud on April 05, 2021, 07:03:24 AMIf that was true then you wouldn't be consistently lying.

When you have no more arguments, you throw insults. You are a troll.

LiaoMi

#14
Microsoft Corporation - Microsoft Macro Assembler 6.11 Reference Manual_Programmers Guide-Microsoft Corporation (1992)

Testing for Argument Type and Environment
Macros can expand conditional blocks of code by testing for argument type with the
OPATTR operator. OPATTR returns a single word constant that indicates the
type and scope of an expression, like this:

OPATTR expression

If expression is not valid or is forward-referenced, OPATTR returns a 0.
Otherwise, the return value incorporates the bit flags shown in the table below.

OPATTR serves as an enhanced version of the .TYPE operator, which returns
only the low byte (bits 0 – 7) shown in the table. Bits 11 – 15 of the return value are
undefined.
Bit Set If expression
0 References a code label
1 Is a memory variable or has a relocatable data label
2 Is an immediate value
3 Uses direct memory addressing
4 Is a register value
5 References no undefined symbols and is without error
6 Is relative to SS
7 References an external label
8–10 Has the following language type:
◆ 000 — No language type
◆ 001 — C
◆ 010 —SYSCALL
◆ 011 —STDCALL
◆ 100 — Pascal
◆ 101 — FORTRAN
◆ 110 — Basic
A macro can use OPATTR to determine if an argument is a constant, a register, or
a memory operand. With this information, the macro can conditionally generate the
most efficient code depending on argument type.
For example, given a constant argument, a macro can test it for 0. Depending on the
argument's value, the code can select the most effective method to load the value
into a register:

IF CONST
mov bx, CONST ; If CONST > 0, move into BX
ELSE
sub bx, bx ; More efficient if CONST = 0
ENDIF


The second method is faster than the first, yet has the same result (with the
byproduct of changing the processor flags).
The following macro illustrates some techniques using OPATTR by loading an
address into a specified offset register:

load MACRO reg:REQ, adr:REQ
IF (OPATTR (adr)) AND 00010000y ;; Register
IFDIFI reg, adr ;; Don't load register
mov reg, adr ;; onto itself
ENDIF
ELSEIF (OPATTR (adr)) AND 00000100y
mov reg, adr ;; Constant
ELSEIF (TYPE (adr) EQ BYTE) OR (TYPE (adr) EQ SBYTE)
mov reg, OFFSET adr ;; Bytes
ELSEIF (SIZE (TYPE (adr)) EQ 2
mov reg, adr ;; Near pointer
ELSEIF (SIZE (TYPE (adr)) EQ 4
mov reg, WORD PTR adr[0] ;; Far pointer
mov ds, WORD PTR adr[2]
ELSE
.ERR <Illegal argument>
ENDIF
ENDM


TYPE with Forward References

MASM 5.1 evaluates .TYPE on both assembly passes. This means it yields zero on
the first pass and nonzero on the second pass, if applied to an expression that
forward-references a symbol.
MASM 6.1 evaluates .TYPE only on the first assembly pass. As a result, if the
operand references a symbol that has not yet been defined, .TYPE yields a value of
zero. This means that .TYPE, if used in a conditional-assembly construction, may
yield different results in MASM 6.1 than in MASM 5.1.

Comparing Types Using EQ and NE with OPTION M510
With OPTION M510, the assembler converts types to a constant value before
comparisons with EQ and NE. Code types are converted to values of 0FFFFh
(near) or 0FFFEh (far). If OPTION M510 is not enabled, the assembler converts
types to constants only when comparing them with constants. Thus, MASM 6.1
recognizes only equivalent qualified types as equal expressions.

For existing MASM 5.1 code, these distinctions affect only the use of the TYPE
operator in conjunction with EQ and NE. The following example illustrates how
the assembler compares types with and without compatibility mode:
MYSTRUCT STRUC
f1 DB 0
f2 DB 0
MYSTRUCT ENDS
; With OPTION M510
val = (TYPE MYSTRUCT) EQ WORD ; True: 2 EQ 2
val = 2 EQ WORD ; True: 2 EQ 2
val = WORD EQ WORD ; True: 2 EQ 2
val = SWORD EQ WORD ; True: 2 EQ 2
; Without OPTION M510
val = (TYPE MYSTRUCT) EQ WORD ; False: MyStruct NE WORD
val = 2 EQ WORD ; True: 2 EQ 2
val = WORD EQ WORD ; True: WORD EQ WORD
val = SWORD EQ WORD ; False: SWORD NE WORD


Use of Constant and PTR as a Type with OPTION M510
You can use a constant as the left operand to PTR in compatibility mode.
Otherwise, you must use a type expression. With OPTION M510, a constant must
have a value of 1 (BYTE), 2 (WORD), 4 (DWORD), 6 (FWORD), 8
(QWORD) or 10 (TBYTE). The assembler treats the constant as the
parenthesized type. Note that the TYPE operator yields a type expression, but the
SIZE operator yields a constant.
; With OPTION M510
MyData DW 0
mov WORD PTR [bx], 10 ; Legal
mov (TYPE MyData) PTR [bx], 10 ; Legal
mov (SIZE MyData) PTR [bx], 10 ; Legal
mov 2 ptr [bx], 10 ; Legal
; Without OPTION M510
MyData WORD 0
mov WORD PTR [bx], 10 ; Legal
mov (TYPE MyData) PTR [bx], 10 ; Legal
; mov (SIZE MyData) PTR [bx], 10 ; Illegal
; mov 2 PTR [bx], 10 ; Illegal