You are on page 1of 11

td_win32asm_115.

asm
;==============================================================================
;
Test Department's WINDOWS 32 BIT x86 ASSEMBLY example
115
;==============================================================================
;==============================================================================
; ==> Part 115 : A 360 degree bitmap animation using the FPU and the Keyboard
;-----------------------------------------------------------------------------; Willkommen an Bord,
; in the Window Proc (WP1) reacting to a WM_CREATE message I setup a STATIC
; window with an associated bitmap, than I create a region (the bitmap region)
; and assign it to the STATIC window.
; Next I setup a high resolution timer, it runs in its own thread.
; In TP1 (Timer Proc 1) I read the keyboard port and examine if the left or
; right arrow key is pressed.
; Here I also calculate the new screen coordinates, using the FPU.
;
; If you wonna play with this source you can increase "multi" for the speed,
; also, in TP1, you could increase "degree" more than 1,
; another way is to change the timer event time in WP1 on WM_CREATE.
; Try another bitmap (68x68 Pixel / 256 Colors) or other hotkey's (MAKECODE).
; If you use a Pen or a Brush you can draw a circle or a part of it ...
; Please read the complete source code ...
; If you have trouble with this proggi, please give me a note and email me !
;
; Test Department
td@crahkob.com
;==============================================================================
; Assembler directives
;-----------------------------------------------------------------------------.386
; specifies the processor our program want run on
.Model Flat ,StdCall
; Flat for Win9x (32 Bit), Calling Convention
option casemap:none
; case sensitive !
;==============================================================================
; Include all files where API functins resist you want use, set correct path
;-----------------------------------------------------------------------------include D:\Masm32\include\windows.inc
includelib kernel32.lib
includelib user32.lib
includelib gdi32.lib
includelib winmm.lib
;==============================================================================
; Declaration of used API functions,take a look into WIN32.HLP and *.inc files
;-----------------------------------------------------------------------------GetModuleHandleA
PROTO :DWORD
LoadIconA
PROTO :DWORD,:DWORD
CreateSolidBrush
PROTO :DWORD
LoadCursorA
PROTO :DWORD,:DWORD
RegisterClassExA
PROTO :DWORD
CreateWindowExA
PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,
:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
ShowWindow
PROTO :DWORD,:DWORD
Page 1

UpdateWindow
GetMessageA
TranslateMessage
DispatchMessageA
PostQuitMessage
DefWindowProcA
ExitProcess
MoveWindow
DeleteObject
DestroyWindow
MessageBoxA
CreateEllipticRgn
SetWindowRgn
timeGetDevCaps
timeSetEvent
timeKillEvent
GetAsyncKeyState

PROTO
PROTO
PROTO
PROTO
PROTO
PROTO
PROTO
PROTO
PROTO
PROTO
PROTO
PROTO
PROTO
PROTO
PROTO
PROTO
PROTO

td_win32asm_115.asm
:DWORD
:DWORD,:DWORD,:DWORD,:DWORD
:DWORD
:DWORD
:DWORD
:DWORD,:DWORD,:DWORD,:DWORD
:DWORD
:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
:DWORD
:DWORD
:DWORD,:DWORD,:DWORD,:DWORD
:DWORD,:DWORD,:DWORD,:DWORD
:DWORD,:DWORD,:DWORD
:DWORD,:DWORD
:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
:DWORD
:DWORD

;==============================================================================
; .const
= the constants area starts here,constants are defined and fixed
;-----------------------------------------------------------------------------.const
; - Parameter MAIN WINDOW CallBack Procedure ( API=RegisterClassExA ) WP1_CallBack
equ [ebp+4]
;return address
WP1_hWnd
equ [ebp+8]
;handle of window who receives message
WP1_uMsg
equ [ebp+12]
;the message number
WP1_wParam
equ [ebp+16]
;extra info about the message
WP1_lParam
equ [ebp+20]
;extra info about the message
;==============================================================================
; .Data
= the data area starts here, datas are defined but not fixed
;
MASM converts real4, real8, real10 values into FPU/IEEE standard.
;-----------------------------------------------------------------------------.Data
IconName
db "TDIcon",0
;icon name in rc file
Class
db "TDWinClass",0
;name of window class
WindowName
db "Test Department - http://surf.to/TestD",0;
STATIC_Name
db "Picture",0
;name of bitmap in rc file
STATIC_Class
db "STATIC",0
;predefined window class
MB1_Titel
db "Program Info",0
;message box titel
MB1_Text
db "Left and Right Arrow Keys moves the world",0
;
STATIC_xPos
STATIC_yPos

