Assembler. Calling API Functions.
To begin with, consider how to call API functions. You can open the help file and
choose any API function; for now, choose MessageBox:
int MessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType);
This function displays a message box with one or more command buttons that allow
you to close it:
� hWnd�The descriptor (handle) of the message box window.
� lpText�The text that will be displayed in this message box.
� lpCaption�The window header text.
uType�The window type; in particular, it allows you to define the number of
command buttons.
�
Now, consider the parameter types. All parameters are 32-bit integer numbers:
� HWND�32-bit integer
� LPCTSTR�32-bit pointer to the string
� UINT�32-bit integer
For a reason that will be explained later, you will have to add the A suffix to
function
names. Besides this, when using MASM, it is necessary to add the @16 suffix to the
function names. Thus, the call to the previously described function will look as
follows:
CALL MessageBoxA@16
What about parameters? They must have been loaded beforehand into the stack using
PUSH commands. Memorize a simple rule: from left to right, and from bottom to top.
Thus, assume that the window descriptor is located by the address HW, the strings
are
located by the addresses STR1 and STR2, and the message box type is a constant. The
simplest type has the zero value and is called MB_OK.
As you can see, everything is easy and straightforward, as if you were calling this
function from a program written in C or Pascal. The result returned by any function
is
usually an integer number returned into the EAX register.
Strings deserve to be considered separately. Generally, when speaking about
strings,
one usually means a string address (or pointer). In most cases, it is assumed that
the
string is terminated by the character with the code 0. However, one of the
parameters
of an API function often specifies the string length (in documentation often called
the
buffer) defined by another parameter. You should bear this in mind, because it
might
happen that the returned string won't be terminated by zero, and zero is required
to
use that string in another function. If this possibility is not taken into account,
this
might result in phantom errors in your program (i.e., such errors that appear or
disappear like ghosts).