shankle,
I noticed a few things. GoAsm doesn't use if/then/else syntax. It is only for conditional assembly. Using a combination of compares and/or testing flags is the way you have to go. Anyway, it'll keep you much more focused on the state of the machine. Knowing the zero, carry, and sign flags inside-out is a must. Also, please read the GoAsm manual section on stack frames/local variables. There is a specific order, e.g. FRAME, USES, LOCAL, CODE,RET,ENDF / ENDU.
I tried to see if I could fix your WndProc--it was just too much for me--sorry. It needs to be simpler--much simpler. So, I've included the bare bones of one I use. It is also originally from the manual. I hope I didn't rip too much out, but it should basically work for you. The "message compares" use a table with the messages and the addresses of the message handler routines. If you want to be good at this you'll start using tables for much of what you do, especially math. Tables are magnitudes faster than anything else because you can branch on flags--and they will always work better than a bunch of slow, sloppy compares that you find in if/then statements. Sometimes (multiplication) tables can be big. But so what? Always better than slow. And you'll hear guys argue against that point. They probably didn't program 1 mHz 8-bit computers in the 70s & 80s, when every byte (and every cycle) mattered. Good assembly language is an art, no doubt about it. That stuff still matters. So, be an artist. Let the "C" guys rely on the fact they have (and need) a 3 gHz machine to make complicated stuff fly.
About saving registers: if you don't modify them in a procedure don't bother to push/pop them. Blindly pushing all the registers makes for slow code. Eventually you'll even start to notice the difference in execution speed. But, if you "use" them, then by all means you should "USES" them. That's the good thing about "USES". You just look through that particular procedure and code a "USES reg,reg,reg" etc for each register used IN THAT PROCEDURE. The exception is if you return something in, say eax. You'll wind up losing it if you "USES" it ;) . (Did that on purpose)
So, I hope you can use this. Study how that message table works. It's old-school, quality assembly--and it's FAST. And simple. It's Jeremy Gordon code...
CONST SECTION
; ******************** Window message table **********************
;
MESSAGES DD WM_CREATE, CREATE ;the message then the code address
DD WM_DESTROY, DESTROY
DD WM_PAINT, PAINT
DD WM_KEYDOWN, KEYDOWN
DD WM_TIMER, TIMER
CODE SECTION
WndProc:
FRAME hwnd, Msg, wParam, lParam ;establish stack frame, get params
;--------------------------------------
;FIND THE A MESSAGE WE'RE INTERESTED IN
;--------------------------------------
mov eax, [Msg] ;get in eax message sent by Windows
mov ecx, SIZEOF MESSAGES/8 ;get number of messages to look at
mov edx, ADDR MESSAGES
P1:
dec ecx ;count down to -1
js >.notfound ;if = -1 then call default win procedure
cmp [edx+ecx*8],eax ;check table if entry is correct message
jnz <P1 ;no, so loop back for next table entry
call [edx+ecx*8+4] ;call the correct procedure for the message
jnc >.exit
;----------------------------------------
;NO MATCH, SO PASS PARAMS BACK TO WINDOWS
;USE DEFAULT WINDOWS PROCEDURE
;----------------------------------------
.notfound
push [lParam]
push [wParam]
push [Msg]
push [hwnd]
call DefWindowProc
;------------------------------
;DESTROY STACK FRAME, EXIT BACK TO WINDOWS HERE
;------------------------------
.exit
ret
ENDF
;_________________________________________________________________________
;_________________________________________________________________________
PAINT: ; RE-DRAW WINDOW
USEDATA WndProc ;use parameters sent to WndProc
USES ebx,ecx,edx,esi,edi ;only save registers that you use in this procedure
;-------------------------------------------------------------
;---------------
;CALL BEGINPAINT
;---------------
invoke BeginPaint, [hwnd], ADDR ps
mov [hdc], eax
;updating/refreshing the window goes here
;-------------
;CALL ENDPAINT
;-------------
invoke EndPaint, [hwnd], ADDR ps
;---------
;EXIT HERE
;---------
xor eax,eax ;return not carry and eax = 0
ret
ENDU ;finished using parameters sent to WndProc
;_________________________________________________________________________
;_________________________________________________________________________
CREATE: ; PROGRAM INITIALIZATION
USEDATA WndProc ;use parameters sent to WndProc
USES ebx,ecx,edx,esi,edi ;only save registers that you use in this procedure
;-------------------------------------------------------------
;program init goes here
;---------
;EXIT HERE
;---------
xor eax,eax ;return not carry and eax = 0
ret
ENDU ;finished using parameters sent to WndProc
;_________________________________________________________________________
;_________________________________________________________________________
DESTROY: ; PROGRAM CLEAN-UP
USEDATA WndProc ;use parameters sent to WndProc
USES ebx,ecx,edx,esi,edi ;only save registers that you use in this procedure
;-------------------------------------------------------------
invoke PostQuitMessage, NULL ;kill the application
;---------
;EXIT HERE
;---------
xor eax,eax ;return not carry and eax = 0
ret
ENDU ;finished using parameters sent to WndProc
;_________________________________________________________________________
;_________________________________________________________________________
KEYDOWN: ; PROCESS KEYPRESSES
USEDATA WndProc ;use parameters sent to WndProc
USES ebx,ecx,edx,esi,edi ;only save registers that you use in this procedure
;-------------------------------------------------------------
mov eax, [wParam]
;----------------------
;COMPARE TO ESCAPE KEY?
;----------------------
cmp eax, VK_ESCAPE
jne >E9
invoke PostQuitMessage, NULL ;kill the application
;---------
;EXIT HERE
;---------
E9:
xor eax,eax ;return not carry and eax = 0
ret
ENDU ;finished using parameters sent to WndProc
;_________________________________________________________________________
;_________________________________________________________________________
TIMER: ; PROCESS TIMERS
USEDATA WndProc ;use parameters sent to WndProc
USES ebx,ecx,edx,esi,edi ;only save registers that you use in this procedure
;-------------------------------------------------------------
;code if you process timers
;I always use timer proc outside the window
;---------
;EXIT HERE
;---------
xor eax,eax ;return not carry and eax = 0
ret
ENDU ;finished using parameters sent to WndProc