⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lion-tutorial03.htm

📁 内有一些代码
💻 HTM
📖 第 1 页 / 共 3 页
字号:
program to death! 
<ul>
  <b>.386</b> <br>
  <b>.model flat,stdcall</b> <br>
  <b>option casemap:none</b> 
  <p><b>WinMain proto :DWORD,:DWORD,:DWORD,:DWORD</b> 
  <p><b>include \masm32\include\windows.inc</b> <br>
    <b>include \masm32\include\user32.inc</b> <br>
    <b>include \masm32\include\kernel32.inc</b> <br>
    <b>includelib \masm32\lib\user32.lib</b> <br>
    <b>includelib \masm32\lib\kernel32.lib</b>
</ul>
The first three lines are "necessities". .386 tells MASM we intend to use 80386 
instruction set in this program. .model flat,stdcall tells MASM that our program 
uses flat memory addressing model. Also we will use stdcall parameter passing 
convention as the default one in our program. <br>
Next is the function prototype for WinMain. Since we will call WinMain later, 
we must define its function prototype first so that we will be able to invoke 
it. <br>
We must include windows.inc at the beginning of the source code. It contains important 
structures and constants that are used by our program. The include file , windows.inc, 
is just a text file. You can open it with any text editor. Please note that windows.inc 
does not contain all structures, and constants (yet). hutch and I are working 
on it. You can add in new items if they are not in the file. <br>
Our program calls API functions that reside in user32.dll (CreateWindowEx, RegisterWindowClassEx, 
for example) and kernel32.dll (ExitProcess), so we must link our program to those 
two import libraries. The next question : how can I know which import library 
should be linked to my program? The answer: You must know where the API functions 
called by your program reside. For example, if you call an API function in gdi32.dll, 
you must link with gdi32.lib. <br>
This is the approach of MASM. TASM 's way of import library linking is much more 
simpler: just link to one and only one file: import32.lib. 
<ul>
  <b>.DATA</b> <br>
  <b>&nbsp;&nbsp;&nbsp; ClassName db "SimpleWinClass",0</b> <br>
  <b>&nbsp;&nbsp;&nbsp; AppName&nbsp; db "Our First Window",0</b> 
  <p><b>.DATA?</b> <br>
    <b>hInstance HINSTANCE ?</b> <br>
    <b>CommandLine LPSTR ?</b>
</ul>
Next are the "DATA" sections. <br>
In .DATA, we declare two zero-terminated strings(ASCIIZ strings): ClassName which 
is the name of our window class and AppName which is the name of our window. Note 
that the two variables are initialized. <br>
In .DATA?, two variables are declared: hInstance (instance handle of our program) 
and CommandLine (command line of our program). The unfamiliar data types, HINSTANCE 
and LPSTR, are really new names for DWORD. You can look them up in windows.inc. 
Note that all variables in .DATA? section are not initialized, that is, they don't 
have to hold any specific value on startup, but we want to reserve the space for 
future use. 
<ul>
  <b>.CODE</b> <br>
  <b>&nbsp;start:</b> <br>
  <b>&nbsp;&nbsp;&nbsp;&nbsp; invoke GetModuleHandle, NULL</b> <br>
  <b>&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp; hInstance,eax</b> <br>
  <b>&nbsp;&nbsp;&nbsp;&nbsp; invoke GetCommandLine</b> <br>
  <b>&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp; CommandLine,eax</b> <br>
  <b>&nbsp;&nbsp;&nbsp;&nbsp; invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT</b> 
  <br>
  <b>&nbsp;&nbsp;&nbsp;&nbsp; invoke ExitProcess,eax</b> <br>
  <b>&nbsp;&nbsp;&nbsp;&nbsp; .....</b> <br>
  <b>end start</b> 
</ul>
.CODE contains all your instructions. Your codes must reside between &lt;starting 
label>: and end &lt;starting label>. The name of the label is unimportant. You 
can name it anything you like so long as it is unique and doesn't violate the 
naming convention of MASM. <br>
Our first instruction is the call to GetModuleHandle to retrieve the instance 
handle of our program. Under Win32, instance handle and module handle are one 
and the same. You can think of instance handle as the ID of your program. It is 
used as parameter to several API functions our program must call, so it's generally 
a good idea to retrieve it at the beginning of our program. <br>
<b>Note: Actually under win32, instance handle is the linear address of your program 
in memory.</b> <br>
Upon returning from a Win32 function, the function's return value, if any, can 
be found in eax. All other values are returned through variables passed in the 
function parameter list you defined for the call. <br>
A Win32 function that you call will nearly always preserve the segment registers 
and the ebx, edi, esi and ebp registers. Conversely, ecx and edx are considered 
scratch registers and are always undefined upon return from a Win32 function. 
<br>
<b>Note: Don't expect the values of eax, ecx, edx to be preserved across API function 
calls.</b> <br>
The bottom line is that: when calling an API function, expects return value in 
eax. If any of your function will be called by Windows, you must also play by 
the rule: preserve and restore the values of the segment registers, ebx, edi, 
esi and ebp upon function return else your program will crash very shortly, this 
includes your window procedure and windows callback functions. <br>
The GetCommandLine call is unnecessary if your program doesn't process a command 
line. In this example, I show you how to call it in case you need it in your program. 
<br>
Next is the WinMain call. Here it receives four parameters: the instance handle 
of our program, the instance handle of the previous instance of our program, the 
command line and window state at first appearance. Under Win32, there's NO previous 
instance. Each program is alone in its address space, so the value of hPrevInst 
is always 0. This is a leftover from the day of Win16 when all instances of a 
program run in the same address space and an instance wants to know if it's the 
first instance. Under win16, if hPrevInst is NULL, then this instance is the first 
one. <br>
Note: You don't have to declare the function name as WinMain. In fact, you have 
complete freedom in this regard. You don't have to use any WinMain-equivalent 
function at all. You can paste the codes inside WinMain function next to GetCommandLine 
and your program will still be able to function perfectly. <br>
Upon returning from WinMain, eax is filled with exit code. We pass that exit code 
as the parameter to ExitProcess which terminates our application. 
<p><b>WinMain proc Inst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD</b> 
<p>The above line is the function declaration of WinMain. Note the parameter:type 
  pairs that follow PROC directive. They are parameters that WinMain receives 
  from the caller. You can refer to these parameters by name instead of by stack 
  manipulation. In addition, MASM will generate the prologue and epilogue codes 
  for the function. So we don't have to concern ourselves with stack frame on 
  function enter and exit. 
<p><b>&nbsp;&nbsp;&nbsp; LOCAL wc:WNDCLASSEX</b> <br>
  <b>&nbsp;&nbsp;&nbsp; LOCAL msg:MSG</b> <br>
  <b>&nbsp;&nbsp;&nbsp; LOCAL hwnd:HWND</b> 
<p>LOCAL directive allocates memory from the stack for local variables used in 
  the function. The bunch of LOCAL directives must be immediately below the PROC 
  directive. The LOCAL directive is immediately followed by &lt;the name of local 
  variable>:&lt;variable type>. So LOCAL wc:WNDCLASSEX tells MASM to allocate 
  memory from the stack the size of WNDCLASSEX structure for the variable named 
  wc. We can refer to wc in our codes without any difficulty involved in stack 
  manipulation. That's really a godsend, I think. The downside&nbsp; is that local 
  variables cannot be used outside the function they're created and will be automatically 
  destroyed when the function returns to the caller. Another drawback is that 
  you cannot initialize local variables automatically because they're just stack 
  memory allocated dynamically when the function is entered . You have to manually 
  assign them with desired values after LOCAL directives. 
<p><b>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp; wc.cbSize,SIZEOF WNDCLASSEX</b> <br>
  <b>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp; wc.style, CS_HREDRAW or CS_VREDRAW</b> 
  <br>
  <b>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp; wc.lpfnWndProc, OFFSET WndProc</b> <br>
  <b>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp; wc.cbClsExtra,NULL</b> <br>
  <b>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp; wc.cbWndExtra,NULL</b> <br>
  <b>&nbsp;&nbsp;&nbsp; push&nbsp; hInstance</b> <br>
  <b>&nbsp;&nbsp;&nbsp; pop&nbsp;&nbsp; wc.hInstance</b> <br>
  <b>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp; wc.hbrBackground,COLOR_WINDOW+1</b> <br>
  <b>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp; wc.lpszMenuName,NULL</b> <br>
  <b>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp; wc.lpszClassName,OFFSET ClassName</b> 
  <br>
  <b>&nbsp;&nbsp;&nbsp; invoke LoadIcon,NULL,IDI_APPLICATION</b> <br>
  <b>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp; wc.hIcon,eax</b> <br>
  <b>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp; wc.hIconSm,eax</b> <br>
  <b>&nbsp;&nbsp;&nbsp; invoke LoadCursor,NULL,IDC_ARROW</b> <br>
  <b>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp; wc.hCursor,eax</b> <br>
  <b>&nbsp;&nbsp;&nbsp; invoke RegisterClassEx, addr wc</b> 
<p>The inimidating lines above are really simple in concept. It just takes several 
  lines of instruction to accomplish. The concept behind all these lines is&nbsp; 
  <i>window class</i>. A window class is nothing more than a blueprint or specification 
  of a window. It defines several important characteristics of a window such as 
  its icon, its cursor, the function responsible for it, its color etc. You create 
  a window from a window class. This is some sort of object oriented concept. 
  If you want to create more than one window with the same characteristics, it 
  stands to reason to store all these characteristics in only one place and refer 
  to them when needed. This scheme will save lots of memory by avoiding duplication 
  of information. Remember, Windows is designed in the past when memory chips 
  are prohibitive and most computers have 1 MB of memory. Windows must be very 
  efficient in using the scarce memory resource. The point is: if you define your 
  own window, you must fill the desired characteristics of your window in a WNDCLASS 
  or WNDCLASSEX structure and call RegisterClass or RegisterClassEx before you're 
  able to create your window. You only have to register the window class once 
  for each window type you want to create a window from. <br>
  Windows has several predefined Window classes, such as button and edit box. 
  For these windows (or controls), you don't have to register a window class, 
  just call CreateWindowEx with the predefined class name. <br>
  The single most important member in the WNDCLASSEX is lpfnWndProc. lpfn stands 
  for long pointer to function. Under Win32, there's no "near" or "far" pointer, 
  just pointer because of the new FLAT memory model. But this is again a leftover 
  from the day of Win16. Each window class must be associated with a function 
  called window procedure. The window procedure is responsible for message handling 
  of all windows created from the associated window class. Windows will send messages 
  to the window procedure to notify it of important events concerning the windows 
  it 's responsible for,such as user keyboard or mouse input. It's up to the window 
  procedure to respond intelligently to each window message it receives. You will 
  spend most of your time writing event handlers in window procedure. <br>
  I describe each member of WNDCLASSEX below: 
<p><b>WNDCLASSEX STRUCT DWORD</b> <br>
  <b>&nbsp; cbSize&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
  DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ?</b> <br>
  <b>&nbsp; style&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
  DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ?</b> <br>
  <b>&nbsp; lpfnWndProc&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
  ?</b> <br>
  <b>&nbsp; cbClsExtra&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
  ?</b> <br>
  <b>&nbsp; cbWndExtra&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
  ?</b> <br>
  <b>&nbsp; hInstance&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
  ?</b> <br>
  <b>&nbsp; hIcon&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
  DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ?</b> <br>
  <b>&nbsp; hCursor&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
  DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ?</b> <br>
  <b>&nbsp; hbrBackground&nbsp;&nbsp;&nbsp;&nbsp; DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
  ?</b> <br>
  <b>&nbsp; lpszMenuName&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
  ?</b> <br>
  <b>&nbsp; lpszClassName&nbsp;&nbsp;&nbsp;&nbsp; DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
  ?</b> <br>
  <b>&nbsp; hIconSm&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
  DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ?</b> <br>
  <b>WNDCLASSEX ENDS</b> 
<p><b>cbSize: </b>The size of WNDCLASSEX structure in bytes. We can use SIZEOF 
  operator to get the value. <br>
  <b>style: </b>The style of windows created from this class. You can combine 
  several styles together using "or" operator. <br>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -