In this lesson, we'll write a Windows program in assembly language that will pop up a message box and display "Win32 assembly is great!" when the program runs.
Theory:
Windows provides a large amount of resources for writing applications. The most important of these is the Windows API (Application programming Interface). The Windows API is a large set of powerful functions that are themselves stationed in Windows for people to call at any time. Most of these functions are included in several dynamic-link libraries (DLLs), such as Kernel32.dll, User32.dll, and Gdi32.dll. The functions in Kernel32.dll mainly deal with memory management and process scheduling; The functions in user32.dll mainly control the user interface; functions in Gdi32.dll are responsible for the graphical aspects of the operation. In addition to the main three dynamic link libraries above, you can also invoke functions that are contained in other dynamic link libraries, and of course you must have enough information about these functions.
Dynamic link libraries, as the name suggests, the code for these APIs is not contained in the Windows executable, but is loaded when it is to be used. In order for the application to find these functions at run time, the relevant relocation information must be embedded in the application's executable file beforehand. This information exists in the introduction library, where the linker finds the relevant information from the introduction library and inserts it into the executable file. You must specify the correct citation to the library, because only the correct placement of the data will have the correct relocation information.
Windows examines this information when the application is loaded, including the name of the dynamic-link library and the name of the function in which it was invoked. If this information is checked, Windows loads the corresponding dynamic link library and redirects the entry address of the called Function statement so that control power is transferred to the function when the function is invoked.
If you divide from the relevance of the character set, there are two classes of APIs: one for the ANSI character set and the other for the UNICODE character set. The first type of function has a "a" character at the end of the name, and a "w" character for Unicode processing (I think "w" may mean the wide character). The ANSI string we are familiar with is a NULL-terminated array of characters, with each ANSI character being a BYTE width. For the European language system, the ANSI character set is sufficient, but for several oriental languages with thousands of unique characters, only the UNICODE character set is used. Each UNICODE character occupies two byte widths, so that it is possible to use 65,336 different characters in a single string.
That's why the introduction of UNICODE is the reason. In most cases, we can use a header file to define a macro, and then when we actually call the function, we don't need to add the suffix "A" or "W" after the function name.
<译者注:如在头文件中定义函数foo();
#ifdef UNICODE
#define foo() fooW()
#else
#define foo() fooA()
#endif
>
Example:
I'm going to put the framework program down, and then we add something to it.
.386
.model flat, stdcall
.data
.code
start:
end start
The execution of an application begins with the first statement after the identifier defined by end. In the above frame program, start with start. Program-by-word execution has been encountered Jmp,jne,je,ret and other jump instructions. These jump directives transfer execution to other statements, and you must call function ExitProcess if the program is to exit Windows.
ExitProcess Proto Uexitcode:dword
The above line is a function prototype. The function prototype tells the compiler and linker the properties of the function, so that when compiling and linking, the compiler and the linker make the relevant type check. The prototype of the function is defined as follows:
functionname PROTO [Parametername]:datatype,[parametername]:datatype, ...
In short, the function name is added pseudo instruction Proto, followed by a string of data types separated by the comma list. In the previous ExitProcess definition, the function has an argument of a DWORD type. When you invoke with a high-level call statement, it is particularly useful to use a function prototype definition, which you can simply assume is a call statement with a parameter type check. For example, suppose you write this:
Call ExitProcess
If you do not push a DWORD type parameter onto the stack, the compiler and linker will not complain, but there is no doubt that your program will cause a crash when it runs. However, when you write this:
Invoke ExitProcess
The connector will send an error to remind you to forget to press a DWORD type parameter. So I recommend that you invoke a function using the Invoke command instead of call. The syntax for INVOKE is as follows:
INVOKE expression [, arguments]
Expression can be either a function name or a function pointer. Arguments are separated by commas. The prototype of most API functions is placed in the header file. If you are using the Hutch MASM32, these headers are in the folder Masm32/include, and these header files have the same extension as the INC, the function names, and the functions in the DLL, for example: KERNEL32.LIB the function of the ExitProcess function prototype sound Ming in the Kernel.inc. You can also declare the function prototype yourself. Hutch Windows is used in all my classes. Inc., these header files you can download from http://win32asm.cjb.net.