📄 lion-tutorial03.htm
字号:
<html>
<head>
<link rel="stylesheet" href="../../asm.css">
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>Iczelion's win32 asm tutorial</title>
</head>
<body bgcolor="#FFFFFF" background="../../images/back01.jpg">
<p align="center">Tutorial 3: A Simple Window</p>
<hr size="1">
In this tutorial, we will build a Windows program that displays a fully functional
window on the desktop. <br>
Download the example file <a href="files/tut03.zip">here</a>
<h3> Theory:</h3>
Windows programs rely heavily on API functions for their GUI. This approach benefits
both users and programmers. For users, they don't have to learn how to navigate
the GUI of each new programs, the GUI of Windows programs are alike. For programmers,
the GUI codes are already there,tested, and ready for use. The downside for programmers
is the increased complexity involved. In order to create or manipulate any GUI
objects such as windows, menu or icons, programmers must follow a strict recipe.
But that can be overcome by modular programming or OOP paradigm. <br>
I'll outline the steps required to create a window on the desktop below:
<ol>
<li> Get the instance handle of your program (required)</li>
<li> Get the command line (not required unless your program wants to process
a command line)</li>
<li> Register window class (required ,unless you use predefined window types,
eg. MessageBox or a dialog box)</li>
<li> Create the window (required)</li>
<li> Show the window on the desktop (required unless you don't want to show
the window immediately)</li>
<li> Refresh the client area of the window</li>
<li> Enter an infinite loop, checking for messages from Windows</li>
<li> If messages arrive, they are processed by a specialized function that is
responsible for the window</li>
<li> Quit program if the user closes the window</li>
</ol>
As you can see, the structure of a Windows program is rather complex compared
to a DOS program. But the world of Windows is drastically different from the world
of DOS. Windows programs must be able to coexist peacefully with each other. They
must follow stricter rules. You, as a programmer, must also be more strict with
your programming style and habit.
<h3> Content:</h3>
Below is the source code of our simple window program. Before jumping into the
gory details of Win32 ASM programming, I'll point out some fine points which will
ease your programming.
<ul>
<li> You should put all Windows constants, structures and function prototypes
in an include file and include it at the beginning of your .asm file. It'll
save you a lot of effort and typo. Currently, the most complete include file
for MASM is hutch's windows.inc which you can download from his page or my
page. You can also define your own constants & structure definitions but
you should put them into a separate include file.</li>
<li> Use includelib directive to specify the import library used in your program.
For example, if your program calls MessageBox, you should put the line:</li>
<ul>
includelib user32.lib
</ul>
at the beginning of your .asm file. This directive tells MASM that your program
will make uses of functions in that import library. If your program calls functions
in more than one library, just add an includelib for each library you use. Using
IncludeLib directive, you don't have to worry about import libraries at link
time. You can use /LIBPATH linker switch to tell Link where all the libs are.
<li> When declaring API function prototypes, structures, or constants in your
include file, try to stick to the original names used in Windows include files,
including case. This will save you a lot of headache when looking up some
item in Win32 API reference.</li>
<li> Use makefile to automate your assembling process. This will save you a
lot of typing.</li>
</ul>
<b>.386</b> <br>
<b>.model flat,stdcall</b> <br>
<b>option casemap:none</b> <br>
<b>include \masm32\include\windows.inc</b> <br>
<b>include \masm32\include\user32.inc</b> <br>
<b>includelib \masm32\lib\user32.lib
; calls to functions in user32.lib and kernel32.lib</b> <br>
<b>include \masm32\include\kernel32.inc</b> <br>
<b>includelib \masm32\lib\kernel32.lib</b>
<p><b>WinMain proto :DWORD,:DWORD,:DWORD,:DWORD</b>
<p><b>.DATA
; initialized data</b> <br>
<b>ClassName db "SimpleWinClass",0
; the name of our window class</b> <br>
<b>AppName db "Our First Window",0
; the name of our window</b>
<p><b>.DATA?
; Uninitialized data</b> <br>
<b>hInstance HINSTANCE ? ; Instance
handle of our program</b> <br>
<b>CommandLine LPSTR ?</b> <br>
<b>.CODE
; Here begins our code</b> <br>
<b>start:</b> <br>
<b>invoke GetModuleHandle, NULL
; get the instance handle of our program.</b> <br>
<b>
; Under Win32, hmodule==hinstance mov hInstance,eax</b> <br>
<b>mov hInstance,eax</b> <br>
<b>invoke GetCommandLine
; get the command line. You don't have to call this function IF</b> <br>
<b>
; your program doesn't process the command line.</b> <br>
<b>mov CommandLine,eax</b> <br>
<b>invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
; call the main function</b> <br>
<b>invoke ExitProcess, eax
; quit our program. The exit code is returned in eax from WinMain.</b>
<p><b>WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD</b>
<br>
<b> LOCAL wc:WNDCLASSEX
; create local variables on stack</b> <br>
<b> LOCAL msg:MSG</b> <br>
<b> LOCAL hwnd:HWND</b>
<p><b> mov wc.cbSize,SIZEOF WNDCLASSEX
; fill values in members of wc</b> <br>
<b> mov wc.style, CS_HREDRAW or CS_VREDRAW</b>
<br>
<b> mov wc.lpfnWndProc, OFFSET WndProc</b> <br>
<b> mov wc.cbClsExtra,NULL</b> <br>
<b> mov wc.cbWndExtra,NULL</b> <br>
<b> push hInstance</b> <br>
<b> pop wc.hInstance</b> <br>
<b> mov wc.hbrBackground,COLOR_WINDOW+1</b> <br>
<b> mov wc.lpszMenuName,NULL</b> <br>
<b> mov wc.lpszClassName,OFFSET ClassName</b>
<br>
<b> invoke LoadIcon,NULL,IDI_APPLICATION</b> <br>
<b> mov wc.hIcon,eax</b> <br>
<b> mov wc.hIconSm,eax</b> <br>
<b> invoke LoadCursor,NULL,IDC_ARROW</b> <br>
<b> mov wc.hCursor,eax</b> <br>
<b> invoke RegisterClassEx, addr wc
; register our window class</b> <br>
<b> invoke CreateWindowEx,NULL,\</b> <br>
<b>
ADDR ClassName,\</b> <br>
<b>
ADDR AppName,\</b> <br>
<b>
WS_OVERLAPPEDWINDOW,\</b> <br>
<b>
CW_USEDEFAULT,\</b> <br>
<b>
CW_USEDEFAULT,\</b> <br>
<b>
CW_USEDEFAULT,\</b> <br>
<b>
CW_USEDEFAULT,\</b> <br>
<b>
NULL,\</b> <br>
<b>
NULL,\</b> <br>
<b>
hInst,\</b> <br>
<b>
NULL</b> <br>
<b> mov hwnd,eax</b> <br>
<b> invoke ShowWindow, hwnd,CmdShow
; display our window on desktop</b> <br>
<b> invoke UpdateWindow, hwnd
; refresh the client area</b>
<p><b> .WHILE TRUE
; Enter message loop</b> <br>
<b>
invoke GetMessage, ADDR msg,NULL,0,0</b> <br>
<b>
.BREAK .IF (!eax)</b> <br>
<b>
invoke TranslateMessage, ADDR msg</b> <br>
<b>
invoke DispatchMessage, ADDR msg</b> <br>
<b> .ENDW</b> <br>
<b> mov eax,msg.wParam
; return exit code in eax</b> <br>
<b> ret</b> <br>
<b>WinMain endp</b>
<p><b>WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM</b> <br>
<b> .IF uMsg==WM_DESTROY
; if the user closes our window</b> <br>
<b> invoke PostQuitMessage,NULL
; quit our application</b> <br>
<b> .ELSE</b> <br>
<b> invoke DefWindowProc,hWnd,uMsg,wParam,lParam
; Default message processing</b> <br>
<b> ret</b> <br>
<b> .ENDIF</b> <br>
<b> xor eax,eax</b> <br>
<b> ret</b> <br>
<b>WndProc endp</b>
<p><b>end start</b>
<h3> Analysis:</h3>
You may be taken aback that a simple Windows program requires so much coding.
But most of those codes are just *template* codes that you can copy from one source
code file to another. Or if you prefer, you could assemble some of these codes
into a library to be used as prologue and epilogue codes. You can write only the
codes in WinMain function. In fact, this is what C compilers do. They let
you write WinMain codes without worrying about other housekeeping chores. The
only catch is that you must have a function named WinMain else C compilers will
not be able to combine your codes with the prologue and epilogue. You do not have
such restriction with assembly language. You can use any function name instead
of WinMain or no function at all. <br>
Prepare yourself. This's going to be a long, long tutorial. Let's analyze this
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -