Original: masm32\example1\generic


.586			;minimum processor needed for 32 bit ASM code
.model flat,stdcall		;FLAT memory model & STDCALL calling
option casemap:none	; set code to case sensitive

;########################################################################


include C:\masm32\include\windows.inc

include C:\masm32\include\user32.inc
include C:\masm32\include\kernel32.inc

includelib C:\masm32\lib\kernel32.lib
includelib C:\masm32\lib\user32.lib

return MACRO arg

 mov eax,arg
 ret
ENDM



WinMain PROTO
WndProc PROTO :DWORD,:DWORD,:DWORD,:DWORD

;########################################################################



.data

szDisplayName 	db 'Generic',0
ClassName db 1,0
TheMsg db "Assembler, Pure & Simple",0
TheText db "Please Confirm Exit",0
hInstance		equ 400000h
wc	WNDCLASSEX 
.data?
msg MSG <>

.code


start:


invoke WinMain

invoke ExitProcess,eax ;cleanup & return

;###########################################################################

WinMain proc uses esi edi ebx  

	;==========================================
	;Fill WNDCLASSEX structure with required variables
	;==========================================
xor ebx,ebx

invoke LoadIcon,hInstance,500	; icon ID resource icon
mov wc.hIcon,eax
invoke LoadCursor,ebx,IDC_ARROW ;system cursor
mov wc.hCursor,eax


invoke RegisterClassEx,ADDR wc ;register the window class

	;=========================================
	;Center window at following size
	;=========================================
	
Wwd equ 500
Wht equ 350

invoke GetSystemMetrics,SM_CXSCREEN; get screen width in pixels
mov esi,eax

invoke GetSystemMetrics,SM_CYSCREEN
shr esi,1
shr eax,1
sub esi,Wwd/2
sub eax,Wht/2

	;==================================
	;Create the main application window
	;==================================

invoke CreateWindowEx,WS_EX_OVERLAPPEDWINDOW,
	addr ClassName,
	ADDR szDisplayName,
	WS_OVERLAPPEDWINDOW or WS_VISIBLE,
	esi,eax,Wwd,Wht,
	ebx,ebx,hInstance,ebx
	mov edi,eax


;=====================================
;Loop until PostQuitMessage is sent
;=====================================
mov esi, offset msg
StartLoop:
	
	invoke GetMessage,esi,ebx,ebx,ebx	;get each message
	or eax,eax				;exit if GetMessage()
	je ExitLoop				;returns 0
	invoke TranslateMessage, esi		;translate it
	invoke DispatchMessage,esi		;send it to message proc
	jmp StartLoop
ExitLoop:
	return msg.wParam

WinMain endp

;###########################################################################

WndProc proc uses edi ebx 	hWin :DWORD,
			uMsg :DWORD,
			wParam:DWORD,
			lParam:DWORD

mov eax,uMsg
xor ebx,ebx
mov edi,hWin
.IF eax == WM_COMMAND



;============ menu commands ==============

.IF wParam == 1000

 invoke SendMessage,edi,WM_SYSCOMMAND,SC_CLOSE,ebx

.ELSEIF wParam == 1900


 invoke MessageBox,edi,ADDR TheMsg,ADDR szDisplayName,ebx

.endif

;=========== end menu commands =============

.ELSEIF eax == WM_CLOSE


invoke MessageBox,edi,ADDR TheText,ADDR szDisplayName,MB_YESNO
.IF eax == IDYES
mov eax,WM_CLOSE
jmp d
.ENDIF


.ELSEIF eax == WM_DESTROY


invoke PostQuitMessage,ebx

.ELSE

d: invoke DefWindowProc,edi,eax,wParam,lParam
    jmp r

.ENDIF
xor eax,eax
r: ret

WndProc endp

end start


Posted on 2001-04-19 08:35:00 by The Svin
.586 ;minimum processor needed for 32 bit ASM code
The 586 is the pentium class processor, and the first 32 bit capable Intel processor was the 386..... Is there some other reason for the .586 (rather that .386 or .486)? I know that Agners docs don't have timings for the (3/4)86, and as your doing optimisations timings are important. Mirno
Posted on 2001-04-19 09:39:00 by Mirno
Alex, This simple callback is an example of why I build authodox style message handling procedures, they can be read and maintained yet they are simple too big for a register style approach. This one is very simple, I have some that are nested 4 conditions deep and are multiple screens long in things like an application's main message processing procedure. The reason why I go for code like the above is so it can be written error free and modified easily without having to have a major re-write each time for no worthwhile advantage. I agree with your approach at an algorithm level but at an architecture level, its very poor code design as it is very difficult to read and maintain. The introductory code examples in MASM32 are just that, they are written to be clear and easy to understand and they are written with an extendable architecture that does not need major recoding for each change. Putting static structures in the .DATA section is something you can do in a very small test aplication as it is very rare to have much in it so there is no real code size change but this will not work in an application size architecture, when you have multiple windows with different characteristics that require different registered classes, this practice just blows out the size of the .DATA section. Like other people who understand the difference, I have rewritten apps that were originally written in TASM with a mountain of static data in the .DATA section into a later design with dynamic code and the size drops considerably. Very small apps don't need a .DATA section, an uninitialised .DATA? section does the job and string data can easily be written into the .CODE section and you get a full section reduction in the size of the code. Regards, hutch@pbq.com.au

; #########################################################################

EditProc proc hCtl   :DWORD,
              uMsg   :DWORD,
              wParam :DWORD,
              lParam :DWORD

    LOCAL xPos :DWORD
    LOCAL yPos :DWORD

    .if uMsg == WM_CHAR

  ; ------------------------------------------
  ; Process key combinations for pasting text
  ; to ensure it is pasted in CF_TEXT format
  ; ------------------------------------------

    .elseif uMsg == WM_KEYDOWN
      .if wParam == VK_SHIFT
        mov pFlag, 1                ; set shift flag
      .elseif wParam == VK_CONTROL
        mov cFlag, 1                ; set control flag

      .elseif wParam == VK_V
        .if cFlag == 1
          invoke SendMessage,hEdit,EM_PASTESPECIAL,CF_TEXT,0
          mov eax, 0
          ret
        .endif

      .elseif wParam == VK_INSERT
        .if pFlag == 1
          invoke SendMessage,hEdit,EM_PASTESPECIAL,CF_TEXT,0
          mov eax, 0
          ret
        .endif
      .endif

    .elseif uMsg == WM_KEYUP
      .if wParam == VK_F1

      .elseif wParam == VK_F2
         invoke CallSearchDlg

      .elseif wParam == VK_F3
         invoke TextFind,ADDR SearchText,TextLen

      .elseif wParam == VK_SHIFT
        mov pFlag, 0
      .elseif wParam == VK_CONTROL
        mov cFlag, 0
      .endif

    .endif

    invoke CallWindowProc,lpEditProc,hCtl,uMsg,wParam,lParam

    ret

EditProc endp

; #########################################################################
Posted on 2001-04-19 10:38:00 by hutch--
:) It's just happend accidently. I left the comments from the original code. Of course .386 was right for the comments. But I usually replace .386 to .586 it does no harm just allow some Pentium instruction to be included in source. To avoid keeping in mind what number of proccessor I allowed at the beginning. That's it. The Svin.
Posted on 2001-04-19 10:42:00 by The Svin
By using anything 'less' than .586 you restrict the instructions you can use, the most handy one for example is rdtsc which reads the pentiums cycle counters, so If you're timing a bit of code it's a good one to have. Using it with .386 will cause an 'unrecognised instruction' error. umbongo
Posted on 2001-04-19 10:46:00 by umbongo
The bottom line these days is .486 as it will run 32 bit windows, .386 works with most of the integer instructions as it directs the assembler to build 32 bit code. The problem with building code with .686 .XMM and the like is that it will only run on a PIII and there are a lot of computers out there that cannot run it. Even using .586 .MMX excludes pentiums without MMX so unless you are writing code for later model machines only and can be sure about it, selecting higher processors limit what machines can run it. Regards, hutch@pbq.com.au
Posted on 2001-04-19 10:55:00 by hutch--
Here we go again :) Steve, The main question for you is: Why you are so afraid of .DATA section grows up while not afraid of .CODE section grows up? :) It's simple arithmetics .dataA = 1 .codeA = 1 .codeB = 3 .codeB > (.dataA + .codeA) You are wrong about big application not good for my style: The bigger application, the more classes it uses THE FASTER AND SHORTER will be app in my design. Cause 1.camulative size of .data and .code section will be less than alone .code in C++ style 2.registration and loading will be faster 'cause WNDCLASSEX member wich can be initialized will be done. Now about classes and modular programming. It's very simple - in C++ style when you put all members in struct in run time all source of class is in .code section exept for names. In classes with WNDCLASSEX you just put in .data the structure .data wcOneClass < here is members,offset OneClassWndProc, ..ect> .code here is rest of ini of wcOneClass invoke RegisterClassEx,addr wcOneClass --------------------------------------------- ---- separate OneClassWndProc proc hWnd,uMsg,wParam,lParam ..... One ClassWndProc endp TwoClassWndProc .. ...endp if each class uses it's own callback. In fact I often use the same one callback with different classes and one class with different callbacks, but it's long story, not basics ... usually I include all Classes callbacks before start point, and register classes after start point. But in dependes. There are lots of types of big progs to talk of uniforms. And simple utility may be written to put and check in dlgbox everything concern to possible values in WNDCLASSEX for specific class so that after it generates this <> filled with choosen values of members. As for the rest I'll answer you in comments. I can only say I don't use either Icz stile to handle msgs or this one. I just optimize Icz style handling in the example that's all. I use some style close to J.Gordon one but not exact one. But it's not the time to talk about it yet. Readable code style is one you get used to. The Svin.
Posted on 2001-04-19 11:43:00 by The Svin
svin somethings wrong with your code. when run the menu item exit doesnt work. since the original generic one does work i thought i should mension this. smurf
Posted on 2001-04-19 18:40:00 by smurf
I've just copied it from this very post. Compiled and cheked in both Win98 and Win NT 4. Menu exit worked. Check again. The Svin.
Posted on 2001-04-19 21:24:00 by The Svin
i tested it again by pasting the code from your post and it doesnt work. i use windows 2000 sp1 and didnt think it would be a windows 2000 specific problem. maybe another win2k user can confirm this. smurf
Posted on 2001-04-20 04:34:00 by smurf
Tell me, please, then: What doesn't work? - 1. MsgBox doesn't appear at all? 2. When you confirm your exit it doesn't exit? The Svin
Posted on 2001-04-20 05:19:00 by The Svin
okies when i click on the exit from the menu the message box doesnt appear. smurf
Posted on 2001-04-20 05:24:00 by smurf
But code that make MsgBox appear is exactly the same as in the original! The difference is how it handles exit after IDYES click. If the oirginal worked in your OS with the MsgBox, this one must work too. If you copied it indeed from the post, something wrong must be in the rsrc.rc, it doesn't send correct menu id. Anyway, to be sure, I'll send you sompiled version of the code. Could you check it for me of your machine? The Svin.
Posted on 2001-04-20 05:54:00 by The Svin
dont waste your time. i figured out the problem. it was my fault sorry for wasting your time. smurf This message was edited by smurf, on 4/20/2001 6:01:29 AM
Posted on 2001-04-20 05:57:00 by smurf