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

Vortex

QuoteI really wonder why they need (or want) this type checking madness. I counted 146 different types from the Windows Data Types doc, where about 8 (BYTE, WORD, DWORD, QWORD, OWORD, REAL4, REAL8, REAL10) should be enough to check if the arg is ok:

I agree with Jochen. Why so much noise about type checking? An assembler is not a compiler

jj2007

Quote from: Vortex on April 13, 2021, 11:06:08 PM
QuoteI really wonder why they need (or want) this type checking madness. I counted 146 different types from the Windows Data Types doc, where about 8 (BYTE, WORD, DWORD, QWORD, OWORD, REAL4, REAL8, REAL10) should be enough to check if the arg is ok:

I agree with Jochen. Why so much noise about type checking? An assembler is not a compiler

Erol,

The type checking madness is not limited to Assembler. Attached a very simple standard Windows source written in FreeBasic (which passes it to Gcc).

Here are the warnings for 100 lines of code:
TmpFb.bas(14) warning 2(1): Passing pointer to scalar, at parameter 3 of APPENDMENU()
TmpFb.bas(20) warning 2(1): Passing pointer to scalar, at parameter 3 of APPENDMENU()
TmpFb.bas(25) warning 3(1): Passing different pointer types, at parameter 2 of SETWINDOWTEXT()
TmpFb.bas(27) warning 1(1): Passing scalar as pointer, at parameter 10 of CREATEWINDOWEX()
TmpFb.bas(29) warning 1(1): Passing scalar as pointer, at parameter 10 of CREATEWINDOWEX()
TmpFb.bas(32) warning 2(1): Passing pointer to scalar, at parameter 4 of SENDMESSAGEA()
TmpFb.bas(38) warning 2(1): Passing pointer to scalar, at parameter 4 of SENDMESSAGE()
TmpFb.bas(77) warning 1(1): Passing scalar as pointer, at parameter 2 of LOADICON()
TmpFb.bas(80) warning 4(1): Suspicious pointer assignment
TmpFb.bas(85) warning 4(1): Suspicious pointer assignment
TmpFb.bas(90) warning 4(1): Suspicious pointer assignment
TmpFb.bas(14) warning 2(1): Passing pointer to scalar, at parameter 3 of APPENDMENU()
TmpFb.bas(20) warning 2(1): Passing pointer to scalar, at parameter 3 of APPENDMENU()
TmpFb.bas(25) warning 3(1): Passing different pointer types, at parameter 2 of SETWINDOWTEXT()
TmpFb.bas(27) warning 1(1): Passing scalar as pointer, at parameter 10 of CREATEWINDOWEX()
TmpFb.bas(29) warning 1(1): Passing scalar as pointer, at parameter 10 of CREATEWINDOWEX()
TmpFb.bas(32) warning 2(1): Passing pointer to scalar, at parameter 4 of SENDMESSAGEA()
TmpFb.bas(38) warning 2(1): Passing pointer to scalar, at parameter 4 of SENDMESSAGE()
TmpFb.bas(77) warning 1(1): Passing scalar as pointer, at parameter 2 of LOADICON()
TmpFb.bas(80) warning 4(1): Suspicious pointer assignment
TmpFb.bas(85) warning 4(1): Suspicious pointer assignment
TmpFb.bas(90) warning 4(1): Suspicious pointer assignment


So 22% of the source cause an absolutely useless warning. No wonder that much of the "professional" software installed on our machines is so bloated and buggy. No sane person can keep control over a source that either issues crappy warnings for over 20% of its lines, or requires you to override the wonderful brilliant type checking feature with type casts in order to avoid the warnings. This is madness, fullstop.

hutch--

 :biggrin:

He he, now you get why I am a data SIZE man, the whole idea of masking data sizes with data types is an act of stupidity. x86-64 processors at their base level work on the data SIZE, not phony types.

HSE

#48
Hi Hutch!

I hope you enjoy your coffee... and take things easy  :biggrin: :biggrin: :biggrin:






Ready?





You can remove a lot of your loved SIZE thing and reduce around 260 lines!

A very reduced REGISTER macro pass examples64 test:
;; *************************************************************************************************
;; -----------------------------
;; Process the first 4 registers
;; -----------------------------
    REGISTER MACRO anum,breg,wreg,dreg,qreg,xreg
      LOCAL elbl, gelbl

      ssize SIZESTR <anum>

    ;; ++++++++++++++++++++++
    ;; text avaluations first
    ;; ++++++++++++++++++++++
      IF ssize GT 4                             ;; handle ADDR notation
        lead SUBSTR <anum>,1,4
        IFIDNI lead,<ADDR>
          wrd2 SUBSTR <anum>,6
          lea qreg, wrd2
          goto elbl
        ENDIF
      ENDIF

      IF ssize GT 1                             ;; handle quoted text
        lead SUBSTR <anum>,1,1
        IFIDNI lead,<">
          mov qreg, reparg(anum)
          goto elbl
        ENDIF
      ENDIF

    ;; ++++++++++++++++++++++++++
    ;; data type evaluations next
    ;; ++++++++++++++++++++++++++

      IF getattr(anum) EQ IMM                           ;; IMMEDIATE
        mov qreg, anum
        goto elbl
      ENDIF

      IF getattr(anum) EQ REG                           ;; REGISTER
        sreg = regsize(anum)
        IF sreg EQ 0
          .err
        ELSEIF sreg EQ 1
          IFIDNI <breg>,<anum>
            and qreg, 0FFh
          ELSE
            xor qreg, qreg
            mov breg, anum
          ENDIF
          goto elbl
        ELSEIF sreg EQ 2
          IFIDNI <wreg>,<anum>
            and qreg, 0FFFFh
          ELSE
            xor qreg, qreg
            mov wreg, anum
          ENDIF
          goto elbl
        ELSEIF sreg EQ 4
          IFIDNI <dreg>,<anum>
            and qreg, 0FFFFFFh
          ELSE
            xor qreg, qreg
            mov dreg, anum
          ENDIF
          goto elbl
        ELSEIF sreg EQ 8
          IFIDNI <qreg>,<anum>
          ELSE
            mov qreg, anum
          ENDIF
          goto elbl
        ENDIF
      ENDIF
     
      if type(anum) eq BYTE
          xor qreg, qreg
          mov breg, anum
      elseif type(anum) eq SBYTE
          movsx qreg, anum
      elseif type(anum) eq WORD
          xor qreg, qreg
          mov wreg, anum
      elseif type(anum) eq SWORD
          movsx qreg, anum
      elseif type(anum) eq DWORD
          xor qreg, qreg
          mov dreg, anum
      elseif type(anum) eq SDWORD
          movsxd qreg, anum
      elseif type(anum) eq QWORD
          mov qreg, anum
      elseif type(anum) eq SQWORD
          mov qreg, anum
      elseif type(anum) eq REAL4
          mov qreg, anum
          movss xreg, DWORD PTR anum
      elseif type(anum) eq REAL8
          mov qreg, anum
          movsd xreg, anum
      else
          goto gelbl
      endif
      goto elbl
       
    :gelbl
   
    ;; +++++++++++++++++++++++
    ;; Unknown data type error
    ;; +++++++++++++++++++++++
      % echo     ***************************
      % echo     ERROR Unknown argument type -> anum        ;; ERROR UNKNOWN DATA TYPE
      % echo     ***************************
      .err

    :elbl
    ENDM




Similar thing in STACKARGS macro:
;; *************************************************************************************************
;; -------------------------------------------------------------
;; Process all following stack arguments without limit.
;; -------------------------------------------------------------
    STACKARG MACRO anum,disp
      LOCAL elbl, gelbl

      ssize SIZESTR <anum>

    ;; ++++++++++++++++++++++
    ;; text avaluations first
    ;; ++++++++++++++++++++++
      IF ssize GT 4                             ;; handle ADDR notation
        lead SUBSTR <anum>,1,4
        IFIDNI lead,<ADDR>
          wrd2 SUBSTR <anum>,6
          lea rax, wrd2
          mov QWORD PTR [rsp+disp], rax
          goto elbl
        ENDIF
      ENDIF

      IF ssize GT 1                             ;; handle quoted text
        lead SUBSTR <anum>,1,1
        IFIDNI lead,<">
          mov rax, reparg(anum)
          mov QWORD PTR [rsp+disp], rax
          goto elbl
        ENDIF
      ENDIF

    ;; ++++++++++++++++++++++++++
    ;; data type evaluations next
    ;; ++++++++++++++++++++++++++
      IF getattr(anum) EQ IMM                           ;; IMMEDIATE
        mov QWORD PTR [rsp+disp], anum
        goto elbl
      ENDIF

      IF getattr(anum) EQ REG                           ;; REGISTER
        sreg = regsize(anum)
        IF sreg EQ 0
          .err
        ENDIF
        IF sreg EQ 1
          mov BYTE PTR [rsp+disp], anum
          goto elbl
        ENDIF
        IF sreg EQ 2
          mov WORD PTR [rsp+disp], anum
          goto elbl
        ENDIF
        IF sreg EQ 4
          mov DWORD PTR [rsp+disp], anum
          goto elbl
        ENDIF
        IF sreg EQ 8
          mov QWORD PTR [rsp+disp], anum
          goto elbl
        ENDIF
      ENDIF

    xor rax,rax
     if type(anum) eq BYTE
          mov al, anum
     elseif type(anum) eq SBYTE
          movsx rax, anum
     elseif type(anum) eq WORD
          mov ax, anum
     elseif type(anum) eq SWORD
          movsx rax, anum
     elseif (type(anum) eq DWORD) or (type(anum) eq REAL4)
          mov eax, anum
     elseif type(anum) eq SDWORD
          movsxd rax, anum
     elseif (type(anum) eq QWORD) or (type(anum) eq SQWORD) or (type(anum) eq REAL8)
         mov rax, anum
     else
         goto gelbl
      endif
      mov QWORD PTR [rsp+disp], rax

      goto elbl

    :gelbl
   
    ;; +++++++++++++++++++++++
    ;; Unknown data type error
    ;; +++++++++++++++++++++++
      % echo     ***************************
      % echo     ERROR Unknown argument type -> anum        ;; ERROR UNKNOWN DATA TYPE
      % echo     ***************************
      .err

    :elbl
    ENDM



This also satisfy Unprototyped and Vararg functions in ABI.

Of course, a lot more tests are needed.

Regards, HSE.
Equations in Assembly: SmplMath

hutch--

Hector,

You will have to forgive me here but I place already tested reliability over any changes. To revise the macros that are already up and tested means having to set it all up again and perform exhaustive tests again and at the moment I have too many other things on my plate.

The videos are a lot of work but I am getting faster at them with practice. Making extra library modules comes next and writing the test code for each module is reasonably time consuming. Then there is matching example code that has to be intelligible as well.

At least some of your suggestions look very useful and I will try and get to them but anything I add or change has to be rigorously tested so that none of the existing capacity gets trashed.


HSE

Yes Hutch, no explanation needed.  :thumbsup:

Quote from: hutch-- on April 14, 2021, 07:16:00 AM
but anything I add or change has to be rigorously tested so that none of the existing capacity gets trashed.
That is. Just building libraries I found a little mistake with floating points  :biggrin: (corrected in previous post).
For sure something more can fail!
Equations in Assembly: SmplMath

jj2007

Quote from: hutch-- on April 14, 2021, 07:16:00 AMrigorously tested

A propos - extracted from the Gcc headers:
#define WM_MOUSELAST                    0x0209
#define WM_MOUSELAST                    0x020A
#define WM_MOUSELAST                    0x020D
#define WM_MOUSELAST                    0x020E

:tongue:

Vortex

Hi Jochen,

I agree with your comments. It's just a lot of paint to type all those useless type castings.

jj2007

Quote from: Vortex on April 14, 2021, 11:12:26 PMIt's just a lot of paint to type all those useless type castings.

Hi Erol,

"For your own safety, it's strictly forbidden to use xxx - but don't worry, I'll show you an easy workaround" :badgrin:

hutch--

This is what I have in the main 64 bit include file.

WM_MOUSEFIRST                        equ 200h
WM_MOUSELAST                         equ 209h


nidud

#55
deleted

jj2007

Quote from: jj2007 on April 13, 2021, 07:26:53 PM
I really wonder why they need (or want) this type checking madness. I counted 146 different types from the Windows Data Types doc, where about 8 (BYTE, WORD, DWORD, QWORD, OWORD, REAL4, REAL8, REAL10) should be enough to check if the arg is ok:

  1 APIENTRY #define APIENTRY
  2 ATOM typedef WORD ATOM;
  3 BOOL typedef int BOOL;
  4 BOOLEAN typedef BYTE BOOLEAN;
  5 BYTE typedef unsigned char BYTE;
  6 CALLBACK #define CALLBACK
  7 CALLBACK typedef
  8 CHAR typedef char CHAR;
  9 COLORREF typedef DWORD COLORREF;
10 CONST #define CONST
11 DWORD typedef unsigned long DWORD;
12 DWORDLONG typedef unsigned __int64 DWORDLONG;
13 DWORD_PTR typedef ULONG_PTR DWORD_PTR;
14 DWORD32 typedef unsigned int DWORD32;
15 DWORD64 typedef unsigned __int64 DWORD64;
16 FLOAT typedef float FLOAT;
17 HACCEL typedef HANDLE HACCEL;
18 HALF_PTR typedef
19 HBITMAP typedef HANDLE HBITMAP;
20 HBRUSH typedef HANDLE HBRUSH;
21 HCOLORSPACE typedef HANDLE HCOLORSPACE;
22 HCONV typedef HANDLE HCONV;
23 HCONVLIST typedef HANDLE HCONVLIST;
24 HCURSOR typedef HICON HCURSOR;
25 HDDEDATA typedef HANDLE HDDEDATA;
26 HDESK typedef HANDLE HDESK;
27 HDROP typedef HANDLE HDROP;
28 HDWP typedef HANDLE HDWP;
29 HENHMETAFILE typedef HANDLE HENHMETAFILE;
30 HFILE typedef int HFILE;
31 HFONT typedef HANDLE HFONT;
32 HGDIOBJ typedef HANDLE HGDIOBJ;
33 HGLOBAL typedef HANDLE HGLOBAL;
34 HHOOK typedef HANDLE HHOOK;
35 HICON typedef HANDLE HICON;
36 HINSTANCE typedef HANDLE HINSTANCE;
37 HKEY typedef HANDLE HKEY;
38 HLOCAL typedef HANDLE HLOCAL;
39 HMENU typedef HANDLE HMENU;
40 HMETAFILE typedef HANDLE HMETAFILE;
41 HMODULE typedef HINSTANCE HMODULE;
42 HMONITOR typedef
43 HPEN typedef HANDLE HPEN;
44 HRESULT typedef LONG HRESULT;
45 HRGN typedef HANDLE HRGN;
46 HRSRC typedef HANDLE HRSRC;
47 HWINSTA typedef
48 HWND typedef HANDLE HWND;
49 INT_PTR typedef
50 LANGID typedef WORD LANGID;
51 LCID typedef DWORD LCID;
52 LCTYPE typedef DWORD LCTYPE;
53 LGRPID typedef DWORD LGRPID;
54 LONG typedef long LONG;
55 LONGLONG typedef
56 LONG64 typedef __int64 LONG64;
57 LPARAM typedef LONG_PTR LPARAM;
58 LPBOOL typedef BOOL far *LPBOOL;
59 LPBYTE typedef BYTE far *LPBYTE;
60 LPCOLORREF typedef DWORD *LPCOLORREF;
61 LPCSTR typedef __nullterminated CONST CHAR *LPCSTR;
62 LPCTSTR typedef
63 LPCWSTR typedef CONST WCHAR *LPCWSTR;
64 LPDWORD typedef DWORD *LPDWORD;
65 LPHANDLE typedef HANDLE *LPHANDLE;
66 LPINT typedef int *LPINT;
67 LPLONG typedef long *LPLONG;
68 LPSTR typedef CHAR *LPSTR;
69 LPTSTR typede
70 LPWORD typedef WORD *LPWORD;
71 LPWSTR typedef WCHAR *LPWSTR;
72 LRESULT typedef LONG_PTR LRESULT;
73 PBOOL typedef BOOL *PBOOL;
74 PBOOLEAN typedef BOOLEAN *PBOOLEAN;
75 PBYTE typedef BYTE *PBYTE;
76 PCHAR typedef CHAR *PCHAR;
77 PCSTR typedef CONST CHAR *PCSTR;
78 PCTSTR typede
79 PDWORD typedef DWORD *PDWORD;
80 PDWORDLONG typedef DWORDLONG *PDWORDLONG;
81 PDWORD_PTR typedef DWORD_PTR *PDWORD_PTR;
82 PDWORD32 typedef DWORD32 *PDWORD32;
83 PDWORD64 typedef DWORD64 *PDWORD64;
84 PFLOAT typedef FLOAT *PFLOAT;
85 PHALF_PTR typedef H
86 PHKEY typedef HKEY *PHKEY;
87 PINT typedef int *PINT;
88 PINT_PTR typedef INT_PTR *PINT_PTR;
89 PINT8 typedef INT8 *PINT8;
90 PINT16 typedef INT16 *PINT16;
91 PINT32 typedef INT32 *PINT32;
92 PINT64 typedef INT64 *PINT64;
93 PLCID typedef PDWORD PLCID;
94 PLONG typedef LONG *PLONG;
95 PLONGLONG typedef LONGLONG *PLONGLONG;
96 PLONG_PTR typedef LONG_PTR *PLONG_PTR;
97 PLONG32 typedef LONG32 *PLONG32;
98 PLONG64 typedef LONG64 *PLONG64;
99 POINTER_32 #define PO
100 POINTER_UNSIGNED #define POINTER_UNSIGNED
101 PSHORT typedef SHORT *PSHORT;
102 PSIZE_T typedef SIZE_T *PSIZE_T;
103 PSSIZE_T typedef SSIZE_T *PSSIZE_T;
104 PSTR typedef CHAR *PSTR;
105 PTBYTE typedef TBYTE *PTBYTE;
106 PTCHAR typedef TCHAR *PTCHAR;
107 PTSTR typed
108 PUHALF_PTR typedef UI
109 PUINT_PTR typedef UINT_PTR *PUINT_PTR;
110 PUINT8 typedef UINT8 *PUINT8;
111 PUINT16 typedef UINT16 *PUINT16;
112 PUINT32 typedef UINT32 *PUINT32;
113 PUINT64 typedef UINT64 *PUINT64;
114 PULONG typedef ULONG *PULONG;
115 PULONGLONG typedef ULONGLONG *PULONGLONG;
116 PULONG_PTR typedef ULONG_PTR *PULONG_PTR;
117 PULONG32 typedef ULONG32 *PULONG32;
118 PULONG64 typedef ULONG64 *PULONG64;
119 PUSHORT typedef USHORT *PUSHORT;
120 PVOID typedef void *PVOID;
121 PWCHAR typedef WCHAR *PWCHAR;
122 PWORD typedef WORD *PWORD;
123 PWSTR typedef WCHAR *PWSTR;
124 QWORD typedef unsigned __int64 QWORD;
125 SC_HANDLE typedef HANDLE SC_HANDLE;
126 SC_LOCK typedef LPVOID SC_LOCK;
127 SERVICE_STATUS_HANDLE typedef HANDLE SERVICE_STATUS_HANDLE;
128 SHORT typedef short SHORT;
129 SIZE_T typedef ULONG_PTR SIZE_T;
130 SSIZE_T typedef LONG_PTR SSIZE_T;
131 TBYTE typed
132 UHALF_PTR typedef u
133 UINT_PTR typedef
134 UINT16 typedef unsigned short UINT16;
135 UINT32 typedef unsigned int UINT32;
136 UINT64 typedef usigned __int 64 UINT64;
137 ULONG typedef unsigned long ULONG;
138 ULONGLONG typedef u
139 ULONG64 typedef unsigned __int64 ULONG64;
140 UNICODE_STRING typedef struct _UNICODE_STRING
141 USHORT typedef unsigned short USHORT;
142 VOID #define VOID
143 WCHAR typedef wchar_t WCHAR;
144 WINAPI #define WINAPI
145 CALLBACK typedef
146 WPARAM typedef UINT_PTR WPARAM;