dd 352
dd 192

;starting x Position of window


;starting y Position of window

degree

dd 90

;starting degrees

temp_xPos
temp_yPos
rad_div
multi

real8
real8
real8
real8

352.000000000
192.000000000
57.2957795130
-1.0000000000

;temp result,
;temp result,
;convert grad
;speed, value

starting x Pos.
starting y Pos.
to rad
must be negative

;==============================================================================
Page 2

td_win32asm_115.asm
; .Data?
= the data? area starts here, not defined and not fixed
;-----------------------------------------------------------------------------.data?
handleWindow
dd ?
;handle main window
handleSTATIC1
dd ?
;handle static window
timerevent1
dd ?
;handle timer
handleRegion1
dd ?
;handle region
align 4
; - WndClassEx Structure ( API=RegisterClassExA ) cbSize
dd ?
;size in bytes of this structure
style
dd ?
;window style
lpfnWndProc
dd ?
;address of user proc function
cbclsExtra
dd ?
;extra bytes to allocate set to 0
cbWndExtra
dd ?
;extra bytes class directive, rc file
hInstance
dd ?
;program handle(API=GetModuleHandleA)
hIcon
dd ?
;handle of icon (API=LoadIconA)
hcursor
dd ?
;handle of cursor (API=LoadCursor)
hbrBackground
dd ?
;background color, 0=transparent
lpszMenuName
dd ?
;name of menu class in resource file
lpszClassName
dd ?
;name of windows this window class
hIconSm
dd ?
;iconhandle 0=search in resource file
hdcDest
dd ?
;handle of dest. device context
align 4
; - Msg Structure ( API=GetMessageA ) - member POINT = POINT structure
hWnd
dd ?
;handle of window who receives message
message
dd ?
;the message number
wParam
dd ?
;extra info about the message
lParam
dd ?
;extra info about the message
time
dd ?
;time the message was posted
xpt
dd ?
;cursor x-position, POINT struc
ypt
dd ?
;cursor x-position, POINT struc
align 4
; - TIMECAPS Structure ( API=timeGetDevCaps ) wPeriodMin
dd ?
;TIMER minimum supported resolution
wPeriodMax
dd ?
;TIMER maximum supported resolution
;==============================================================================
; .CODE
= our code area starts here
Main = label of our program code
;-----------------------------------------------------------------------------.Code
Main:
;==============================================================================
; Always get your program ID first (API=GetModuleHandleA)
;-----------------------------------------------------------------------------push
0h
;lpModuleHandle, 0=get program handle
call
GetModuleHandleA
;- API Function mov
hInstance,eax
;return value in eax=handle of program
;==============================================================================
Page 3

td_win32asm_115.asm
; Init the Floating Point Unit
;-----------------------------------------------------------------------------finit
;init FPU
;==============================================================================
; The API function "RegisterClassExA" registers a window class.
; This API needs a "WNDCLASSEX" structure so we fill it with correct values.
;-----------------------------------------------------------------------------mov
cbSize,30h
;size in bytes of WNDCLASSEX structure
mov
style,3h
;window style
mov
lpfnWndProc,OFFSET WP1
;address of user lpfnWndProc function
mov
cbclsExtra,0h
;extra bytes to allocate set to 0
mov
cbWndExtra,0h
;class directive in rc file
mov
lpszMenuName,0h
;menu name in resource file,0=no menu
mov
lpszClassName,OFFSET Class ;name of windows class
mov
hIconSm,0h
;iconhandle 0=search in rc file
;-----------------------------------------------------------------------------; API "CreateSolidBrush" creates a logical brush with the specified solid color
;-----------------------------------------------------------------------------push
00000000h
;crColor, brush color value RGB
call
CreateSolidBrush
;- API Function mov
hbrBackground,eax
;background color
;-----------------------------------------------------------------------------; API "LoadIconA" loads an icon defined in the resource file and stores the
; handle in the "WNDCLASSEX" structure
;-----------------------------------------------------------------------------push
OFFSET IconName
;icon-string or icon resource id
push
hInstance
;our program handle
call
LoadIconA
;- API Function mov
hIcon,eax
;store handle of newly loaded icon
;-----------------------------------------------------------------------------; API "LoadCursorA" loads a default system cursor, in this case we must set
; hInstance to 0 and lpCursorName to a default system cursor value, here 32512
; Then we store the cursor handle in the "WNDCLASSEX" structure
;-----------------------------------------------------------------------------push
32512
;lpCursorName, default value in dezimal
push
0h
;hInstance, 0=default system cursor
call
LoadCursorA
;- API Function mov
hcursor,eax
;store handle of the cursor
;-----------------------------------------------------------------------------; Now, after filled the "WNDCLASSEX" structure we call API "RegisterClassEx"
;-----------------------------------------------------------------------------push
OFFSET cbSize
;pointer to WNDCLASSEX structure
call
RegisterClassExA
;- API Function ;==============================================================================
; API "CreateWindowExA" creates an overlapped, pop-up, or child window with an
; extended style. The return value in EAX is the handle of the new window.
; This API sends a WM_CREATE message to the window procedure (WP1).
;-----------------------------------------------------------------------------push
0h
;lpParam, extra pointer data 0=no data
push
hInstance
;hInstance, handle of our program
push
0h
;hMenu, handle window menu 0=class menu
Page 4

push
push
push
push
push
push
push
push
push
call
mov

0h
00000200h
00000300h
20h
10h
04CA0000h
OFFSET WindowName
OFFSET Class
0300h
CreateWindowExA
hWnd,eax

td_win32asm_115.asm
;hWndParent, handle parent window 0=no
;intnHeight, window height pixel
;intnWidth, window width pixel
;inty, vertical position window
;intx, horizontal position window
;dwStyle, look into WIN32.HLP
;lpWindowName, pointer to window name
;lpClassName, pointer to class name
;dwExStyle, extra window style 0=no
;- API Function ;hwnd,return value=handle of window

;==============================================================================
; API "ShowWindow" function sets the specified window's show state.
;-----------------------------------------------------------------------------push
1h
;nCmdShow, show state 1=SW_SHOWNORMAL
push
hWnd
;hwnd, handle of window
call
ShowWindow
;- API Function ;==============================================================================
; API "UpdateWindow" updates the area of the specified window by sending a
; WM_PAINT message to the window if the window's update region is not empty.
;-----------------------------------------------------------------------------push
hWnd
;hwnd, handle of window
call
UpdateWindow
;- API Function ;==============================================================================
; API "MessageBoxA" creates a message box, we can only click OK
;-----------------------------------------------------------------------------push
0h
;uType, style, 0=MB_OK Button
push
OFFSET MB1_Titel
;lpCaption,pointer to title text
push
OFFSET MB1_Text
;lpText,pointer to text message box
push
hWnd
;handle of owner window 0=no owner
call
MessageBoxA
;- API Function LoopGetMessage:
;==============================================================================
; API "GetMessageA" retrieves a message + places it in the specified structure.
;-----------------------------------------------------------------------------push
0h
;wMsgFilterMax, highest message value
push
0h
;wMsgFilterMin, lowest message value
push
0h
;hWnd, handle of window who gets msg.
push
OFFSET hWnd
;lpMsg, pointer to MSG structure
call
GetMessageA
;- API Function cmp
eax,0h
;check if return value=0 (exit)
je
ExitPrg
;if return value is 0 goto LABEL
;==============================================================================
; API "TranslateMessage" translates virtual-key messages in character messages
;-----------------------------------------------------------------------------push
OFFSET hWnd
;lpMSG, pointer to msg structure
call
TranslateMessage
;- API Function - keyboard code
Page 5

