masmflip.zip
This is the masm version of Mike Bibby's original example of how to
use Direct Draw. It has been slightly modified with the author's permission
so that it will build in the MASM32 environment. Mike has supplied the
necessary include files for the Direct Draw interface.
dc-ddraw.zip
This is a Direct Draw plasma demo by Ewald Snel & Gatt. It requires
a 32 bit colour monitor to run it but it displays some very clever programming
techniques drawn from C programming. The include file by Ewald Snel is
particularly good and Gatt has written a small text tutorial to explain
how it works. It has been slightly modified with the authors permission
so it will build from the MASM32 environment.
push par4
push par3
push par2
push par1
call FunctionName
mov retval, eax
With the MASM "invoke" syntax, you code as follows,
invoke FunctionName,par1,
par2, par3, par4
mov retval, eax
Apart from much clearer coding, there is another important advantage in that the "invoke" syntax is type checked against function prototypes so that parameter number and size errors are caught at assembly time.
MASM uses the notation for addresses in the invoke syntax of ADDR. This will resolve to an address in the correct form at assembly time. To call a function that uses a zero terminated string as a parameter, you use,
invoke FunctionName,ADDR szString
MASM32 also uses a high level simulation of branching code in the WndProc of its example code that is very similar to a standard C switch block.
.if par1 == num
code
code
.elseif par2 == num
code
code
.else
code
code
.endif
Combined with the invoke syntax, this allows for very clear coding of
otherwise unreadable and error prone WndProc and similar functions. Code
written in this way has a similar "feel" to writing in a compiler using
inline assembler but the difference is that with pure assembler, there
are no problematic runtime libraries and the size and speed when written
correctly is beyond the capacity of compilers.
Below is the source code for a basic window with an icon and menu supplied
with MASM32. It assembles at 5120 bytes.
This should be enough to convince the programmer who still works in other
languages that modern assembler has many advantages over the compilers
that they are using in terms of both speed and size. Examine the code and
it has much of the familiarity of writing C but without the problems associated
with using the often very uneven C runtime libraries.
; #########################################################################
.386
.model flat, stdcall
option casemap :none
; case sensitive
; #########################################################################
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
; #########################################################################
;=============
; Local macros
;=============
szText MACRO Name, Text:VARARG
LOCAL lbl
jmp lbl
Name db Text,0
lbl:
ENDM
m2m MACRO M1, M2
push M2
pop M1
ENDM
return MACRO arg
mov eax, arg
ret
ENDM
;=================
; Local prototypes
;=================
WinMain PROTO :DWORD,:DWORD,:DWORD,:DWORD
WndProc PROTO :DWORD,:DWORD,:DWORD,:DWORD
TopXY PROTO
:DWORD,:DWORD
.data
szDisplayName db
"Template",0
CommandLine
dd 0
hWnd
dd 0
hInstance
dd 0
.code
start:
invoke GetModuleHandle,
NULL
mov hInstance, eax
invoke GetCommandLine
mov CommandLine,
eax
invoke WinMain,hInstance,NULL,CommandLine,SW_SHOWDEFAULT
invoke ExitProcess,eax
; #########################################################################
WinMain proc hInst :DWORD,
hPrevInst :DWORD,
CmdLine :DWORD,
CmdShow :DWORD
;====================
; Put LOCALs on stack
;====================
LOCAL wc
:WNDCLASSEX
LOCAL msg :MSG
LOCAL Wwd :DWORD
LOCAL Wht :DWORD
LOCAL Wtx :DWORD
LOCAL Wty :DWORD
;==================================================
; Fill WNDCLASSEX
structure with required variables
;==================================================
mov wc.cbSize,
sizeof WNDCLASSEX
mov wc.style,
CS_HREDRAW or CS_VREDRAW \
or CS_BYTEALIGNWINDOW
mov wc.lpfnWndProc,
offset WndProc
mov wc.cbClsExtra,
NULL
mov wc.cbWndExtra,
NULL
m2m wc.hInstance,
hInst
mov wc.hbrBackground,
COLOR_BTNFACE+1
mov wc.lpszMenuName,
NULL
mov wc.lpszClassName,
offset szClassName
invoke
LoadIcon,hInst,500 ; icon ID
mov wc.hIcon,
eax
invoke
LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,
eax
mov wc.hIconSm,
0
invoke RegisterClassEx, ADDR wc
;================================
; Centre window at
following size
;================================
mov Wwd, 500
mov Wht, 350
invoke GetSystemMetrics,SM_CXSCREEN
invoke TopXY,Wwd,eax
mov Wtx, eax
invoke GetSystemMetrics,SM_CYSCREEN
invoke TopXY,Wht,eax
mov Wty, eax
szText szClassName,"Template_Class"
invoke CreateWindowEx,WS_EX_OVERLAPPEDWINDOW,
ADDR szClassName,
ADDR szDisplayName,
WS_OVERLAPPEDWINDOW,
Wtx,Wty,Wwd,Wht,
NULL,NULL,
hInst,NULL
mov hWnd,eax
invoke LoadMenu,hInst,600
; menu ID
invoke SetMenu,hWnd,eax
invoke ShowWindow,hWnd,SW_SHOWNORMAL
invoke UpdateWindow,hWnd
;===================================
; Loop until PostQuitMessage
is sent
;===================================
StartLoop:
invoke GetMessage,ADDR msg,NULL,0,0
cmp eax, 0
je ExitLoop
invoke TranslateMessage, ADDR
msg
invoke DispatchMessage,
ADDR msg
jmp StartLoop
ExitLoop:
return msg.wParam
WinMain endp
; #########################################################################
WndProc proc hWin :DWORD,
uMsg :DWORD,
wParam :DWORD,
lParam :DWORD
.if uMsg == WM_COMMAND
;======== menu commands ========
.if wParam == 1000
invoke SendMessage,hWin,WM_SYSCOMMAND,SC_CLOSE,NULL
.elseif wParam ==
1900
szText TheMsg,"Assembler, Pure & Simple"
invoke MessageBox,hWin,ADDR TheMsg,ADDR szDisplayName,MB_OK
.endif
;====== end menu commands ======
.elseif uMsg == WM_CLOSE
szText TheText,"Please
Confirm Exit"
invoke MessageBox,hWin,ADDR
TheText,ADDR szDisplayName,MB_YESNO
.if eax
== IDNO
return 0
.endif
.elseif uMsg == WM_DESTROY
invoke PostQuitMessage,NULL
return 0
.endif
invoke DefWindowProc,hWin,uMsg,wParam,lParam
ret
WndProc endp
; ########################################################################
TopXY proc wDim:DWORD, sDim:DWORD
shr sDim, 1
; divide screen dimension by 2
shr wDim, 1
; divide window dimension by 2
mov eax, wDim ; copy window
dimension into eax
sub sDim, eax ; sub half
win dimension from half screen dimension
return sDim
TopXY endp
; ########################################################################
end start