Now I counted a few more (1000+), see attachment :cool:

hutch--

I have a view on type checking, argument count checking, never ending equates with different names, read the DOCUMENTATION !!!!

Add a maze of confusion and you end up with confusion. Even if you get some form of squarking about something that does not match, you still have to look up the documentation to correct the error. Now if you bother to look up the documentation and it shows an argument as being a POINTER, size and arg count will not help you here, you need to know that it is a pointer which will be either 4 or 8 bytes depending on if your code is 32 or 64 bit.

This where you get a TYPEDEF or a #define that is named as a POINTER. Overlaying C/C++ technology on an assembler is getting the cart to pull the horse. When Microsoft release a 64 bit assembler, they are not trying to outpace their C compiler which does all of the things that a C compiler should, it does not do anything that tries to over ride the C compiler.

Now if you want to use an API like SendMessage() in an assembler, you look up the documentation for both the API AND the message you want to send. In 32 bit you can use the PUSH / CALL notation, in 64 bit you are better off using the call automation for any working version of "invoke" and set any handles or pointers to either 32 or 64 bit and this is determined by READING the documentation.

jj2007

Quote from: hutch-- on May 03, 2021, 09:51:03 AMif you want to use an API like SendMessage() in an assembler

Warnings issues by FreeBasic/Gcc, for perfectly valid and suitable arguments in a 100-line GUI template:
TmpFb.bas(15) warning 2(1): Passing pointer to scalar, at parameter 3 of APPENDMENU()
TmpFb.bas(21) warning 2(1): Passing pointer to scalar, at parameter 3 of APPENDMENU()
TmpFb.bas(28) warning 1(1): Passing scalar as pointer, at parameter 10 of CREATEWINDOWEX()
TmpFb.bas(30) warning 1(1): Passing scalar as pointer, at parameter 10 of CREATEWINDOWEX()
TmpFb.bas(33) warning 2(1): Passing pointer to scalar, at parameter 4 of SENDMESSAGEA()
TmpFb.bas(39) warning 2(1): Passing pointer to scalar, at parameter 4 of SENDMESSAGE()
TmpFb.bas(78) warning 1(1): Passing scalar as pointer, at parameter 2 of LOADICON()
TmpFb.bas(81) warning 4(1): Suspicious pointer assignment
TmpFb.bas(86) warning 4(1): Suspicious pointer assignment


You can "heal" the "bad" code by using e.g.
SendMessage(hEdit, WM_SETTEXT, 0, CAST(LPARAM, @file_char(0)))
instead of
SendMessage(hEdit, WM_SETTEXT, 0, @file_char(0))

It's type madness :cool:

hutch--

You are right, it looks disgusting. I have yet to comprehend the reasoning that confusing and misleading inexperienced programmers achieves anything else than to make them give up on a particular language.  :thdn: