--------------------------------------------------------------------------- ----------------------------------------------------------------------- - A L W A Y S U N D E R C O N S T R U C T I O N - $$$$$$$$ $$$$$$$$ $$$$$$$$$$$$$ $$$$$$$$ $$$$$$$$ $$$$$ $$$$ $$$$$ $$$$ $$$$$ $$$$ $$$ $$$$$ $$$$ $$$$$ $$$$ $$$$$ $$$$ $$$$$ $$$$$ $$$$ $$$ $$$$ $$$$ $$$$$$$$$$ $$$$$$$$ $$$$$ $$$$ $$$ $$$$$$$$ $$$$$$$$ $$$$$ $$$$ $$$$ $$$$$ $$$$ $$$ $$$$ $$$$$ $$$$$ $$$$ $$$$$ $$$$ $$$$$ $$$$ $$$ $$$$$ $$$$ $$$$$ $$$$ $$$$$ $$$$ $$$$$$$$ $$$$$ $$$$ $$$ $$$$$$$$ $$$$$$$$$$ How to program for windows 95 in asm32 Lesson 1 : your first program by _HaK_ and corrected by Nemrod and ReN ----------------------------------------------------------------------- --------------------------------------------------------------------------- 1.Introduction : ---------------- This lesson will try to show you how to do a stupid message box for windows. 2.How we gonna do that ? ------------------------ The main API used here in the prog (see below) is the MessageBoxA. By viewing the API Reference we can see : int MessageBox( HWND hWnd, // handle of owner window LPCTSTR lpText, // address of test in message box LPCTSTR lpCaption, // address of title of message box UINT uType // style of message box ); Before calling the API we have to push every value on the stack with a push instruction. But not in any orders : the last parameter at first, then the third, followed by the second and at last the first parameter. This order is always to be respected : always the last parameter at first, and finish with the first ! All the types here are DWORD so it correspond to LARGE PUSH. The "uType" parameters defines the type of the dialog box. It can have for main value : MB_OK equ 00000000h ; create a simple OK button MB_OKCANCEL equ 00000001h ; two buttons: OK and Cancel MB_ABORTRETRYIGNORE equ 00000002h ; 3 buttons: Abort, Retry and ignore MB_YESNOCANCEL equ 00000003h ; 3 buttons: Yes, No and Cancel MB_YESNO equ 00000004h ; 2 buttons: Yes and No MB_RETRYCANCEL equ 00000005h ; 2 buttons: Retry and Cancel If we want a special icon on the left of the text we must add one of the value : MB_ICONHAND equ 00000010h ; test them to find to MB_ICONQUESTION equ 00000020h ; what they correspond ! MB_ICONEXCLAMATION equ 00000030h MB_ICONASTERISK equ 00000040h And we can select the default button by adding one of the value : MB_DEFBUTTON1 equ 00000000h ; for default button = the first MB_DEFBUTTON2 equ 00000100h ; the second MB_DEFBUTTON3 equ 00000200h ; the third MB_DEFBUTTON4 equ 00000300h ; and the fourth ! Other value (I didn't test them so try them by yourself) : MB_APPLMODAL equ 00000000h MB_SYSTEMMODAL equ 00001000h MB_TASKMODAL equ 00002000h MB_HELP equ 00004000h ; add a Help button (send WM_HELP) MB_RIGHT equ 00080000h MB_RTLREADING equ 00100000h MB_NOFOCUS equ 00008000h MB_SETFOREGROUND equ 00010000h MB_DEFAULT_DESKTOP_ONLY equ 00020000h MB_SERVICE_NOTIFICATION equ 00040000h MB_TYPEMASK equ 0000000Fh MB_USERICON equ 00000080h MB_ICONMASK equ 000000F0h MB_DEFMASK equ 00000F00h MB_MODEMASK equ 00003000h MB_MISCMASK equ 0000C000h Ok after having pushed the uType value, we must push two long pointer : - lpCaption : points to the title of the windows : It's showed in the Caption Bar, which is at the top of the windows. - lpContent : points to the content of the message box. This are two pointer so only push the offset pointing the first character of the string. This string must be null terminated (shows windows where to stop). If you want to display a message on more than one line use : ,13,10 at the End of the line instead of zero which define the end of the message. The 13 character defines the carriage return and the 10 define Line feed ! The last parameter to push is a HWND : a application handle : it's for Windows, it uses it to recognize who is linked to who (personal supposition). So before push this value we have to get it (see below for how to). Now we have pushed all the value on the stack. We can call the Windows API to create the message box with our given parameters. Once called, the message box wait the user to push a button. Meanwhile it doesn't give you back the hand and the execution stop at the call. Once the user choose a button, Windows destroy the message box, gives the value of the pushed button by the user in the eax processor register and the execution of the program continues. The value in eax can be : IDOK = 1 IDCANCEL = 2 IDABORT = 3 IDRETRY = 4 IDIGNORE = 5 IDYES = 6 IDNO = 7 To get the application handle we use the GetModuleHandleA. This API has to get the hwnd of an application. We can push a long pointer, pointing to a string, null terminated and defining the name of the module we wants to get the handle. But if we want the handle Windows assigned to our application, only push the null value and as return in eax, we get the current file hwnd which corresponds to the Application hwnd. I think that when the program starts, Windows gives this application handle, but I don't know where ! Once we have finish, we wants to quit our program. To do this we use the API : ExitProcess. Before calling it we have to push a value : the exit code which is tha same as the int 21h fonction 4Ch exit code. 3.General information. ----------------------- Before being called, any API must be defined in the .asm file as being an external procedure. This is used by the assembler : creates a type of jumptable. And by the linker : fills the table by the correct address defined in the imports32.lib 4.The Main File : .ASM ---------------------- ;--- Start of TUT_01.ASM -->8 .386 locals jumps .model flat,STDCALL ; All APIs have to be defined before being called extrn GetModuleHandleA:Proc extrn MessageBoxA:Proc extrn ExitProcess:Proc ; here we store the data ! .data AppHWnd dd 0 ; here we store the application Handle ! MsgBoxCaption db "Lesson 1",0 ; The message box title (or caption) MsgBoxContent db "Just saying Hello,",13,10 ; The message box content db "To Yourself !!!",0 ; here starts the code .code Start: push 0h ; 0 = current application call GetModuleHandleA ; give us the handle ! mov [AppHWnd],eax ; and store it. push 20h ; type of the message box ; (MB_ICONQUESTION and MB_OK) push offset MsgBoxCaption ; msgbox title push offset MsgBoxContent ; msgbox content push [AppHWnd] ; Application handle call MessageBoxA ; display the message box push 0h ; no return code call ExitProcess ; exit all process End Start ; end of the code. ;8<- EOF TUT_01.ASM --- 5.The definitions file : .DEF ----------------------------- ;--- Start of TUT_01.DEF -->8 NAME TUT_01 DESCRIPTION 'ASM program' EXETYPE WINDOWS CODE PRELOAD MOVEABLE DATA PRELOAD MOVEABLE MULTIPLE ;8<- EOF TUT_01.DEF --- 6.The makefile file : --------------------- ;--- Start of MakeFile -->8 # make -B Will build .EXE # make -B -DDEBUG Will build the debug version. NAME = TUT_01 OBJS = $(NAME).obj DEF = $(NAME).def !if $d(DEBUG) TASMDEBUG=/zi LINKDEBUG=/v !else TASMDEBUG= LINKDEBUG= !endif !if $d(MAKEDIR) IMPORT=$(MAKEDIR)\..\lib\import32 !else IMPORT=import32 !endif $(NAME).EXE: $(OBJS) $(DEF) tlink32 /Tpe /aa /c $(LINKDEBUG) $(OBJS),$(NAME),, $(IMPORT), $(DEF) .asm.obj: tasm32 $(TASMDEBUG) /ml /m2 $&.asm ;8<- EOF MakeFile --- 7.How to assemble. ------------------ To make the TUT_01.EXE Just create TUT_01.ASM, TUT_01.DEF and the MAKEFILE with the above data. Put the tasm\bin directory in your path. And just type : MAKE 8.The Greetz : -------------- _Masta_ : when does your next lesson come out ? Nemrod : your punishment continues !! :) ReN : Which university ? To contact myself : try the sunday afternoon on #Win32asm on EFNET. Next lesson : your first Window !