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
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
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
Here is an example using uasm for a simple 64bit window
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.
RegisterClassEx succeeds but CreateWindowEx fails. Right now I have no time to check why, sorry...
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
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
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
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
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.
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
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
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
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):(http://www.webalice.it/jj2006/pics/Window64.png)
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: