I can not get it to work. I simply do not know what is wrong. The simple window program assembles and link OK and all constant defined in the headers work just fine. This has to be 64 bit and GoAsm. I do understand how the example program works that is in the GoAsm manual, but I wanted to use the header files. Thanks for any help.
#define LINKFILES
#include c:\goasm\headers\windows.h
; --------------------------------------------------------
DATA SECTION
ALIGN 8
hInstance dq 0
hWnd DQ 0
hButton0 dq 0
hEdit0 dq 0
idButton0 dq 5001
idEdit0 dq 6001
szClassName db 'SarelClass',0
szDisplayName db 'Hallo Sarel',0
szButtonClass db 'BUTTON',0
szEditClass db 'EDIT',0
szCaption1 db 'Error1',0
szText1 db 'RegisterWindow failed',0
; --------------------------------------------------------
CODE SECTION
START:
INVOKE GetModuleHandleA,0
mov [hInstance],RAX
invoke WinMain,[hInstance],0,0,SW_SHOWDEFAULT
invoke ExitProcess,rax
; --------------------------------------------------------
WinMain frame hInst, hPrevInst, CmdLine, CmdShow
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
mov D[wc.cbSize],sizeof WNDCLASSEX
mov D[wc.style],CS_HREDRAW or CS_VREDRAW or CS_BYTEALIGNWINDOW
mov Q[wc.lpfnWndProc],ADDR WndProc
mov D[wc.cbClsExtra],0
mov D[wc.cbWndExtra],0
mov rax,[hInst]
mov [wc.hInstance],rax
invoke LoadIcon,[hInst],500
mov Q[wc.hIcon],rax
invoke LoadCursor,0,IDC_ARROW
mov Q[wc.hCursor],rax
mov Q[wc.hbrBackground],COLOR_WINDOW+1
mov Q[wc.lpszMenuName],0
mov Q[wc.lpszClassName],ADDR szClassName
mov Q[wc.hIconSm],0
invoke RegisterClassEx,ADDR wc
invoke CreateWindowEx,WS_EX_OVERLAPPEDWINDOW,\
ADDR szClassName,\
ADDR szDisplayName,\
WS_OVERLAPPEDWINDOW,\
[20],[20],[500],[400],\
0,0,\
[hInst],0
cmp rax,0
jne >> Over
invoke MessageBox, NULL, 'CreateWindow failed', 'ERROR', MB_OK
invoke ExitProcess,0
Over:
mov Q[hWnd],rax
invoke ShowWindow,[hWnd],SW_SHOWNORMAL
invoke UpdateWindow,[hWnd]
StartLoop:
invoke GetMessage,addr msg,0,0,0
cmp eax,0
je >> ExitLoop
invoke TranslateMessage,ADDR msg
invoke DispatchMessage,ADDR msg
jmp StartLoop
ExitLoop:
mov rax,[msg.wParam]
ret
endf
; --------------------------------------------------------
WndProc frame hWin, uMsg, wParam, lParam
USES rbp,rbx,rsi,rdi
LOCAL hDC:Q
LOCAL rct:RECT
LOCAL ps:PAINTSTRUCT
mov eax,[uMsg]
cmp eax,WM_DESTROY
je >> Msg1
jmp DefaultProc
Msg1:
invoke PostQuitMessage,0
xor rax,rax
ret
DefaultProc:
INVOKE DefWindowProc, [hWnd], [uMsg], [wParam], [lParam]
ret
endf
What are these brackets good for??
[20],[20],[500],[400]
Yes, remove the brackets, and also change the first parameter of your window proc from hWin to hWnd. After those corrections it worked for me.
Those brackets ?? I dont know... Battle scars.
There were TopX, TopY, Width and Height in there once. It didnt look wrong until the question was asked. :icon_mrgreen:
I changed the hWin to hWnd also. But this did not work. When I comment out the message box part the program runs but does not show. I need to end the process in task manager.
Below is my batch file that I use
cls
path = c:\goasm\headers;c:\Goasm
set INCLUDE=c:\goasm\headers
GoAsm /l /x64 Hi.asm
GoLink Hi.obj user32.dll kernel32.dll gdi32.dll
Quote from: Sarel on August 02, 2012, 04:22:10 AM
I changed the hWin to hWnd also. But this did not work.
The only thing I changed in your code, except this and the brackets, was the path for windows.h, so I don't have any more ideas at the moment. Your program works for me and I can see the window. I am on Win7 x64 SP1.
I'm on Win 7 64 bit Ultimate. Also service pack 1. My goasm files are all newly downloaded. Even my hard drive is newly formatted and reloaded. Previously I tried Masm 64bit, but that was a disaster. Strangely the CreateWindow also returned zero then. I can still use the same method as in the GoAsm example but then I need to build my own header file as some of the structures and constants get duplicated. Thanks for your support and also to every one who helped Shankle with his problems. It helped me set up and use the header files.
I am trying again with this window.
Below is the listing for the program. When I assemble it for 32bit (/x86 in the batch file) it shows up on screen. When assembling for 64 bit (/x64) with the two d type indicators (for wc.hbrBackground and wc.lpszMenuName ) changed to q it assembles and build the executable file. The window never shows and the program needs to be stopped by stopping the process. Right after RegisterClass I have GetClassInfo which fails. On my PC the message is "Class does not exist" The RegisterClass function executes successfully.
Please help.
#define LINKFILES
#include c:\goasm\headers\windows.h
; --------------------------------------------------------
DATA SECTION
ALIGN 8
hinst dq 0
ptrCmdLine dq 0
hButton0 dq 0
hEdit0 dq 0
idButton0 dq 5001
idEdit0 dq 6001
szClassName db "SarelKlas",0
szDisplayName db "Hallo Sarel",0
szButtonClass db "BUTTON",0
szEditClass db "EDIT",0
; --------------------------------------------------------
CODE SECTION
START:
ALIGN 8
INVOKE GetModuleHandle,0
mov [hinst],RAX
invoke GetCommandLine
mov [ptrCmdLine],rax
invoke WinMain,[hinst],0,rax,SW_SHOW
invoke ExitProcess,rax
; --------------------------------------------------------
WinMain frame hInst, hPrevInst, CmdLine, CmdShow
LOCAL wc:WNDCLASS
LOCAL sc:WNDCLASS
LOCAL msg:MSG
LOCAL hWnd:q
LOCAL Temp:q
invoke SetLastError,0
mov D[wc.style],CS_HREDRAW or CS_VREDRAW or CS_BYTEALIGNWINDOW
mov rax,addr WndProc
mov [wc.lpfnWndProc],rax
mov D[wc.cbClsExtra],0
mov D[wc.cbWndExtra],0
mov rax,[hInst]
mov [wc.hInstance],rax
invoke LoadIcon,0,IDI_APPLICATION
mov [wc.hIcon],rax
invoke LoadCursor,0,IDC_ARROW
mov [wc.hCursor],rax
mov d[wc.hbrBackground],COLOR_WINDOW+1
mov d[wc.lpszMenuName],0
mov rax,addr szClassName
mov [wc.lpszClassName],rax
invoke RegisterClass,addr wc ;address of the class structure to register
mov [Temp],rax
invoke GetClassInfo,[hInst],addr szClassName,addr sc
cmp rax,0
jne > Over0
;invoke MessageBox, NULL, 'GetClassInfo failed', 'ERROR', MB_OK
invoke GetLastError
sub esp,512
xor ecx,ecx
mov edx,esp
invoke FormatMessage,FORMAT_MESSAGE_FROM_SYSTEM,ecx,eax,ecx,edx,512,ecx
mov edx,esp
xor ecx,ecx
invoke MessageBox,ecx,edx,ecx,ecx
add esp,512
invoke ExitProcess,0
Over0:
invoke CreateWindow,addr szClassName,addr szDisplayName,\
WS_OVERLAPPEDWINDOW or WS_VISIBLE,\
20,20,500,400,\
0,0,\
[hInst],0
mov [hWnd],rax
cmp rax,0
jne > Over1
;invoke MessageBox, NULL, 'CreateWindowEx failed', 'ERROR', MB_OK
invoke GetLastError
sub esp,512
xor ecx,ecx
mov edx,esp
invoke FormatMessage,FORMAT_MESSAGE_FROM_SYSTEM,ecx,eax,ecx,edx,512,ecx
mov edx,esp
xor ecx,ecx
invoke MessageBox,ecx,edx,ecx,ecx
add esp,512
invoke ExitProcess,0
Over1:
invoke ShowWindow,[hWnd],[CmdShow]
invoke UpdateWindow,[hWnd]
StartLoop:
invoke GetMessage,addr msg,0,0,0
cmp eax,0
je > ExitLoop
invoke TranslateMessage,ADDR msg
invoke DispatchMessage,ADDR msg
jmp StartLoop
ExitLoop:
mov rax,[msg.wParam]
ret
endf
; --------------------------------------------------------
WndProc frame hWin, uMsg, wParam, lParam
USES rbp,rbx,rsi,rdi
LOCAL hDC:q
mov eax,[uMsg]
cmp eax,WM_DESTROY
je > msgDestroy
cmp eax,WM_CREATE
je > msgCreate
jmp > DefaultProc
msgDestroy:
invoke PostQuitMessage,0
xor rax,rax
ret
msgCreate:
xor eax,eax
ret
DefaultProc:
INVOKE DefWindowProc, [hWin], [uMsg], [wParam], [lParam]
ret
endf
I'm hardly the one to be giving advice but doesn't the Winmain statement
need to be something like this:
"invoke WinMain, [hInstance],NULL,[CommandLine],SW_SHOWDEFAULT"
I am doing one in 32-bit so maybe it is different from yours.
Running Windows 7 Pro 32-bit.
when he invoke's WinMain, RAX holds a pointer to the command line string
SW_SHOW, SW_SHOWDEFAULT - i doubt that it matters much
it seems that windows substitutes the default value from STARTUPINFO
the first time ShowWindow is called, anyways
the WinMain invoke is strictly a compiler construct
it has nothing to do with how the kernel loads and executes the program
the kernel does not look for this function, nor does it ever attempt to reference it
so - you can eliminate that call if you like
i believe the WinMain construct shows up in a lot of assembly code because
the guys that figured out how to write windows programs in assembler did so
by disassembling C-compiled programs
they saw the WinMain construct and stayed with it - lol
it is, of course, described in MSDN documentation, as well
but, it is described for the benefit of programmers that use compilers
while we're on the subject, the command line pointer that is passed to a compiled WinMain
is pre-parsed, so it would not be exactly correct to pass the command line pointer as is
in an actual compiled program there are a lot of other things that happen before WinMain is called
for example, if you use certain parts of MSVCRT.DLL, some initialization may be performed
i am sure that other things happen, as well - such as InitCommonControlsEx, FPU initialization, and so on
the compiler knows which functions are used and performs the required init
as assembly language programmers, we are responsible for all that stuff, ourselves
You're using WNDCLASS and RegisterClass instead of WNDCLASSEX and RegisterClassEx.
This is probably not a good decision, because WNDCLASS will cause problems if structure alignment isn't set properly to QWORD. OTOH, WNDCLASSEX is "by design" properly aligned to QWORD, and hence a missing struct alignment doesn't matter there.
A quick lookk at the listing or a disassembly will tell you whether everything is ok.
GoAsm handles proper structure alignment, so WNDCLASS and RegisterClass should still be fine. The listing does not go into LOCAL expansion details, so it was not readily apparent, but the size was off. I believe all that you need to do is put this before your #include line:
#define WIN64
That will give you the 64-bit structures instead of the 32-bit ones.
#define WIN64
YES !! The window is there. I added that as the first line. Thank you wjr. I have been having a hard time with this. Also thanks to dedndave for the GetlastError / FormatMessage.
Now I can start with the 64 bit assembler and find out what changed. Things like mov [wc.lpfnWndProc],addr WndProc does not work. First move the address into a register and then into a memory location. That GetlastError helped me there as well.
I hope this simple window program can help others start faster than I did. Comming from 32 bit this program looks very similar. Also I hope something similar can be included as an example with the GoAsm manual. The current example2 defines its own structures and when you want to use the header files those structure clash.
Thanks every one.