td_win32asm_115.asm
;==============================================================================
; API "DispatchMessageA" function dispatches a message to a window procedure.
;-----------------------------------------------------------------------------push
OFFSET hWnd
;lpMSG, pointer to msg structure
call
DispatchMessageA
;- API Function jmp
LoopGetMessage
;check for message again, goto LABEL
ExitPrg:
;==============================================================================
; Next we terminate our program (API=ExitProcess)
;-----------------------------------------------------------------------------push
hInstance
;push our programm handle to exit
call
ExitProcess
;- API Function ;##############################################################################
; The Window Procedure (API=RegisterClassExA) for this registered window.
;-----------------------------------------------------------------------------WP1:
push
ebp
;create stack frame
mov
ebp,esp
;
pushad
;push all register to the stack
mov
eax,WP1_uMsg
;move the message number to eax
;==============================================================================
; WM_CREATE (value=01h) message received ?
;-----------------------------------------------------------------------------WP1_uMsg_01h:
cmp
eax,1h
;check if WM_CREATE message recieved
jne
WP1_uMsg_02h
;if not goto LABEL
mov
eax,WP1_hWnd
;store handle main window
mov
handleWindow,eax
;
;-----------------------------------------------------------------------------; API "CreateWindowExA" creates a window with a predefined class name (STATIC).
; The return value in EAX is the handle of the new window.
;-----------------------------------------------------------------------------push
0h
;lpParam, extra pointer data 0=no data
push
hInstance
;hInstance, handle of our program
push
700h
;hMenu, the child-window ID
push
WP1_hWnd
;hWndParent, handle parent window 0=no
push
44h
;intnHeight, window height pixel
push
44h
;intnWidth, window width pixel
push
STATIC_yPos
;inty, vertical position window
push
STATIC_xPos
;intx, horizontal position window
push
5400000Eh
;dwStyle, static window style
;WS_CHILD
= 40000000h
;WS_VISIBLE
= 10000000h
;WS_CLIBSIBLINGS
= 4000000h
;SS_BITMAP
=
0Eh
push
OFFSET STATIC_Name
;lpWindowName, pointer to window name
push
OFFSET STATIC_Class
;lpClassName, pointer to class name
push
0h
;dwExStyle,look WIN32.HLP + windows.inc
call
CreateWindowExA
;- API Function mov
handleSTATIC1,eax
;hwnd, return value=handle of window
Page 6

td_win32asm_115.asm
;-----------------------------------------------------------------------------; API "CreateEllipticRgn" creates an elliptical region.
;-----------------------------------------------------------------------------push
42h
;y-coordinate of the lower-right corner
push
42h
;x-coordinate of the lower-right corner
push
2h
;y-coordinate of the upper-left corner
push
2h
;x-coordinate of the upper-left corner
call
CreateEllipticRgn
;- API Function mov
handleRegion1,eax
;return value=handle of region
;-----------------------------------------------------------------------------; API "SetWindowRgn" assigns the region defined above to a window.
;-----------------------------------------------------------------------------push
1h
;bRedraw, window redraw flag
push
handleRegion1
;hRgn, handle to region
push
handleSTATIC1
;hWnd, handle of window
call
SetWindowRgn
;- API Function ;-----------------------------------------------------------------------------; API "timeGetDevCaps" queries the timer device to determine its resolution.
; Returned values in the TIMECAPS struc are different from system to system.
;-----------------------------------------------------------------------------push
8h
;cbtc, size in bytes TIMECAPS structure
push
OFFSET wPeriodMin
;ptc, address of a TIMECAPS structure
call
timeGetDevCaps
;- API Function ;-----------------------------------------------------------------------------; The timeSetEvent function starts a PRECISION timer event. After activated, it
; calls the specified callback function. It runs in its own thread !
;-----------------------------------------------------------------------------push
1h
;fuEvent, timer type, TIME_PERIODIC=1h
push
0h
;dwUser, user-supplied callback data
push
OFFSET TP1
;lpTimeProc, address callback function
push
wPeriodMin
;uResolution, resolution in ms
push
10
;uDelay, event delay in milliseconds
call
timeSetEvent
;- API Function mov
timerevent1,eax
;store handle
jmp
WP1_return
;
;==============================================================================
; WM_DESTROY (value=02h) message received ?
;-----------------------------------------------------------------------------WP1_uMsg_02h:
cmp
eax,2h
;check if value=2h (WM_DESTROY)
jne
WP1_uMsg_112h
;if not 2h go to LABEL
call
My_CleanSystem
;- SubRoutine ;-----------------------------------------------------------------------------; API "PostQuitMessage" indicates to Windows a request to terminate
;-----------------------------------------------------------------------------push
0h
;nExitCode, exit code=wParam
call
PostQuitMessage
;- API Function popad
;pop all register back from stack
xor
eax,eax
;set eax to 0 to exit our program
mov
esp,ebp
;delete stack frame
pop
ebp
;
ret
10h
;return and clear stack
Page 7

td_win32asm_115.asm
;==============================================================================
; WM_SYSCOMMAND (value=112h) message recieved ?
;-----------------------------------------------------------------------------WP1_uMsg_112h:
cmp
eax,112h
;check if WM_COMMAND message recieved
jne
WP1_return
;if not goto label
mov
eax,WP1_wParam
;extra info about the message
cmp
eax,0F060h
;SC_CLOSE=0F060h received ?
jne
WP1_return
;
call
My_CleanSystem
;- SubRoutine jmp
WP1_return
;==============================================================================
; API "DefWindowProcA" calls the window procedure to provide default processing
; for any window messages that an application does not process.
; This function ensures that every message is processed.
; It is called with the same parameters received by the window procedure.
;-----------------------------------------------------------------------------WP1_return:
popad
;pop all register from stack
push
WP1_lParam
;extra info about the message
push
WP1_wParam
;extra info about the message
push
WP1_uMsg
;the message number
push
WP1_hWnd
;handle of window who receives message
call
DefWindowProcA
;- API Function mov
esp,ebp
;delete stack frame
pop
ebp
;
ret
10h
;return and clear stack
;##############################################################################
;##############################################################################
; HIGH RESOLUTION TIMER procedure (Mmedia.hlp) !
;-----------------------------------------------------------------------------TP1:
push
ebp
;create stack frame
mov
ebp,esp
;
pushad
;push all register to the stack
;-----------------------------------------------------------------------------; API "GetAsyncKeyState" determines whether a key is up or down at the time the
; function is called ...
;-----------------------------------------------------------------------------push
27h
;vKey, virtual-key code, VK_RIGHT=27h
call
GetAsyncKeyState
;- API Function shr
eax,1Fh
cmp
eax,1h
je
RightArrow
;-----------------------------------------------------------------------------; API "GetAsyncKeyState" determines whether a key is up or down at the time the
; function is called ...
;-----------------------------------------------------------------------------push
25h
;vKey, virtual-key code, VK_LEFT=25h
call
GetAsyncKeyState
;- API Function Page 8

td_win32asm_115.asm
shr
cmp
jne

eax,1Fh
eax,1h
Check_Pos

LeftArrow:
inc
degree
cmp
degree,360
jbe
Check_Pos
mov
degree,1
jmp
Check_Pos
RightArrow:
dec
degree
cmp
degree,1
jae
Check_Pos
mov
degree,360
Check_Pos:
;-----------------------------------------------------------------------------; Check the min and max position
;-----------------------------------------------------------------------------Test_xPos_Max:
cmp
STATIC_xPos,2A0h
jb
Test_xPos_Min
mov
degree,90
jmp
Calculate
Test_xPos_Min:
cmp
STATIC_xPos,10h
ja
Test_yPos_Max
mov
degree,270
jmp
Calculate
Test_yPos_Max:
cmp
STATIC_yPos,190h
jb
Test_yPos_Min
mov
degree,360
jmp
Calculate
Test_yPos_Min:
cmp
STATIC_yPos,10h
ja
Calculate
mov
degree,180
Calculate:
;-----------------------------------------------------------------------------; Calculate the new x and y position using the FPU.
; This is one of the interested parts in this x86win32asm example.
; Please imagine : We are in the center (oldPos x,y) and a circle is around us.
;
Now, for example, we want walk to direction 30 degree ...
;
Degree points to a newPos (x,y) on the circle around us.
;
newyPos = oldyPos+multi(fsin(degree/57.2957795130))
;
newxPos = oldxPos+multi(fcos(degree/57.2957795130))
; Oh yeah, that's mathe ..., natural I hate it, but today I love it.
; This routine do all the work, even if the sin and/or cos is negativ.
;-----------------------------------------------------------------------------ffree
ST(7)
;declare ST(7) as empty, not required
Page 9

td_win32asm_115.asm
fild
degree
;load integer degree into TOS
fdiv
rad_div
;convert grad to rad, real8, /~ 57.3
fsincos
;calculate sinus (TOS) and cosinus ST(1)
fmul
multi
;multiply (real8 value), increases speed
fadd
temp_yPos
;add old yPos (real8 value)
fst
temp_yPos
;store new yPos (real8 value)
fistp
STATIC_yPos
;store result in y position (integer) + POP
fmul
multi
;multiply (real8 value), increases speed
fadd
temp_xPos
;add old xPos (real8 value)
fst
temp_xPos
;store new xPos (real8 value)
fistp
STATIC_xPos
;store result in x position (integer) + POP
;-----------------------------------------------------------------------------; API "MoveWindow" changes the position and dimensions of the STATIC window.
; Remember that I assign a region to the STATIC window handle on WM_CREATE.
;-----------------------------------------------------------------------------push
01h
;bRepaint, repaint flag
push
44h
;nHeight, height
push
44h
;nWidth, width
push
STATIC_yPos
;Y, vertical position
push
STATIC_xPos
;X, horizontal position
push
handleSTATIC1
;hWnd, handle of window
call
MoveWindow
;- API Function ;-----------------------------------------------------------------------------; API "UpdateWindow" updates the area of the specified window by sending a
; WM_PAINT message to the window if the window's update region is not empty.
;-----------------------------------------------------------------------------push
handleSTATIC1
;hwnd, handle of window
call
UpdateWindow
;- API Function TP1_return:
popad
;pop all register back from stack
mov
esp,ebp
;delete stack frame
pop
ebp
;
ret
14h
;return and clear stack (14h !!!)
;##############################################################################
;******************************************************************************
; My own subroutine(s) for a compacter code resist here ...
;-----------------------------------------------------------------------------My_CleanSystem:
;-----------------------------------------------------------------------------; The timeKillEvent function cancels a specified high precision timer event.
;-----------------------------------------------------------------------------push
timerevent1
;uTimerID, ID of timer event to cancel
call
timeKillEvent
;- API Function ;-----------------------------------------------------------------------------; API "DeleteObject" deletes a logical pen, brush, font, bitmap, region, or
; palette, freeing all system resources associated with the object.
; After the object is deleted, the specified handle is no longer valid.
;-----------------------------------------------------------------------------push
handleRegion1
;hObject, handle of graphic object
call
DeleteObject
;- API Function ret
Page 10

td_win32asm_115.asm
;******************************************************************************
;==============================================================================
; end Main
= end of our program code
;-----------------------------------------------------------------------------end Main
;end of our program code, entry point
;==============================================================================
; To create the exe file use this commands with your Microsoft Assembler/Linker
;-----------------------------------------------------------------------------; ml.exe /c /coff td_win32asm_115.asm
;asm command
; rc.exe /v rsrc.rc
;rc command
; cvtres.exe /machine:ix86 rsrc.res
; link.exe /subsystem:windows td_win32asm_115.obj rsrc.obj
;link command
;==============================================================================

Page 11

You might also like