News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Using goasm / Window does not appear

Started by pro3carp3, July 12, 2006, 12:30:18 PM

Previous topic - Next topic

pro3carp3

I am attempting to switch to goasm from masm for several reasons, one of which is to have more control jumping into and out of procedures and being able to push the arguments onto the stack well ahead of the call.  Granted, this can be accomplished with masm, however, the goasm syntax seems to be much cleaner.  I've become accustomed to the use of invoke, so it has been somewhat of a challenge for me to "hand code" the function call.  I'd rather not use the arg and frame as I want complete control of the implementation.  Here is what I have so far:


;HELLOWIN

#include F:\goasm\includea\windows.inc
#include F:\goasm\includea\all_api.inc

CONST SECTION
align 4

sAppName db "HelloWin",0
sWndClassName db "HelloWinClass",0

DATA SECTION
align 4

;INITIALIZED DATA

;UNINITIALIZED DATA
hAppInst dd ?
psCmdLine dd ?
hWnd dd ?
msg MSG <?>
wc WNDCLASSEX <?>

CODE SECTION

Start:

;Get instance handle
push NULL
call GetModuleHandle
mov [hAppInst], eax

;Get command line
call GetCommandLine
mov [psCmdLine], eax

;Set up windows class
mov d[wc.cbSize], sizeof WNDCLASSEX
mov d[wc.style], CS_HREDRAW | CS_VREDRAW
mov d[wc.lpfnWndProc], addr WndProc
mov d[wc.cbClsExtra], NULL
mov d[wc.cbWndExtra], NULL
mov eax, [hAppInst]
mov d[wc.hInstance], eax
mov d[wc.hbrBackground], COLOR_WINDOW+1
mov d[wc.lpszMenuName], NULL
mov d[wc.lpszClassName], addr sWndClassName
push IDI_APPLICATION
push NULL
call LoadIcon
mov d[wc.hIcon], eax
mov d[wc.hIconSm], eax
push IDC_ARROW
push NULL
call LoadCursor
mov d[wc.hCursor], eax

;Register window class
push addr wc
call RegisterClassEx

;Create window
push NULL
push [hAppInst]
push NULL
push NULL
push CW_USEDEFAULT
push CW_USEDEFAULT
push CW_USEDEFAULT
push CW_USEDEFAULT
push WS_OVERLAPPEDWINDOW
push addr sAppName
push addr sWndClassName
push NULL
call CreateWindowEx
mov [hWnd], eax

;Show window
push SW_SHOWDEFAULT
push [hWnd]
call ShowWindow

;Update window
push [hWnd]
call UpdateWindow

;Message Loop
L1:
push 0
push 0
push NULL
push addr msg
call GetMessage
cmp eax, 0
jz >L2
push addr msg
call TranslateMessage
push addr msg
call DispatchMessage
jmp <L1
L2:

;Exit app
push 0
;push [msg.wParam]
call ExitProcess

WndProc:
;hWnd [ebp+8]
;uMsg [ebp+12]
;wParam [ebp+16]
;lParam [ebp+20]

push ebp
mov ebp, esp

cmp d[ebp+12], WM_DESTROY
je >.Destroy

.DefWndProc:
push [ebp+20]
push [ebp+16]
push [ebp+12]
push [ebp+8]
call DefWindowProc

.End_WndProc:

xor eax, eax
pop ebp
ret 16

.Destroy:
push NULL
call PostQuitMessage
jmp <.End_WndProc


1.  The window does not appear on the screen.  I can step through the code with ollydbg and it does enter the message loop, but I cannot close the window as there is no visible interface.

2.  I'd like to access the parameters using a structure, but I don't know how to tell the compiler to base the structure on ebp.  (e.g. like assume in masm.)

Thanks for any help you can give with these two issues or any other comments you may have with my code.  It is greatly appreciated.
LGC

jorgon

Hi pro3carp3!

Welcome to GoAsm!

Personally I would suggest that the window procedure needs some attention.

DefWindowProc should be permitted to pass whatever value it returns in EAX, back to the system.  You have it returning EAX=0 in all cases. 
Just in passing I would also say that it's actually a good idea in the WndProc always to save and restore EDI,ESI,EBX even if not using them at the moment (you will eventually need them), although I suspect you know that and just wanted to keep it very simple.

By the way, GoAsm does support INVOKE.

As an alternative to starting with MASM code and converting to GoAsm, an alternative might be to start with the GoAsm HelloWorld sample files, which are available from the GoAsm help file.  Just a suggestion!

Author of the "Go" tools (GoAsm, GoLink, GoRC, GoBug)

donkey

Hello pro3carp3,

As Jeremy says the INVOKE pseudo-macro is supported by GoAsm, though it is better written and more powerful than it's masm counterpart. I cannot see anything blatently obvious that is wrong with your code but I would suggest that you re-code it using INVOKE if that is what you are used to, it will make finding small bugs easier.

Donkey
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

Infro_X

As jorgon said, you are always returning 0 which is inadvisable.
Your CreateWindow is also failing (Which GetLastError would show) because your WM_NCCREATE is returning FALSE (0) instead of TRUE (1).
WM_NCCREATE needs a return of 1 for success.
WM_CREATE needs a return of 0 for success.

Boucly

Good eye, Infro_X

Does it mean that it should be like this


WndProc:
;hWnd [ebp+8]
;uMsg [ebp+12]
;wParam [ebp+16]
;lParam [ebp+20]

push ebp
mov ebp, esp

cmp d[ebp+12], WM_DESTROY
xor eax, eax ; zero'ing  out eax only for message needed 0 return value.
je >.Destroy

.DefWndProc:
push [ebp+20]
push [ebp+16]
push [ebp+12]
push [ebp+8]
call DefWindowProc
; leaving the eax as the return value from DefWindowProc, whatever it may be.

.End_WndProc:

[glow=red,2,300]; take out xor eax, eax[/glow]
pop ebp
ret 16


I know it is a long time since the first post but would still cause the same problem?

Boucly

Infro_X

That looks right, but personally I like using jump tables which requires something like this.


.data
MessageTable DD 2048 dup (?)

.code
mov [MessageTable+WM_DESTROY*4],wmdestory
mov [MessageTable+WM_SIZE*4],wmsize

WndProc:  ;(I use frame but whatever)
push ebp;
mov ebp,esp
sub esp,wndprocstacksize
mov eax,[ebp+Ch]
call [eax]
push [ebp+14h]
push [ebp+10h]
push [ebp+Ch]
push [ebp+8h]
call [DefWindowProc]
mov esp,ebp
pop ebp
retn 10h

wmdestroy:
//esp=return pointer
//esp+4 = wndproc stack
//ebp=stack pointer
push 0
call PostQuitMessage
ret

wmsize:
movzx eax,w[ebp+14h]
movzx ecx,w[ebp+16h]
//resize child windows with eax/ecx calculations
ret

Boucly

Actually I though of using a lookup table like that :wink , but I thought that it may not be smart to use up such a large amount of memory if I only use a few of the WM_thingy even if it is data intensive programs. Don't you think? 16×2048 = 32768 bit = 4kB. Okay, maybe 4kB is not a lot for modern computers but ... never mind. :red

Anyway, why 2048? that's 800h, right. Sooooo, is there only 2048 messages or something?

Boucly

jorgon

It's a matter of taste, but personally I like the table method:-


DATA
;this table, in the data section holds the messages to be processed
MESSAGES DD (ENDOF_MESSAGES-$-4)/8      ;=number to be done
         DD  1h,CREATE,2h,DESTROY,0Fh,PAINT
ENDOF_MESSAGES:           ;label used to work out how many messages
;******************************************
;
CODE
;
CREATE:                 ;one of the few messages dealt with in this example
XOR EAX,EAX             ;return zero to make window
RET
;
DESTROY:                ;one of the few messages dealt with in this example
PUSH 0
CALL PostQuitMessage    ;exit via the message loop
STC                     ;go to DefWindowProc too
RET
;
PAINT:
;code to paint window goes here
XOR EAX,EAX
RET
;
;********** this is a general window procedure (ANSI version) which in an ordinary
;********** program deals with all messages sent to the window
GENERAL_WNDPROC:        ;eax can be used to convey information to the call
PUSH EBP                ;use ebp to avoid using eax which may hold information
MOV EBP,[ESP+10h]       ;uMsg
MOV ECX,[EDX]           ;get number of messages to do
ADD EDX,4               ;jump over size dword
L2:
DEC ECX
JS >L3
CMP [EDX+ECX*8],EBP     ;see if its the correct message
JNZ L2                  ;no
MOV EBP,ESP
PUSH ESP,EBX,EDI,ESI    ;save registers as required by Windows
ADD EBP,4               ;allow for the extra call to here
;now [EBP+8]=hwnd, [EBP+0Ch]=uMsg, [EBP+10h]=wParam, [EBP+14h]=lParam,
CALL [EDX+ECX*8+4]      ;call the correct procedure for the message
POP ESI,EDI,EBX,ESP
JNC >L4                 ;nc=return value in eax - don't call DefWindowProc
L3:
PUSH [ESP+18h],[ESP+18h],[ESP+18h],[ESP+18h]     ;allowing for change of ESP
CALL DefWindowProcA
L4:
POP EBP
RET
;
;******************* This is the actual window procedure
WndProc:
MOV EDX,ADDR MESSAGES   ;give edx the list of messages to deal with
CALL GENERAL_WNDPROC    ;call the generic message handler
RET 10h                 ;restore the stack as required by caller
Author of the "Go" tools (GoAsm, GoLink, GoRC, GoBug)

Boucly

Sorry if/that it is off topic, but does anyone mind looking into what inefficiency/problem this kind of table has/can have or bugs that can creep up.,


WindowProcedure proc window_handle :DWORD,
window_message :DWORD,
wParam :DWORD,
lParam :DWORD

cmp window_message, WM_PAINT
je window_message_select_WM_PAINT
cmp window_message, WM_DESTROY
je window_message_select_WM_DESTROY
jmp window_message_select_default

window_message_select_WM_PAINT:
win32_BeginPaint 1, application_temp_HDC, window_handle, offset application_temp_PAINTSTRUCT
win32_EndPaint 1, application_temp_HDC, window_handle, offset application_temp_PAINTSTRUCT
return 0
jmp window_message_select_finished

window_message_select_WM_DESTROY:
win32_PostQuitMessage 0, 0, NULL
return 0
jmp window_message_select_finished

window_message_select_default:

win32_DefWindowProc 0, 0, window_handle, window_message, wParam, lParam

window_message_select_finished:

ret

WindowProcedure endp


Boucly

[attachment deleted by admin]