News:

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

Main Menu

Why won't this 64 bit window open?

Started by markallyn, March 20, 2018, 05:10:46 AM

Previous topic - Next topic

markallyn

Hello everyone,

For my own edification I have tried to adapt a 32bit iczelion tutorial (tut 4) to 64 bit code.  The following code assembles and links without an error, but the resulting executable (1) does not open a window, and (2) remains alive after running so that I need to invoke taskmgr to exit the process.

Quote
;;mywindow1.asm.  A simple windows 64 bit window.  Adapted from IczELION's Tut 4.

include \masm32\include64\masm64rt.inc

WinMain PROTO   :QWORD,:QWORD,:QWORD,:QWORD
WndProc   PROTO   

.data
ClassName db "SimpleWinClass",0
AppName   db "OurFirstWindow",0

.data?
hInstance HINSTANCE ?
CommandLine   LPSTR ?

.code
main   PROC
invoke   GetModuleHandle, NULL
mov   hInstance, rax
invoke  GetCommandLine
mov   CommandLine, rax
invoke  WinMain, hInstance,NULL,CommandLine,SW_SHOWDEFAULT
invoke   ExitProcess,0
ret
main   ENDP

WinMain   PROC hInst:HINSTANCE, hPrevInst:HINSTANCE, CmdLine:LPSTR, CmdShow:QWORD   
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL hwnd:HWND

mov   wc.cbSize, SIZEOF WNDCLASSEX
mov   wc.style, CS_HREDRAW or CS_VREDRAW
;lea    rdx, WndProc
mrm   wc.lpfnWndProc, OFFSET WndProc  ;rdx
mov   wc.cbClsExtra, NULL
mov   wc.cbWndExtra, NULL
push   hInstance
pop   wc.hInstance
mov   wc.hbrBackground, COLOR_WINDOW+1
mov   wc.lpszMenuName, NULL
lea   rdx, ClassName
mov   wc.lpszClassName, rdx
invoke    LoadIcon, NULL, IDI_APPLICATION
mov   wc.hIcon, rax
mov   wc.hIconSm, rax
invoke  LoadCursor, NULL, IDC_ARROW
mov   wc.hCursor, rax
invoke   RegisterClassEx, ADDR wc
invoke   CreateWindowEx, NULL,\
      ADDR ClassName,\
      ADDR AppName,\
      WS_OVERLAPPEDWINDOW,\
      CW_USEDEFAULT,\
      CW_USEDEFAULT,\      
      CW_USEDEFAULT,\
      CW_USEDEFAULT,\
      NULL,\
      NULL,\
      hInst,\
      NULL
mov   hwnd, rax
invoke   ShowWindow, hwnd, CmdShow
invoke   UpdateWindow, hwnd

.while   TRUE
   invoke   GetMessage, ADDR msg, NULL, 0,0
   .break .if rax {} 0
   invoke   TranslateMessage, ADDR msg
   invoke   DispatchMessage, ADDR msg
.endw
mov   rax, msg.wParam
ret
WinMain   ENDP

WndProc   PROC
LOCAL hWnd:QWORD
LOCAL uMsg:QWORD
LOCAL wParam:QWORD
LOCAL lParam:QWORD

mov   rcx, hWnd
mov   rdx, uMsg
mov   r8, wParam
mov   r9, lParam

.if uMsg==WM_DESTROY
   invoke PostQuitMessage,NULL
.else
   invoke DefWindowProc, hWnd,uMsg,wParam,lParam
   ret
.endif
xor rax,rax
ret
WndProc ENDP
END

Obviously, I've not done much GUI programming and I can't figure this one out.  Any suggestions would be most useful.

Regards,
Mark Allyn

hutch--

Mark,

64 bit MASM does not use 32 bit prototypes.

A WndProc procedure receives 4 arguments, LOCAL args are not arguments passed to the WndProc by the operating system. It is technically what you call a "callback" that the operating system calls with the messages processed by the window.

This will not work.
WndProc   PROC
LOCAL hWnd:QWORD
LOCAL uMsg:QWORD
LOCAL wParam:QWORD
LOCAL lParam:QWORD

mov   rcx, hWnd
mov   rdx, uMsg
mov   r8, wParam
mov   r9, lParam

You need this format.
WndProc proc hWin:QWORD,uMsg:QWORD,wParam:QWORD,lParam:QWORD

markallyn

Hutch,

You're suggestion works, but doesn't do the entire job.  What I get now is a very briefly flashed window which closes instantly.  Something else is haywire in the code.

I have a terrible time with 32 bit versus 64 bit calls.  Honestly, I loved the simplicity of the old 32 bit ABI.

Regards,
Mark

fearless

Here is an example using uasm for a simple 64bit window

hutch--

Mark,

You are having the problem because you are trying to mix the two systems and they don't mix. The architecture is different. I have attached a bare 64 bit MASM Window, its one of the templates set up in the MASM 64 bit package.

jj2007

RegisterClassEx succeeds but CreateWindowEx fails. Right now I have no time to check why, sorry...

markallyn

Fearless, Hutch, JJ,

Thanks for the UASM example, fearless.

I found the problem.  Very simple solution in fact.  In Iczelion's original tut4
there is the rather ugly (my opinion...) instruction:

Quote
.BREAK .IF (!eax)

ml64 doesn't like the ! symbol in this context.  So I had changed the code to something that looked like this:

Quote
.break .if rax {} 0

...which ml64 likes just fine, but it has the effect of closing the window instantly.  What does work and doesn't close the window is:

Quote
.break .if rax==0

Now I want to paint text in the window.  No doubt I'll be right back here pretty soon.

Regards,
Mark

hutch--

As long as you keep trying to use old style 32 bit MASM code you will keep having these problems, below is how you write a basic message loop. I did in fact post the template for a reason, it works correctly and is written properly. You need to remember that Iczelion wrote these old examples almost 20 years ago and they are a little off the pace these days.


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

msgloop proc

    LOCAL msg    :MSG
    LOCAL pmsg   :QWORD

    mov pmsg, ptr$(msg)                     ; get the msg structure address
    jmp gmsg                                ; jump directly to GetMessage()

  mloop:
    invoke TranslateMessage,pmsg
    invoke DispatchMessage,pmsg
  gmsg:
    test rax, rv(GetMessage,pmsg,0,0,0)     ; loop until GetMessage returns zero
    jnz mloop

    ret

msgloop endp

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


markallyn

Good morning, Hutch,

I was unaware of the msgloop template.  I will try it out.

I'd like to explore the statement you began the post with.  Namely:

Quote
As long as you keep trying to use old style 32 bit MASM code you will keep having these problems,...

My "trying" isn't because I'm resisting "new style 32 bit MASM", it's because I don't know how to do "new style".  Could you point me to some documentation that would enlighten me.

Thanks,
Mark

hutch--

Mark,

I wonder if we live in alternate universes, I post you a safe reliable working example so you ignore it, I copy the message loop out of the example so you assume its the template, you insist on trying to make 32 bit MASM notation work in 64 bit MASM when it is a different assembler, I am a little lost in how to connect what you are after.

The reason why there are a range of templates accessed from QE in the 64 bit version is so you have safe working examples to learn from and/or use as a base to write your own executable files from. The 32 bit version of MASM32 is complete and has worked well for years and it differs from the historical example Iczelion wrote nearly 20 years ago.

Iczelion was a personal friend of mine and we worked together on the earliest versions of MASM32. He retired due to normal things like "wife, life, work, kids etc ....". That is the difference between old style 32 bit MASM and the later MASM32 SDK that has more than 15 years development done on it since Iczelion wrote his original examples.

The 64 bit version of MASM is an entirely different animal to the older 32 bit versions, it is an industrial tool developed by the OS vendor Microsoft and it was never "consumerised" to make it friendly or easy to use. It is terse, highly inflexible, does not hold your hot little hand and will bite you if you part your hair the wrong way, exactly what an industrial professional tool does with no tolerance for errors.

Apart from its ancient piggishly bad mannered pre-processor, its only saving grace is it is capable of producing what it was designed to produce, high quality binary code written by programmers who know how to write it.

markallyn

Hello Hutch,

Well, it's true you are in Sydney and I am 55 miles north of Philadelphia PA USA and we are separated by 16 hours of time and goodness knows how many miles -- 13,000?--but we're definitely in the same universe.  Pretty sure of this.

What we seem to have run into is the limits of the internet for high fidelity communication--and in the same universe at that.

I propose that, if you have the time, we try the telephone.  I'd enjoy talking to you.

Or perhaps better still I post a rewrite of my original iczelion-tut3-inspired code that contains your message loop.  This would demonstrate conclusively that I am not ignoring your counsel.  As it happens, this was my plan for today anyway, once preparations for yet another snowstorm are completed.

Regards as always,

Mark

Siekmanski

Quote from: markallyn on March 21, 2018, 01:07:12 AM
Hello Hutch,

Well, it's true you are in Sydney and I am 55 miles north of Philadelphia PA USA and we are separated by 16 hours of time and goodness knows how many miles -- 13,000?--but we're definitely in the same universe.  Pretty sure of this.

Are you sure? In my universe you and Hutch are separated by only 9 hours.  :biggrin:

Although, you could be right if you're living in another universe with another gravitational field and time base as explained in Stephen Hawking's latest paper on multiple universes.  :t
Creative coders use backward thinking techniques as a strategy.

hutch--

Here is the fix of your source posted above. I have attached a zip file with this source and a "makeit.bat" that works. Don't ignore this one as I have bothered to fix your own source code.


;;mywindow1.asm.  A simple windows 64 bit window.  Adapted from IczELION's Tut 4.

include \masm32\include64\masm64rt.inc

; WinMain PROTO   :QWORD,:QWORD,:QWORD,:QWORD
; WndProc   PROTO   

  .data
    ClassName db "SimpleWinClass",0
    AppName   db "OurFirstWindow",0

  .data?
    hInstance HINSTANCE ?
    CommandLine   LPSTR ?

  .code

; --------------------------------------------------------------------

entry_point PROC

    invoke  GetModuleHandle, NULL
    mov     hInstance, rax
    invoke  GetCommandLine
    mov     CommandLine, rax
    invoke  WinMain, hInstance,NULL,CommandLine,SW_SHOWDEFAULT
    invoke  ExitProcess,0
    ret

entry_point ENDP

; --------------------------------------------------------------------

WinMain   PROC hInst:QWORD, hPrevInst:QWORD, CmdLine:QWORD, CmdShow:QWORD

    LOCAL wc:WNDCLASSEX
    LOCAL msg:MSG
    LOCAL hwnd:HWND

    mov   wc.cbSize, SIZEOF WNDCLASSEX
    mov   wc.style, CS_HREDRAW or CS_VREDRAW
    mrm   wc.lpfnWndProc, OFFSET WndProc  ;rdx
    mov   wc.cbClsExtra, NULL
    mov   wc.cbWndExtra, NULL
    push   hInstance
    pop   wc.hInstance
    mov   wc.hbrBackground, COLOR_WINDOW+1
    mov   wc.lpszMenuName, NULL
    lea   rdx, ClassName
    mov   wc.lpszClassName, rdx
    invoke    LoadIcon, NULL, IDI_APPLICATION
    mov   wc.hIcon, rax
    mov   wc.hIconSm, rax
    invoke  LoadCursor, NULL, IDC_ARROW
    mov   wc.hCursor, rax

    invoke   RegisterClassEx, ADDR wc

    invoke CreateWindowEx, NULL,\
           ADDR ClassName,\
           ADDR AppName,\
           WS_OVERLAPPEDWINDOW,\
           CW_USEDEFAULT,\
           CW_USEDEFAULT,\     
           CW_USEDEFAULT,\
           CW_USEDEFAULT,\
           NULL,\
           NULL,\
           hInst,\
           NULL
    mov   hwnd, rax

invoke   ShowWindow, hwnd, CmdShow
invoke   UpdateWindow, hwnd

  lbl:
     invoke   GetMessage, ADDR msg, NULL, 0,0
     test rax, rax
     jz @F
     invoke   TranslateMessage, ADDR msg
     invoke   DispatchMessage, ADDR msg
     jmp lbl
  @@:

    mov   rax, msg.wParam
    ret

WinMain ENDP

; --------------------------------------------------------------------

WndProc PROC hWin:QWORD, uMsg:QWORD, wParam:QWORD, lParam:QWORD

; LOCAL hWnd:QWORD
; LOCAL uMsg:QWORD
; LOCAL wParam:QWORD
; LOCAL lParam:QWORD

; mov   rcx, hWnd
; mov   rdx, uMsg
; mov   r8, wParam
; mov   r9, lParam

    .if uMsg == WM_CLOSE
       invoke SendMessage,hWin,WM_DESTROY,0,0

    .elseif uMsg == WM_DESTROY
        invoke PostQuitMessage,NULL

    .else
      ; unused in this example
    .endif

   invoke DefWindowProc,hWin,uMsg,wParam,lParam
   ret

WndProc ENDP

; --------------------------------------------------------------------

END


jj2007

For those dare-devils who have Masm32 and MasmBasic installed (and nothing else :P), there is always, as a last resort, the ultra-compatible dual 32-/64-bit Gui template hidden under menu File/New Masm source/Dual 32/64 bit console/GUI templates (5,632 bytes exe attached; note that the box showing "This template was built with ml64 in 64-bit mode" is a RichEdit control):

aw27

Quote from: Siekmanski on March 21, 2018, 01:37:29 AM
Are you sure? In my universe you and Hutch are separated by only 9 hours.  :biggrin:
Don't forget that in Sydney now is Wednesday not Tuesday. So the difference is more likely to be 15 hours.
As a curiosity there are places pretty close, I can't remember which they are, that are separated by more than 25 hours.

Hell, but you are right. In relation to the frame of hours the difference is indeed only 9 hours! Who cares about the day of the week?  :biggrin: