News:

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

Main Menu

Microsoft C using the 64 bit MASM library

Started by hutch--, August 01, 2019, 07:12:48 PM

Previous topic - Next topic

hutch--

The attached example written in VC2019 plain C uses a few simple UI procedures from the m64lib MASM library. This is one of the main targets for ML64 as CL.EXE no longer supports inline assembler. To save on the download size the 64 bit library in the MASM32 sub directory has been used.

This is the C source.

/* ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ */

      #include <windows.h>

      LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);

      /* ------------------------
      MASM 64 bit library modules
      ------------------------ */
      LRESULT MsgboxI(HWND,LPCTSTR,LPCTSTR,LONGLONG,LPSTR);
      HANDLE  button(HINSTANCE,HWND,LPCTSTR,UINT,UINT,UINT,UINT,UINT);
      VOID    line(HWND,UINT,UINT,UINT,UINT,COLORREF,UINT);


      HINSTANCE     hInstance;
      HANDLE        hWnd;
      HANDLE        butn1;
      HANDLE        butn2;
      HANDLE        butn3;
      HANDLE        butn4;
      UINT          sWid;
      UINT          sHgt;
      char          pTitle[]       = " MASM 64 bit modules with Microsoft C";
      char          pWindowClass[] = "MASM_and_C_Window";

/* ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ */

void main()

    {
      HICON         hIcon;
      HCURSOR       hCursor;
      LPMSG         pmsg;
      WNDCLASSEX    wc;
      WNDCLASSEX *  pwc;
      MSG           msg;
      UINT          wwid;
      UINT          whgt;
      HBRUSH        hBrush;

      hInstance = GetModuleHandle(0);
      hIcon     = LoadIcon(hInstance,MAKEINTRESOURCE(5));
      hBrush    = CreateSolidBrush(0x00333333);
      hCursor   = LoadCursor(NULL,IDC_ARROW);

      pmsg  = &msg;
      pwc   = &wc;

      wwid  = 900;          /* required window width  */
      whgt  = 600;          /* required window height */

      sWid  = GetSystemMetrics(SM_CXSCREEN);
      sHgt  = GetSystemMetrics(SM_CYSCREEN);

      wc.cbSize        = sizeof(WNDCLASSEX);
      wc.style         = CS_BYTEALIGNWINDOW | CS_BYTEALIGNCLIENT;
      wc.lpfnWndProc   = &WndProc;
      wc.cbClsExtra    = 0;
      wc.cbWndExtra    = 0;
      wc.hInstance     = hInstance;
      wc.hIcon         = hIcon;
      wc.hCursor       = hCursor;
      wc.hbrBackground = hBrush;
      wc.lpszMenuName  = NULL;
      wc.lpszClassName = pWindowClass;
      wc.hIconSm       = hIcon;

      RegisterClassEx(pwc);     

      hWnd = CreateWindowEx(WS_EX_LEFT,
                            pWindowClass,
                            pTitle,
                            WS_OVERLAPPEDWINDOW,
                            sWid/2-(wwid/2),
                            sHgt/2-(whgt/2),
                            wwid,whgt,
                            NULL,NULL,hInstance,NULL);

      ShowWindow(hWnd,SW_SHOW);
      UpdateWindow(hWnd);

      while (GetMessage(pmsg,NULL,0,0))
      {
        TranslateMessage(pmsg);
        DispatchMessage(pmsg);
      }

    }

/* ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ */

LRESULT CALLBACK WndProc(
                          HWND hWin,
                          UINT uMsg,
                          WPARAM wParam,
                          LPARAM lParam
                        )
    {
      PAINTSTRUCT ps;

      switch (uMsg)
        {
          case WM_COMMAND:
            {
            switch (wParam)
              {
             /* ---------
              * buttons *
              --------- */
              case 150:
                MsgboxI(hWin,"Button 1"," About",MB_OK,MAKEINTRESOURCE(5));
                SetWindowText(butn1,"Done");
                return 0;
                break;
              case 151:
                MsgboxI(hWin,"Button 2"," About",MB_OK,MAKEINTRESOURCE(5));
                SetWindowText(butn2,"Done");
                return 0;
                break;
              case 152:
                MsgboxI(hWin,"Button 3"," About",MB_OK,MAKEINTRESOURCE(5));
                SetWindowText(butn3,"Done");
                return 0;
                break;
              case 153:
                if (MsgboxI(hWin,"Do you really want to exit ?",
                    " Exit Confirmation",MB_YESNO,MAKEINTRESOURCE(5)) == IDNO)
                  {
                    return 0;
                    break;
                  }
                SendMessage(hWin,WM_DESTROY,0,0);
                return 0;
                break;
             /* ------------
              * menu items *
              ------------ */
              case 1000:
                SendMessage(hWin,WM_CLOSE,0,0);
                break;

              case 5000:
                MsgboxI(hWin,pTitle," Isn't MASM magnificent",
                             MB_OK,MAKEINTRESOURCE(5));
                return 0;
                break;
              }
            }

          case WM_PAINT:
            BeginPaint(hWin,&ps);
            line(hWin,160,30,160,sHgt,0x0000009F,3);
            line(hWin,160,30,sWid,30,0x0000009F,3);
            EndPaint(hWin,&ps);
            return 0;

          case WM_CREATE:
            butn1 = button(hInstance,hWin,"Button 1",30,30,100,22,150);
            butn2 = button(hInstance,hWin,"Button 2",30,60,100,22,151);
            butn3 = button(hInstance,hWin,"Button 3",30,90,100,22,152);
            butn4 = button(hInstance,hWin,"Close",30,120,100,22,153);
            SetMenu(hWin,LoadMenu(hInstance,MAKEINTRESOURCE(10)));
            return 0;
            break;

          case WM_CLOSE:
            MsgboxI(hWin," Seeya round like a Rubens",
                         "Thats all folks",MB_OK,MAKEINTRESOURCE(5));
            SendMessage(hWin,WM_DESTROY,0,0);
            break;
 
          case WM_DESTROY:
            PostQuitMessage(0);
            break;
        }

    return DefWindowProc(hWin,uMsg,wParam,lParam);

    }

/* ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ */

Vortex

Hi Hutch,

The Universal C run-time is a headache in the latest Visual Studio releases. I guess you used other include file sets and libraries from old SDKs to build your example.

https://stackoverflow.com/questions/35805113/visual-studio-2015-run-time-dependencies-or-how-to-get-rid-of-universal-crt

hutch--

Hi Erol,

Nope, I started with windows.h and every time it needed another library, I found it in the distribution and copied the whole lot into the include directory. I ended up with about 2500 files but it works correctly and can finds everything. The include dir has 2554 files and the lib has 552 files but the compiled output files seem to work OK. There is an absolute mountain of junk in the whole package but if you look hard enough you can find most things.

Vortex

Hi Hutch,

Thanks for the information. Sadly, the introduction of the Universal C run-time library results in a lot of mess. I cannot link a VC 2019 object module with msvcrt.lib :

public __local_stdio_printf_options
public _vfprintf_l
public printf

extern __stdio_common_vfprintf: near
extern __acrt_iob_func: near
extern ?_OptionsStorage@?1??__local_stdio_printf_options@@9@9: byte


A simple hello world application using printf is importing those modules. ( the three extern statements )

jcfuller

Hutch,
  I cloned the example with bc9/TCLib and it came in at 11,264, 512 larger that the original. TCLib is c++ only so I did need to wrap the declares with extern "C".
I also had to change all HANDLE's to HWND's (compiler complained )and redo the rc file. My rc editor did not like something in there???
I may post it over on my forum in a bit.

I just updated my VS2019 today. 16.1.6 -> 16.2.0. Big update. It even had to reboot the system.
I have both the ide and the build tools installed as I do build downloaded projects from time to time but use the build tools for all my bc9/TClib work. Having the installer makes it a breeze to keep them updated.

James


hutch--

Erol,

I just converted a CPP golden oldie and when it built at 283k, I went looking for the msvcrt option. The /MD option did the job, droped to 41k.

aw27

Playing from the IDE will produce better results, unless you are a VS command line expert (I am not and am yet to find a real one).  For the first program you will get an .exe of 7KB not 11KB tweaking from the IDE.

hutch--

It would be interesting to see how its done, I went through the CL manual options but I used the speed optimisation. With your build, did you include an icon, manifest and version control block ?

TimoVJL

#8
SET Path=C:\code\msvc2019\bin\x64
SET INCLUDE=C:\code\WDDK710\include
SET LIB=M:\masm32\lib64
cl -GS- -Zl -O2 -DWIN32_LEAN_AND_MEAN cplusasm.c kernel32.lib user32.lib gdi32.lib M:\masm32\m64lib\m64lib.lib  rsrc.res -link -nodefaultlib -entry:main -subsystem:windows,5.2 -nocoffgrpinfo -map
9.5 KB

/GS[-] enable security checks
/Zl omit default library name in .OBJ
/Ox optimizations (favor speed)
/O2 maximum optimizations (favor speed)

-link
/NODEFAULTLIB[:library]
/MAP[:filename]

EDIT: use now masm32\lib64 folder.


EDIT: MSVCUnPack.cmd just download and unzip files to current folder.
May the source be with you

aw27

I have gone to 9KB without using the kernel32.lib from the masm32 library, without using an older toolset, like the Windows 7.1 SDK and without optimizing for size (it is for speed). With these it will go to 7.5 KB. I have used VS 2019, manifest, version block and icon.  :thumbsup: , I am using Visual Studio 2017 - Windows XP (v141_xp) toolset (for the xp reason), but the size will not change with the Visual Studio 2019 (v142) toolset.

daydreamer

I tested a around 110k program,changed optimize speed vs optimize size,from mid option "neither" to optimize size and got Exe 1.5k smaller
It contains lots of gdi calls, some in loops
@hutch about 41k,there just be way to create a wizard for a minimum vc++ windows app,or a minimum template to start from
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

Vortex

Attached is Hutch's example built with a batch file. The size of the executable is 7.5 Kb by merging some sections. A small C run-time module is added to the project.

TimoVJL

#12
Optional feature to a template without commandline:void __cdecl WinMainCRTStartup(void) { ExitProcess(WinMain(GetModuleHandle(NULL), NULL, NULL, W_SHOWDEFAULT)); }
void __cdecl mainCRTStartup(void) { __declspec(dllimport) void __cdecl exit(int status); int __cdecl main(void); exit(main()); }
May the source be with you

aw27

Not 100% true a few things   :wink2: , namely we can build with VS 2019 and the VS 2017 Xp toolset using the Masm32/64 MSVCRT.lib and Masm32/64 Kernel32.lib.
Ignore All Default Libraries: Yes (/NODEFAULTLIB), change Entry Point to main then:


#define _NO_CRT_STDIO_INLINE
#include <stdlib.h>
#include <stdio.h>

int main()
{
printf("hello\n");
return(0);
}




Vortex

The statement _NO_CRT_STDIO_INLINE does the job, thanks.