I have kept working on trying to get a basic window that looks more like conventional API code. It would seem that any procedure that has more than 4 arguments needs to have a stack frame. Those with less arguments appear to work fine with no stack frame as do pure mnemonic procedures. Something I found unusual was that I could not get a clean exit with the window unless I specifically used SendMessage to WM_DESTROY from the WM_CLOSE message location.
This is the test piece.
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
OPTION DOTNAME
option casemap:none
include \masm64\include\temphls.inc
include \masm64\include\win64.inc
include \masm64\include\kernel32.inc
include \masm64\include\user32.inc
include \masm64\include\msvcrt.inc
includelib \masm64\lib\kernel32.lib
includelib \masm64\lib\user32.lib
includelib \masm64\lib\msvcrt.lib
OPTION PROLOGUE:rbpFramePrologue
OPTION EPILOGUE:rbpFrameEpilogue
include macros64.inc
WNDCLASSEX64 STRUCT QWORD
cbSize dd ?
style dd ?
lpfnWndProc dq ?
cbClsExtra dd ?
cbWndExtra dd ?
hInstance dq ?
hIcon dq ?
hCursor dq ?
hbrBackground dq ?
lpszMenuName dq ?
lpszClassName dq ?
hIconSm dq ?
WNDCLASSEX64 ENDS
.data
ClassName db "API Window Class",0
AppName db "Bare API Window",0
.data?
hInstance dq ?
hWnd dq ?
sWid dq ?
sHgt dq ?
lft dq ?
top dq ?
wid dq ?
hgt dq ?
.code
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
main proc
LOCAL wcex:WNDCLASSEX64
mov hInstance, rv64(GetModuleHandle,0)
mov wcex.cbSize, SIZEOF WNDCLASSEX64
mov wcex.style, 0
mov rax, OFFSET WndProc
mov wcex.lpfnWndProc, rax
mov wcex.cbClsExtra, 0
mov wcex.cbWndExtra, 0
mov rax, hInstance
mov wcex.hInstance, rax
mov wcex.hIcon, 10003h
mov wcex.hCursor, 10003h
mov wcex.hbrBackground, COLOR_WINDOW
mov wcex.lpszMenuName, 0
mov rax, OFFSET ClassName
mov wcex.lpszClassName, rax
mov wcex.hIconSm, 10003h
invoke RegisterClassEx, ADDR wcex
invoke GetSystemMetrics,SM_CXSCREEN
mov r11, rax
shr rax, 2
mov lft, rax
mov rax, r11
shr rax, 1
mov wid, rax
invoke GetSystemMetrics,SM_CYSCREEN
mov r11, rax
shr rax, 2
mov top, rax
mov rax, r11
shr rax, 1
mov hgt, rax
invoke CreateWindowEx,0,addr ClassName,addr AppName,\
WS_OVERLAPPEDWINDOW or WS_VISIBLE,\
lft,top,wid,hgt,0,0,hInstance,0
mov hWnd, rax
call msgloop
invoke ExitProcess, rax
main endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
msgloop proc
LOCAL msg :MSG
mov r11, rdi ; preserve rdi
lea rdi, msg ; load structure address
jmp gmsg
@@:
fn64 TranslateMessage,rdi
fn64 DispatchMessage,rdi
gmsg:
fn64 GetMessage,rdi,0,0,0
test rax, rax
jnz @B
mov rdi, r11 ; restore rdi
fn64 ExitProcess, 0
retn
msgloop endp
OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
WndProc proc
LOCAL64 hWin
LOCAL64 uMsg
LOCAL64 wParam
LOCAL64 lParam
mov hWin, rcx
mov uMsg, rdx
mov wParam, r8
mov lParam, r9
.if uMsg == WM_COMMAND
.elseif uMsg == WM_CLOSE
.data
text db "Seeya round like a Rubens",0
titl db "WM_CLOSE here",0
ptxt dq text
pttl dq titl
.code
fn64 MessageBox,0,ptxt,pttl,0
fn64 SendMessage,hWin,WM_DESTROY,0,0
.elseif uMsg == WM_DESTROY
fn64 PostQuitMessage,NULL
.endif
fn64 DefWindowProc,hWin,uMsg,wParam,lParam
retn
WndProc endp
OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
end
; ----------
; left overs
; ----------
; .elseif uMsg == WM_SYSCOMMAND
; .if wParam == SC_CLOSE
; fn64 SendMessage,wHandle,WM_DESTROY,0,0
; .endif
; fn64 SendMessage,wHandle,WM_SYSCOMMAND,SC_CLOSE,NULL