---------------------------------------------------------------------------
-----------------------------------------------------------------------
- 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 !