I thought I would post this as it is my commented version of tutorial#3 of eczelions tutorials. I know he did a fairly good job of explaining it but I have put some debug stuff that i got from this message board and also tried to explain how I believe the program is running. I know it looks a bit messy, hopefully it will still explain the process though



.386 ;This is the Machine type
.model flat,stdcall ;This is the syntax to use for calls
option casemap:none ;This allows the keys to be case sensitive


include windows.inc ;various include bits
include kernel32.inc
include user32.inc
includelib kernel32.lib ;and there associated libraries
includelib user32.lib


;have to define the prototype before calling it as a procedure.
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD

.CONST ;numerical variables that don't change.
; DBUG equ 1 ;we uncomment this to run debug instructions on the program

.DATA

AppName db "An Application",0 ;String variables that don't change
ClassName db "A Class Name",0 ;always finish with a terminating 0 as
ErrorHandle db "Incorrect Parent Handle",0 ;it is in ascii format
ErrorMsgBoxTitle db "Critical Error",0
ErrorWindow db "Could not create or update the window",0
.DATA?

hInstance HINSTANCE ? ;strings that change
CommandLine LPSTR ?

.code ;start of code section

start: ;our first label

invoke GetModuleHandle,NULL ;grab the handle for our module
mov hInstance,eax ;put it into hInstance
invoke GetCommandLine ;grab the command line
mov CommandLine,eax ;put it in CommandLine
invoke WinMain,hInstance,NULL,CommandLine,SW_SHOWDEFAULT ;invoke our procedure
invoke ExitProcess,eax ;then exit


;this is the beginning of our procedure
WinMain proc hInst:HINSTANCE,
hPrevInst:HINSTANCE,
CmdLine:LPSTR,
CmdShow:DWORD


LOCAL wc:WNDCLASSEX ;set up local variables. wc is our windows class, msg is the messenger variable
LOCAL msg:MSG ;and hWnd is the handle of our Main Window.
LOCAL hWnd:HWND

mov wc.cbSize,SIZEOF WNDCLASSEX ;set the variables for the wc class
mov wc.style,CS_HREDRAW+CS_VREDRAW
mov wc.lpfnWndProc,OFFSET WinProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInstance
pop wc.hInstance
invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
mov wc.hbrBackground,COLOR_WINDOW+1
mov wc.lpszMenuName,NULL
mov wc.lpszClassName,OFFSET ClassName
invoke RegisterClassEx,addr wc ;register our class
invoke CreateWindowEx, ;begin the creation of the window
NULL, ;this will give us our window handle
ADDR ClassName,
ADDR AppName,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInst,
NULL
mov hWnd,eax ;place the handle in hWnd
invoke ShowWindow,hWnd,SW_SHOWNORMAL ;make the window visible
invoke UpdateWindow,hWnd ;keep the window refreshed
;**** The window doesn't display if the procedure is not running

IFDEF DBUG ;This section is only attached to the code if the DBUG variable is defined. ;debug section only
;used to check for errors
.IF !EAX ;execute next instruction if there was an error creating the window
INVOKE MessageBox,ESI,addr ErrorWindow,addr ErrorMsgBoxTitle,MB_OK ;message and exit if failure
JMP EXIT ;after creating a notification box we jump to the exit
.ENDIF

ENDIF ;not that the . in front of IF means it is run at run time. No . means it is run at assembly time

.WHILE TRUE ;enter the message loop

invoke GetMessage,addr msg,NULL,0,0 ;get our message. usually wm_paint first up.

IFDEF DBUG ;more debug script.. only gets assembled if we create the variable DBUG
.IF eax==-1 ;another way of checking for values. check to see if eax is -1
invoke MessageBox, NULL,addr ErrorHandle,addr ErrorMsgBoxTitle, MB_OK
JMP EXIT ;invoke a message box and exit
.ENDIF
ENDIF ;end of our debug section which was used to check if there was an error in the window handle.

.BREAK .IF (!EAX) ;this is realtime code.. breaks the loop if eax is 0. i.e. program is finished.
invoke TranslateMessage, ADDR msg ;translate message to ansi code.
invoke DispatchMessage, ADDR msg ; dispatch the message and run the procedure
mov eax,msg.wParam ;load the message for the exit process
.ENDW ;I'm not sure if this is how the procedure is run.. i'm just guessing at present.
EXIT: ;our exit label.. so that we can jump to the end of the loop if there is an error.
ret ;return to the calling function.. i.e. top of this program after invoke WinMain. The next line is invoke exitprocess

WinMain endp ;the end of our WinMain procedure.. this probably never really gets executed.

WinProc proc hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM ;the start of the window procedure

.IF uMsg==WM_DESTROY ;if we got the exit message from getmessage in WinMain.
invoke PostQuitMessage,NULL ;then we invoke the quitmessage grabber
.ELSE ;otherwise we run the default window cleaning stuff which takes care of all the
invoke DefWindowProc,hWnd,uMsg,wParam,lParam ;other messages.
ret ;then we return to WinMain..
.ENDIF ;if we use post quitmessage we will end up here to exit the loop.

xor eax,eax ;after recieving the post quit message, we execute a zero out of eax. I.E. this makes it 0

ret ;then we return control to WinMain So that it can exit, because it has a 0 message.

WinProc endp ;this is just the end of the procedure

end start ;and this is the end of our program, that displayed a window.
Posted on 2003-12-01 19:02:43 by Phase Verocity