News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

ENUM example 2 and request for comments. (RFC2) :)

Started by hutch--, January 06, 2012, 01:54:45 AM

Previous topic - Next topic

hutch--

I have been pottering around the C/C++ documentation on "typedef enum" and it gives the appearance of being a clapped out old technique for replacing long lists of C #define statements and while I probably would not write MASM code using such an ancient technique, the SDK header files have a reasonable number of structures that have "enum" members and without some technique to emulate the "enum" format those structures cannot be used in MASM.

The unallocated form of structures are sequentiall numbered based on the data size, 1 for BYTE, 2 for WORD etc .... which appears to be an internal method of MASM keeping track of the size of structure members but it does not lend itself well to non-sequential nuberings so i have tried out another method of initialised structure members but it has the limitation that it must be allocated in the initialised data section. This is the test piece.


IF 0  ; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                      Build this template with "CONSOLE ASSEMBLE AND LINK"
ENDIF ; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    include \masm32\include\masm32rt.inc

    ENUM TEXTEQU <STRUCT>

    POWERS_OF_2 ENUM
      item0 dd ?
      item1 dd ?
      item2 dd ?
      item3 dd ?
      item4 dd ?
      item5 dd ?
      item6 dd ?
      item7 dd ?
      item8 dd ?
      item9 dd ?
      item10 dd ?
      item11 dd ?
    POWERS_OF_2 ENDS
    POWERS_OF_2_UNUM_VALUES_@@@@ equ <0,1,2,4,8,16,32,64,128,256,512,1024>

    NEWSTRUCT STRUCT
      somevalue    dd ?
      pow POWERS_OF_2   <POWERS_OF_2_UNUM_VALUES_@@@@>
      anothervalue dd ?
    NEWSTRUCT ENDS

    .data
      po2 NEWSTRUCT <>  ; initialised ENUM data must be in initialised data section

    .code

start:
   
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    call main
    inkey
    exit

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

main proc

    print ustr$(po2.pow.item0),13,10
    print ustr$(po2.pow.item1),13,10
    print ustr$(po2.pow.item2),13,10
    print ustr$(po2.pow.item3),13,10
    print ustr$(po2.pow.item4),13,10
    print ustr$(po2.pow.item5),13,10
    print ustr$(po2.pow.item6),13,10
    print ustr$(po2.pow.item7),13,10
    print ustr$(po2.pow.item8),13,10
    print ustr$(po2.pow.item9),13,10
    print ustr$(po2.pow.item10),13,10
    print ustr$(po2.pow.item11),13,10

    ret

main endp


; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

end start


The output is as follows.



0
1
2
4
8
16
32
64
128
256
512
1024
Press any key to continue ...


Now what I wonder is if there are any problems in performing this action where the data size is set where properly an "enum" data type is effectively no sized equates. I note that the later C++ header files embed the enum values in a structure and are usually typed as ULONG or similar 32 bit DWORD sized values.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

donkey

As far as the Windows headers are concerned I have yet to find an enumerated type that is not a DWORD.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

MichaelW

When I was experimenting with the first version I created two small C apps to see what the Microsoft compilers do with enumerates.

//=============================================================================
#include <windows.h>
#include <conio.h>
#include <stdio.h>
#include <AccCtrl.h>
//=============================================================================
/*
typedef enum _SE_OBJECT_TYPE
{
    SE_UNKNOWN_OBJECT_TYPE = 0,
    SE_FILE_OBJECT,
    SE_SERVICE,
    SE_PRINTER,
    SE_REGISTRY_KEY,
    SE_LMSHARE,
    SE_KERNEL_OBJECT,
    SE_WINDOW_OBJECT,
    SE_DS_OBJECT,
    SE_DS_OBJECT_ALL,
    SE_PROVIDER_DEFINED_OBJECT,
    SE_WMIGUID_OBJECT,
    SE_REGISTRY_WOW64_32KEY
} SE_OBJECT_TYPE;

typedef struct  _OBJECTS_AND_NAME_A
{
    DWORD          ObjectsPresent;
    SE_OBJECT_TYPE ObjectType;
    LPSTR    ObjectTypeName;
    LPSTR    InheritedObjectTypeName;
    LPSTR    ptstrName;
} OBJECTS_AND_NAME_A, *POBJECTS_AND_NAME_A;
*/

int main(void)
{
    OBJECTS_AND_NAME_A oana;

    oana.ObjectsPresent = 123;
    oana.ObjectType = SE_UNKNOWN_OBJECT_TYPE;
    printf("%d\t%d\t",oana.ObjectsPresent,oana.ObjectType);
    printf("%d\n",sizeof(oana.ObjectType));

    oana.ObjectsPresent = 123;
    oana.ObjectType = SE_FILE_OBJECT;
    printf("%d\t%d\t",oana.ObjectsPresent,oana.ObjectType);
    printf("%d\n",sizeof(oana.ObjectType));

    oana.ObjectsPresent = 123;
    oana.ObjectType = SE_SERVICE;
    printf("%d\t%d\t",oana.ObjectsPresent,oana.ObjectType);
    printf("%d\n",sizeof(oana.ObjectType));

    // With C, even when the enumeration named, you can substitute
    // values that are not defined in the the enumeration.
    oana.ObjectsPresent = 123;
    oana.ObjectType = -1;
    printf("%d\t%d\t",oana.ObjectsPresent,oana.ObjectType);
    printf("%d\n",sizeof(oana.ObjectType));

    getch();
    return 0;
}


123     0       4
123     1       4
123     2       4
123     -1      4


//=============================================================================
#include <windows.h>
#include <conio.h>
#include <stdio.h>
//=============================================================================

/*
typedef enum  {
  BIDI_NULL     = 0,
  BIDI_INT      = 1,
  BIDI_FLOAT    = 2,
  BIDI_BOOL     = 3,
  BIDI_STRING   = 4,
  BIDI_TEXT     = 5,
  BIDI_ENUM     = 6,
  BIDI_BLOB     = 7
} BIDI_TYPE;

typedef struct _BINARY_CONTAINER {
  DWORD  cbBuf;
  LPBYTE  pData;
} BINARY_CONTAINER, *PBINARY_CONTAINER;

typedef struct _BIDI_DATA {
  DWORD  dwBidiType;
  union {
     BOOL  bData;
     INT  iData;
     LPWSTR  sData;
     FLOAT  fData;
     BINARY_CONTAINER  biData;
  } u;
} BIDI_DATA, *PBIDI_DATA, *LPBIDI_DATA;
*/
//
// This causes redefinition errors because the names of the enumerators
// must be unique within the scope where the enum is defined.
//
/*
typedef enum
{
    BIDI_NULL     = 0,
    BIDI_INT      = 1,
    BIDI_FLOAT    = 2,
    BIDI_BOOL     = 3,
    BIDI_STRING   = 4,
    BIDI_TEXT     = 5,
    BIDI_ENUM     = 6,
    BIDI_BLOB     = 7
} SOME_OTHER_NAME;
*/

int main(void)
{

    BIDI_DATA bid;

    bid.dwBidiType = BIDI_NULL;
    printf("BIDI_NULL %d\n",bid.dwBidiType);

    bid.dwBidiType = BIDI_INT;
    printf("BIDI_INT %d\n",bid.dwBidiType);

    bid.dwBidiType = BIDI_FLOAT;
    printf("BIDI_FLOAT %d\n",bid.dwBidiType);

    bid.dwBidiType = BIDI_BLOB;
    printf("BIDI_BLOB %d\n",bid.dwBidiType);

    printf("sizeof(BINARY_CONTAINER) %d\n",sizeof(BINARY_CONTAINER));

    printf("sizeof(BIDI_DATA) %d\n",sizeof(BIDI_DATA));


    getch();
    return 0;
}


BIDI_NULL 0
BIDI_INT 1
BIDI_FLOAT 2
BIDI_BLOB 7
sizeof(BINARY_CONTAINER) 8
sizeof(BIDI_DATA) 12


set file="test"
set PATH=C:\Program Files\Microsoft Visual C++ Toolkit 2003\bin;%PATH%
set INCLUDE=C:\Program Files\Microsoft SDK\include;C:\Program Files\Microsoft Visual C++ Toolkit 2003\include;%INCLUDE%
set LIB=C:\Program Files\Microsoft SDK\Lib;C:\Program Files\Microsoft Visual C++ Toolkit 2003\lib;%LIB%

cl /W4 /FA %file%.c

pause


I still cannot see any situation where a straightforward ENUM macro would not work as well as a structure definition, and be easier to create and use.
eschew obfuscation

hutch--

Michael,

> I still cannot see any situation where a straightforward ENUM macro would not work as well as a structure definition, and be easier to create and use.

I would be interested to see what you had in mind with a macro, even if its just a sketch of how it is supposed to work. Where I have problems in building assembler include files is when a structure has a member that has a "typedef enum" as one of its members.


typedef enum _FILE_ID_TYPE {
      FileIdType,
      ObjectIdType,
      MaximumFileIdType
} FILE_ID_TYPE, *PFILE_ID_TYPE;

typedef struct FILE_ID_DESCRIPTOR {
    DWORD dwSize;  // Size of the struct
    FILE_ID_TYPE Type; // Describes the type of identifier passed in.
    union {
        LARGE_INTEGER FileId;
        GUID ObjectId;
    };
} FILE_ID_DESCRIPTOR, *LPFILE_ID_DESCRIPTOR;


Now I am open to suggestion here but normally from within a structure you reference a data structure like an enum in the same manner as a nested struct that is outside the struct definition.


    _Type FILE_ID_TYPE <>
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php


hutch--

I have had a look at the macros that Drizz has posted but I am none the wiser in how they should be used. Its technically trivial to produce a sequence of numbers with an equate,


    name equ <1,2,3,4,5,6,7,8>


and of course there are other ways of doing it but I need a technique where the enumeration can be called from a structure like a C style "typedef enum". This is why I have so far tried using a structure as it can be called from another structiure with conventional notation.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php