📄 lion-tutorial02.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"><font face="Arial">Tutorial 2: MessageBox</font></p>
<hr size="1">
<center>
<font face="Arial">In this tutorial, we will create a fully functional Windows
program that displays a message box saying "Win32 assembly is great!".</font>
</center>
<p><font face="Arial">Download the example file <a href="files/tut02.zip">here</a>.</font>
<h3> <font face="Arial">Theory:</font></h3>
<font face="Arial">Windows prepares a wealth of resources for Windows programs.
Central to this is the Windows API (Application Programming Interface). Windows
API is a huge collection of very useful functions that reside in Windows itself,
ready for use by any Windows programs. These functions are stored in several dynamic-linked
libraries (DLLs) such as kernel32.dll, user32.dll and gdi32.dll. Kernel32.dll
contains API functions that deal with memory and process management. User32.dll
controls the user interface aspects of your program. Gdi32.dll is responsible
for graphics operations. Other than "the main three", there are other DLLs that
your program can use, provided you have enough information about the desired API
functions.</font> <br>
<font face="Arial">Windows programs dynamically link to these DLLs, ie. the codes
of API functions are not included in the Windows program executable file. In order
for your program to know where to find the desired API functions at runtime, you
have to embed that information into the executable file. The information is in
import libraries. You must link your programs with the correct import libraries
or they will not be able to locate API functions.</font> <br>
<font face="Arial">When a Windows program is loaded into memory, Windows reads
the information stored in the program. That information includes the names of
functions the program uses and the DLLs those functions reside in. When Windows
finds such info in the program, it'll load the DLLs and perform function address
fixups in the program so the calls will transfer control to the right function.</font>
<br>
<font face="Arial">There are two categoriesof API functions: One for ANSI and
the other for Unicode. The names of API functions for ANSI are postfixed with
"A", eg. MessageBoxA. Those for Unicode are postfixed with "W" (for Wide Char,
I think). Windows 95 natively supports ANSI and Windows NT Unicode.</font> <br>
<font face="Arial">We are usually familiar with ANSI strings, which are arrays
of characters terminated by NULL. ANSI character is 1 byte in size. While ANSI
code is sufficient for European languages, it cannot handle several oriental languages
which have several thousands of unique characters. That's why UNICODE comes in.
A UNICODE character is 2 bytes in size, making it possible to have 65536 unique
characters in the strings.</font> <br>
<font face="Arial">But most of the time, you will use an include file which can
determine and select the appropriate API functions for your platform. Just refer
to API function names without the postfix.</font>
<h3> <font face="Arial">Example:</font></h3>
<font face="Arial">I'll present the bare program skeleton below. We will flesh
it out later.</font>
<p><b><font face="Arial">.386<br>
.model flat, stdcall</font></b> <br>
<b><font face="Arial">.data</font></b> <br>
<b><font face="Arial">.code</font></b> <br>
<b><font face="Arial">start:</font></b> <br>
<b><font face="Arial">end start</font></b>
<p><font face="Arial">The execution starts from the first instruction immediately
below the label specified after end directive. In the above skeleton, the execution
will start at the first instruction immediately below start label. The execution
will proceed instruction by instruction until some flow-control instructions
such as jmp, jne, je, ret etc is found. Those instructions redirect the flow
of execution to some other instructions. When the program needs to exit to Windows,
it should call an API function, ExitProcess.</font>
<p><b><font face="Arial">ExitProcess proto uExitCode:DWORD</font></b>
<p><font face="Arial">The above line is called a function prototype. A function
prototype defines the attributes of a function to the assembler/linker so it
can do type-checking for you. The format of a function prototype is like this:</font>
<p><b><font face="Arial">FunctionName PROTO [ParameterName]:DataType,[ParameterName]:DataType,...</font></b>
<p><font face="Arial">In short, the name of the function followed by the keyword
PROTO and then by the list of data types of the parameters,separated by commas.
In the ExitProcess example above, it defines ExitProcess as a function which
takes only one parameter of type DWORD. Functions prototypes are very useful
when you use the high-level call syntax, invoke. You can think of invoke as
a simple call with type-checking. For example, if you do:</font>
<p><font face="Arial">call ExitProcess</font>
<p><font face="Arial">without pushing a dword onto the stack, the assembler/linker
will not be able to catch that error for you. You'll notice it later when your
program crashes. But if you use:</font>
<p><font face="Arial">invoke ExitProcess</font>
<p><font face="Arial">The linker will inform you that you forgot to push a dword
on the stack thus avoiding error. I recommend you use invoke instead of simple
call. The syntax of invoke is as follows:</font>
<p><b><font face="Arial">INVOKE expression [,arguments]</font></b>
<p><font face="Arial">expression can be the name of a function or it can be a
function pointer. The function parameters are separated by commas.</font>
<p><font face="Arial">Most of function prototypes for API functions are kept in
include files. If you use hutch's MASM32, they will be in MASM32/include folder.
The include files have .inc extension and the function prototypes for functions
in a DLL is stored in .inc file with the same name as the DLL. For example,
ExitProcess is exported by kernel32.lib so the function prototype for ExitProcess
is stored in kernel32.inc.</font> <br>
<font face="Arial">You can also create function prototypes for your own functions.</font>
<br>
<font face="Arial">Throughout my examples, I'll use hutch's windows.inc which
you can download from http://win32asm.cjb.net</font>
<p><font face="Arial">Now back to ExitProcess, uExitCode parameter is the value
you want the program to return to Windows after the program terminates. You
can call ExitProcess like this:</font>
<p><b><font face="Arial">invoke ExitProcess, 0</font></b>
<p><font face="Arial">Put that line immediately below start label, you will get
a win32 program which immediately exits to Windows, but it's a valid program
nonetheless.</font>
<p><b><font face="Arial">.386</font></b> <br>
<b><font face="Arial">.model flat, stdcall</font></b> <br>
<b><font face="Arial">option casemap:none</font></b> <br>
<b><font face="Arial">include \masm32\include\windows.inc</font></b> <br>
<b><font face="Arial">include \masm32\include\kernel32.inc</font></b> <br>
<b><font face="Arial">includelib \masm32\lib\kernel32.lib</font></b> <br>
<b><font face="Arial">.data</font></b> <br>
<b><font face="Arial">.code</font></b> <br>
<b><font face="Arial">start:</font></b> <br>
<b><font face="Arial"> invoke
ExitProcess,0</font></b> <br>
<b><font face="Arial">end start</font></b>
<p>option casemap:none tells MASM to make labels case-sensitive so ExitProcess
and exitprocess are different. <font face="Arial">Note a new directive, include.
This directive is followed by the name of a file you want to insert at the place
the directive is. In the above example, when MASM processes the line include
\masm32\include\windows.inc, it will open windows.inc which is in \MASM32\include
folder and process the content of windows.inc as if you paste the content of
windows.inc there. hutch's windows.inc contains definitions of constants and
structures you need in win32 programming. It doesn't contain any function prototype.
windows.inc is by no means comprehensive. hutch and I try to put as many constants
and structures into it as possible but there are still many left to be included.
It'll be constantly updated. Check out hutch's and my homepage for updates.</font>
<br>
<font face="Arial">From windows.inc, your program got constant and structure
definitions. Now for function prototypes, <font face="Arial, Helvetica, sans-serif">you
need to include other include files. They are all stored in \masm32\include
folder. </font></font>
<p><font face="Arial, Helvetica, sans-serif">In our example above, we call a function
exported by kernel32.dll, so we need to include the function pro</font><font face="Arial">totypes
from kernel32.dll. That file is kernel32.inc. If you open it with a text editor,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -