📄 lion-tutorial02.htm
字号:
you will see that it's full of function prototypes for kernel32.dll. If you
don't include kernel32.inc, you can still call ExitProcess but only with simple
call syntax. You won't be able to invoke the function. The point here is that:
in order to invoke a function, you have to put its function prototype somewhere
in the source code. In the above example, if you don't include kernel32.inc,
you can define the function prototype for ExitProcess anywhere in the source
code above the invoke command and it will work. The include files are there
to save you the work of typing out the prototypes yourself so use them whenever
you can.</font> <br>
<font face="Arial">Now we encounter a new directive, includelib. includelib
doesn't work like include. It 's only a way to tell the assembler what import
library your program uses. When the assembler sees an includelib directive,
it puts a linker command into the object file so that the linker knows what
import libraries your program needs to link with. You're not forced to use includelib
though. You can specify the names of the import libraries in the command line
of the linker but believe me, it's tedious and the command line can hold only
128 characters.</font>
<p><font face="Arial">Now save the example under the name msgbox.asm. Assuming
that ml.exe is in your path, assemble msgbox.asm with:</font>
<ul>
<font face="Arial">ml /c /coff /Cp msgbox.asm</font>
<li> <font face="Arial">/c tells MASM to assemble only. Do not invoke link.exe.
Most of the time, you would not want to call link.exe automatically since
you may have to perform some other tasks prior to calling link.exe.</font></li>
<br>
<font face="Arial">/coff tells MASM to create .obj file in COFF format. MASM
uses a variation of COFF (Common Object File Format) which is used under Unix
as its own object and executable file format.</font> <br>
<font face="Arial">/Cp tells MASM to preserve case of user identifiers. If you
use hutch's MASM32 package, you may put "option casemap:none" at the head of
your source code, just below .model directive to achieve the same effect.</font>
</ul>
<font face="Arial">After you successfully assemble msgbox.asm, you will get msgbox.obj.
msgbox.obj is an object file. An object file is only one step away from an executable
file. It contains the instructions/data in binary form. What is lacking is some
fixups of addresses by the linker.</font>
<p><font face="Arial">Then go on with link:</font>
<ul>
<font face="Arial">link /SUBSYSTEM:WINDOWS /LIBPATH:c:\masm32\lib
msgbox.obj</font>
</ul>
<blockquote><font face="Arial">/SUBSYSTEM:WINDOWS informs Link what sort
of executable this program is</font> <br>
<font face="Arial">/LIBPATH:<path to import library> tells Link where the
import libraries are. If you use MASM32, they will be in MASM32\lib folder.</font></blockquote>
<font face="Arial">Link reads in the object file and fixes it with addresses from
the import libraries. When the process is finished you get msgbox.exe.</font>
<p><font face="Arial">Now you get msgbox.exe. Go on, run it. You'll find that
it does nothing. Well, we haven't put anything interesting into it yet. But
it's a Windows program nonetheless. And look at its size! In my PC, it is 1,536
bytes.</font>
<p><font face="Arial">Next we're going to put in a message box. Its function prototype
is:</font>
<p><b><font face="Arial">MessageBox PROTO hwnd:DWORD, lpText:DWORD, lpCaption:DWORD,
uType:DWORD</font></b>
<blockquote><font face="Arial">hwnd is the handle to parent window. You can think
of a handle as a number that represents the window you're referrring to. Its
value is not important to you. You only remember that it represents the window.
When you want to do anything with the window, you must refer to it by its handle.</font>
<br>
<font face="Arial">lpText is a pointer to the text you want to display in the
client area of the message box. A pointer is really an address of something.
A pointer to text string==The address of that string.</font> <br>
<font face="Arial">lpCaption is a pointer to the caption of the message box</font>
<br>
<font face="Arial">uType specifies the icon and the number and type of buttons
on the message box</font></blockquote>
<font face="Arial">Let's modify msgbox.asm to include the message box.</font>
<br>
<p><font face="Arial">.386</font> <br>
<font face="Arial">.model flat,stdcall</font> <br>
<font face="Arial">option casemap:none</font> <br>
<font face="Arial">include \masm32\include\windows.inc</font> <br>
<font face="Arial">include \masm32\include\kernel32.inc</font> <br>
<font face="Arial">includelib \masm32\lib\kernel32.lib</font> <br>
<font face="Arial">include \masm32\include\user32.inc</font> <br>
<font face="Arial">includelib \masm32\lib\user32.lib</font>
<p><font face="Arial">.data</font> <br>
<font face="Arial">MsgBoxCaption db "Iczelion Tutorial No.2",0</font>
<br>
<font face="Arial">MsgBoxText db "Win32
Assembly is Great!",0</font>
<p><font face="Arial">.code</font> <br>
<font face="Arial">start:</font> <br>
<font face="Arial">invoke MessageBox, NULL, addr MsgBoxText, addr MsgBoxCaption,
MB_OK</font> <br>
<font face="Arial">invoke ExitProcess, NULL</font> <br>
<font face="Arial">end start</font>
<p><font face="Arial">Assemble and run it. You will see a message box displaying
the text "Win32 Assembly is Great!".</font>
<p><font face="Arial">Let's look again at the source code.</font> <br>
<font face="Arial">We define two zero-terminated strings in .data section. Remember
that every ANSI string in Windows must be terminated by NULL (0 hexadecimal).</font>
<br>
<font face="Arial">We use two constants, NULL and MB_OK. Those constants are
documented in windows.inc. So you can refer to them by name instead of the values.
This improves readability of your source code.</font> <br>
<font face="Arial">The addr operator is used to pass the address of a label
to the function. It's valid only in the context of invoke directive. You can't
use it to assign the address of a label to a register/variable, for example.
You can use offset instead of addr in the above example. However, there are
some differences between the two:</font>
<ol>
<li> <font face="Arial">addr cannot handle forward reference while offset can.
For example, if the label is defined somewhere further in the source code
than the invoke line, addr will not work.</font></li>
<blockquote><font face="Arial">invoke MessageBox,NULL, addr MsgBoxText,addr
MsgBoxCaption,MB_OK</font> <br>
<font face="Arial">......</font> <br>
<font face="Arial">MsgBoxCaption db "Iczelion Tutorial No.2",0</font>
<br>
<font face="Arial">MsgBoxText db "Win32
Assembly is Great!",0</font></blockquote>
<font face="Arial">MASM will report error. If you use offset instead of addr
in the above code snippet, MASM will assemble it happily.</font>
<li> <font face="Arial">addr can handle local variables while offset cannot.
A local variable is only some reserved space in the stack. You will only know
its address during runtime. offset is interpreted during assembly time by
the assembler. So it's natural that offset won't work for local variables.
addr is able to handle local variables because of the fact that the assembler
checks first whether the variable referred to by addr is a global or local
one. If it's a global variable, it puts the address of that variable into
the object file. In this regard, it works like offset. If it's a local variable,
it generates an instruction sequence like this before it actually calls the
function:</font></li>
<blockquote><font face="Arial">lea eax, LocalVar</font> <br>
<font face="Arial">push eax</font></blockquote>
<p><br>
<font face="Arial">Since lea can determine the address of a label at runtime,
this works fine.</font><font face="Fixedsys"><strong> </strong></font>
</ol>
<hr size="1">
<div align="center"> This article come from Iczelion's asm page, Welcom to <a href="http://asm.yeah.net">http://asm.yeah.net</a></div>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -