News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

new form of the TYPEDEF instruction

Started by StillLearningMasm, September 30, 2023, 04:35:37 PM

Previous topic - Next topic

StillLearningMasm

I believe I have found a new undocumented form of the TYPEDEF instruction.
In fact I found 3 different forms. Here they are:

symbol/label(for TYPEDEF) symbol/label(for prior TYPEDEF) symbol/label(for prior TYPEDEF)
symbol/label(for TYPEDEF) symbol/label(for prior TYPEDEF) symbol/label(for prior data definition)
symbol/label(for TYPEDEF) symbol/label(for prior TYPEDEF) data expression with commas optional

I found no documention on these forms and masm accepts them without any errors.

Here are example fragments of code of each:

;Example code for first form:
;symbol/label(for TYPEDEF) symbol/label(for prior TYPEDEF) symbol/label(for prior TYPEDEF)

myexample typedef dword
myother  typedef byte
myexample2 myexample myother

;Example code for second form:
;symbol/label(for TYPEDEF) symbol/label(for prior TYPEDEF) symbol/label(for prior data definition)

mydata db 1
myexample3 typedef dword
myexample4 myexample3 mydata

;Example code for third form:

;symbol/label(for TYPEDEF) symbol/label(for prior TYPEDEF) data expression with commas optional
myexample5 typedef dword
myexample6 myexample5 1

Has anybody used these forms? What is the purpose of them?
Instead should they be forms that are in error?

Thank you,
StillLearningMasm


NoCforMe

Well, this one for sure

mydata db 1
myexample3 typedef dword
myexample4 myexample3 mydata

makes no sense whatsoever. I think you've discovered a weird glitch in the assembler.

Best to just forget about it, seems to me.
Assembly language programming should be fun. That's why I do it.

jj2007

Testbed for you:

include \masm32\include\masm32rt.inc

;Example code for first form:
;symbol/label(for TYPEDEF) symbol/label(for prior TYPEDEF) symbol/label(for prior TYPEDEF)
.DATA
myexample typedef dword
myother  typedef byte
myexample2 myexample myother

;Example code for second form:
;symbol/label(for TYPEDEF) symbol/label(for prior TYPEDEF) symbol/label(for prior data definition)

mydata db 1
myexample3 typedef dword
myexample4 myexample3 mydata

;Example code for third form:

;symbol/label(for TYPEDEF) symbol/label(for prior TYPEDEF) data expression with commas optional
myexample5 typedef dword
myexample6 myexample5 1

.code
start:
int 3
  mov eax, offset myexample4
  mov ebx, offset myexample3
  mov ecx, offset mydata
  exit

end start

Address   Hex dump          Command                                  Comments
00401001  |.  B8 05304000   mov eax, offset myexample4
00401006  |.  BB 04000000   mov ebx, 4
0040100B  |.  B9 04304000   mov ecx, offset mydata

zedd

I am not sure why anyone would want to use a typedef of a typedef of still another typedef. Could get real confusing really fast. More "TYPDEF Madness"??
Also, is there any difference between "TYPEDEF" and "typedef"? Is it case sensitive?

From "Masm32.chm" in the \masm32\help directory

QuoteTYPEDEF


Syntax: name TYPEDEF qualifiedtype

name TYPEDEF PROTO prototypelist


Description

Defines a new type or creates a synonym for an already defined type. The TYPEDEF directive associates <name> with a type, and, once defined, the symbol can be used anywhere a type can be used or as a data declaration directive. The <qualifiedtype> parameter can specify a pointer to a qualified type. The TYPEDEF PROTO syntax defines a prototype type.

Once a type is defined, you can use it to define variables. Use is similar to the other variable definition directives (like BYTE and WORD).


Parameter Description

qualifiedtype Any qualified type. Can include a type previously defined by a TYPEDEF directive, but recursive definitions are not allowed.
prototypelist List of parameters for procedure prototype. Uses the same syntax as the PROTO directive.

QuoteTYPEDEF Directive

Description


Use TYPEDEF to


* Define types for procedure arguments in PROC, PROTO, and INVOKE statements.

* Define types used in high-level expressions such as .IF, WHILE, and .REPEAT.

* Define pointer types so that CodeView can give appropriate information about the pointer.

* Define the types for procedure arguments in procedure prototypes.


Typical TYPEDEFS


CHAR TYPEDEF BYTE                ; Rename an existing type
PCHAR TYPEDEF PTR CHAR           ; Create a pointer type
PWORD TYPEDEF PTR WORD           ; Create a pointer type
PPWORD TYPEDEF PTR PWORD         ; Create a complex pointer type
PMYSTRUCT TYPEDEF PTR MYSTRUCT   ; Create pointer type to structure or union
PPROTO TYPEDEF PROTO \
NEAR C arg1:byte arg2:word       ; Define proc prototype
PFUNCT TYPEDEF PTR PPROTO        ; Define pointer to proc
                                 ; prototype
Typical uses of TYPEDEFs:

user CHAR "Jill"                 ; Use new type as initializer
Puser PCHAR user                 ; Initialize a pointer
task PROC myvar:PMYSTRUCT        ; Pass pointer to structure
EXTERNDEF ppw:PPWORD             ; Define external with user type
proctbl PFUNC Up, Down, Home     ; Initialize procedure table
-
-
-
INVOKE proctbl[bx], pos          ; Call procedure from table
The two definitions seem to add to the confusion.  :rolleyes:   I am 'assuming' that the capitalization of "TYPEDEF" is a holdover from the MS DOS days, as I see it in lowercase more often than upper case.

StillLearningMasm

I tried using JWASM and it also accepts these forms of typedef.

jj2007

Out of curiosity, I checked how often I use typedefs in my code: in 0.013% of lines, i.e. roughly every 7,700 lines. Remember a DWORD is a DWORD. The cpu knows what to do with it.

StillLearningMasm

How did JWASM know about this? Was there information about this already posted?

NoCforMe

My advice is to stay away from this directive altogether. You don't need it. Assembler types are few and primitive, thus easy to remember.

If you're dealing with a lot of "types" like pointers to structures (I use a lot of these all the time), then instead of TYPEDEFing them, just use comments to identify what your variables are. This is the purpose of TYPEDEF anyhow, basically a documentation function.

If you really feel you need this kind of crutch, maybe you should be writing in C instead of assembly language ...
Assembly language programming should be fun. That's why I do it.

tenkey

The rule that makes sense of these examples is that the type name can be used as a data definition directive.

In win64.inc (included by masm64rt.inc), HANDLE is typdef'ed, so you can define handle data by typing
handle1 HANDLE ?
handle2 HANDLE NULL
file_handle HANDLE INVALID_HANDLE_VALUE
instead of
; 64-bit code
handle1 dq ?
handle2 dq NULL
file_handle dq INVALID_HANDLE_VALUE

So...

myexample typedef dword
myother  typedef byte
myexample2 myexample myother
Since myother is a type name (and not a code or data label), the last line is interpreted as
myexample2 dd (sizeof myother)

mydata db 1
myexample3 typedef dword
myexample4 myexample3 mydata
Since mydata is a data label (and not a type name), the last line is interpreted as
myexample4 dd (offset mydata)
myexample5 typedef dword
myexample6 myexample5 1
The last line is straightforwardly interpreted as
myexample6 dd 1

zedd

Excellent examples and explanations, tenkey.
I still don't know what that would be useful for (nested typedefs, etc), but it does indeed explain the disassembly, so that it makes sense.  :smiley:

NoCforMe

Quote from: tenkey on October 01, 2023, 08:18:18 AMIn win64.inc (included by masm64rt.inc), HANDLE is typdef'ed, so you can define handle data by typing
handle1 HANDLE ?
handle2 HANDLE NULL
file_handle HANDLE INVALID_HANDLE_VALUE
instead of
; 64-bit code
handle1 dq ?
handle2 dq NULL
file_handle dq INVALID_HANDLE_VALUE

Well, the same is true for 32-bit programming (the TYPEDEFs are in windows.inc). I use them all the time. All the following are TYPEDEFd:

  • HDC
  • HBITMAP
  • HBRUSH
  • HFILE
  • HPEN
  • HINSTANCE

and there are more, but I won't bore you any longer.

But so what? This is all trivial, because (in 32-bit Win32 code) everything is a DWORD. So it's at best a bookkeeping aid. There's really no difference, so far as the code is concerned, between these declarations:

    LOCAL    fileHandle:HFILE, brush:HBRUSH, pen:HPEN
; -- or --
    LOCAL    fileHandle:DWORD, brush:DWORD, pen:DWORD


meaning that it's really more important what you name your variables in the first place.
Assembly language programming should be fun. That's why I do it.

jj2007

Quote from: NoCforMe on October 01, 2023, 09:01:14 AMSelect Expand
    LOCAL    fileHandle:HFILE, brush:HBRUSH, pen:HPEN
; -- or --
    LOCAL    fileHandle:DWORD, brush:DWORD, pen:DWORD

Actually, LOCAL fileHandle, brush, pen is valid code, too. If you don't specify the size, it's DWORD.

NoCforMe

Right, so maybe all the more reason not to place too much emphasis on fancy-schmancy directives like TYPEDEF.

In my code, at least, there are only two cases where a LOCAL variable isn't a DWORD:
  • BYTE variables (always multiples of 4! (32-bit code; 8 for 64-bit code))
  • structures

Ackshooly, this goes for globals too, except that I do use byte-size (meaning 1-byte) variables for things like flags, where a DWORD would be a waste of 3 bytes. These always go at the end of the .data or .data? section.
Assembly language programming should be fun. That's why I do it.

daydreamer

Float Typedef real4 was useful for port dx9 code examples , without need to replace all with real4
my none asm creations
https://masm32.com/board/index.php?topic=6937.msg74303#msg74303
I am an Invoker
"An Invoker is a mage who specializes in the manipulation of raw and elemental energies."
Like SIMD coding