ICZelion TUT2

zhaozj2021-02-11  191

Second class message box

In this lesson, we will write a Windows program with assembly language, and a message box will pop up when the program runs and displays "Win32 Assembly IS Great!".

theory:

Windows provides a lot of resources for writing applications. The most important of these is the Windows API (Application Programming Interface). Windows API is a large group of powerful functions that are stationed in Windows for people to call. Most of these functions are included in several dynamic link libraries (DLLs), such as kernel32.dll, user32.dll, and gdi32.dll. The function in kernel32.dll works primarily to process memory management and process schedule; functions in user32.dll primarily control the user interface; the functions in GDI32.DLL are responsible for graphics operations. In addition to the main three dynamic link libraries above, you can also call functions included in other dynamic link libraries, of course, you must have enough information on these functions.

Dynamic Link Library, as the name suggests, these API code itself is not included in the Windows executable, but is loaded when you are used. In order to let the application can find these functions at runtime, you must embed the relevant relocation information in advance to the application's executable. This information exists in the introduction library, and the linker finds the relevant information from the introduction library in the inserted to the executable. You must specify the correct introduction library because only the correct import library will have correct relocation information.

Windows checks this information when the application is loaded, including the name of the dynamic link library and the names of the function being called. If you check such information, Windows loads the corresponding dynamic link library, and relocates the entry address of the called function statement to control the control power to the inside of the function when the function is called.

If the correlation from the character set is divided, the API has two categories: one is to process the ANSI character set, and the other is to process the Unicode character set. The tail of the previous class function name with a "A" character, handling Unicode, with a "W" character (I think "W" may be a representative of the broad character.) Our more familiar ANSI strings are array of characters ending with NULL, each ANSI character is a BYTE width. For the European language system, the ANSI character set is sufficient, but only the Unicode character set is used for several oriental language systems with thousands of unique characters. Each Unicode character holds two BYTE width, so that 65336 different characters can be used in a string.

This is why the reason for introducing Unicode. In most cases, we can use a header file in which a macro is defined, and then when the function is actually invoked, the function name does not need to add "A" or "W".

example:

I first put the framework below, then add something to it.

.386.Model flat, stdcall.data.codestart: End Start

The execution of the application starts from the first statement after the identifier defined by the END. The above frame program is starting from START. The program is performed on a jump instruction that is encountered by JMP, JNE, JE, RET. These jump instructions will transfer the execution to other statements. If the program is to exit Windows, the function EXITPROCESS must be called. EXITPROCESS Proto UEXITCODE: DWORD

The above line is the function prototype. Function prototypes tell the compiler and linker properties of this function, which is checked by the compiler and linker when compiling and linking. The prototype of the function is as follows:

FunctionName Proto [parametername]: DataType, [parametername]: DataType, ...

In short, adding the command Proto after the function name, follows a string of data type linked lists separated by commas. In the previous exitProcess definition, this function has a DWORD type parameter. When you use the High-level call statement invoke, use the function prototype definition especially, you can simply think that invoke is a call statement with a parameter type check. For example, suppose you write this:

Call EXITPROCESS

If you don't press a DWORD type parameter in advance, the compiler and linker will not report error, but there is no doubt that it will cause crash when your program is running. But when you write this:

Invoke EXITPROCESS

The connector will report an error to remind you to forget to press a DWORD type parameter. So I suggest you call a function with the Invoke directive instead of call. The syntax of Invoke is as follows:

Invoke expression [, arguments]

Expression can be either a function name or a function pointer. The parameters are separated by commas. The prototype of most API functions is placed in the header file. If you use the hutch's Masm32, these header files Under Folder Masm32 / Include, these header files are the same as the function name in the INC, function name, and DLL, such as the function of the function EXITPROCESS, which is: kernel32.lib. Declare in kernel.inc. You can also declare the function prototype yourself. Use Hutch's Windows in my teaching course. INC, these headers you can download from http://win32asm.cjb.net.

Ok, we now return to the exitProcess function, the parameter uExitcode is what you want to pass Windows when your application ends. You can write this:

Invoke EXITPROCESS, 0

Put this line to the start identifier, this app will immediately exit Windows, of course, there is no doubt that an application itself is a complete Windows program.

.386.model flat, stdcalloption casemap: noneinclude /masm32/include/windows.incinclude /masm32/include/kernel32.incincludelib /masm32/lib/kernel32.lib.data.codestart:invoke ExitProcess, 0end start

Option Casemap: None means to tell Masm to distinguish between scratch, such as: Start and Start are different. Note that the new directive Include, follow the files specified in the file name thereafter in compile time. In our block, when MASM is processed to statement incrude /masm/include/windows.inc, it opens file Windows.inc on folder / masm32 / include, which is pasted throughout the file. The effect in your source program is the same. Hutch's Windows.inc contains the definitions of constants and structures required for Win32 programming. But it does not contain the definition of the function prototype. Although Hutch and I do our best to include all constants and structures definitions, there will still be a lot of omissions, and we will continue to join new content. Please stay at our home page at any time and download the latest header file. Your application requires a declaration of a function prototype from other header files in addition to the definition of the correlation variable structure from Windows.inc, which is placed in the / Masm32 / Include folder. In our example, call the function in the kernel.dll, so you need to include the header file kernel.inc with this function prototype declaration. If you open this file with a text editor you will find a statement that is all the functions taken from Kernel.dll. If you don't include kernel.inc, you can still call (Call) EXITPROCESS, but you cannot call (Invoke) EXITPROCESS (this will not be able to check the compiler and the parameters of the connector). So if you call a function with Invoke, you must declare prior, of course, don't have to include our header file, you can perform a name before calling the function. It is mainly to save time (translator: Of course, there is also correct)

Let's take a look at the includeLib pseudo directive, and the include, it is just to tell the compiler which library is quoted. When the compiler processes the instruction, insert the link command in the generated destination file tells the linker to link what library. Of course, you can also achieve the same purpose as the introduction library name in the command line of the linker, but considering that the command line can only pass 128 characters and do not tire the manifest to knock in the command line, The method is very unsuitable.

Ok, now save an example, named msgbox.asm. Put ml.exe's path into the PATH environment variable, type the following line to compile:

ML / C / COFF / CP MSGBOX. ASM (Translator Note: Command line parameter case is different)

/ c is telling MASM only compiling without links. This is mainly considering that you may have other jobs before the link. / Coff tells MASM to generate the target file with the COFF format. The MASM's COFF format is a variant of the Coff (Common Object File Format) format. There is also different COFF formats under UNIX. / CP tells MASM Do not change the case of user-defined identifiers. If you use the HUTCH containing files, add the "Option Casemap: None" statement under the .Model directive to achieve the same effect.

When you successfully compile MSGBox.asm, the compiler generates a msgbox.obj target file, the target file, and executable only one step, the target file contains instructions and data existing in binary form, than executable The difference is just the relocation information added by the linker. Ok, let's link the target file:

LINK / SUBSYSTEM: Windows / LibPath: C: / Masm32 / Lib msgbox.obj

/ Subsystem: Windows tells the linker running platform / libpath: tells the path of the library.

The work made by the linker is to add relocation information to the target file in the introduction library, and finally generate executable files. Since we get an executable file, let's run. Good, one, two, three, go! Nothing on the screen. Oh, yes, in addition to calling the exitprocess function, we haven't done anything! But don't have a sense of accomplishment, because we write a real Windows program with a compilation, don't believe it, check the msgbox.exe file on your disk, with a size of 1,536 words on my machine. Section.

Let's take a look at it, we join a dialog in the program. The prototype of this function is as follows:

MessageBox Proto Hwnd: DWORD, LPTEXT: DWORD, LPCAPTION: DWORD, UTYPE: DWORD

HWND is the handle of the parent window. The handle represents an address pointer to the window you reference. Its value is not important to your editor's Windows program (Translator Note: If you want to become a master), you just need to know that it represents a window. When you want to do anything about the window, you must reference the pointer of the window. LPText is a pointer to the text you want to display. The pointer to the text string is actually the first address of the text string. LPCAPTION is the title text string pointer to the dialog you want to display. UTYPE is the type of small icon displayed on the dialog window.

Below is the source program

.386 .model flat, stdcall option casemap: none include /masm32/include/windows.inc include /masm32/include/kernel32.inc includelib /masm32/lib/kernel32.lib include /masm32/include/user32.inc includelib / masm32 /LIB/USER32.LIB

.Data Msgboxcaption DB "icion tutorial No.2", 0 MSGboxText DB "Win32 Assembly is Great!", 0

. Code Start: Invoke Messagebox, Null, Addr Msgboxtext, Addr Msgboxcaption, MB_OK Invoke EXITPROCESS, NULL End Start

Compile, link the block above to get the executable. Run, haha, pop up a dialog on the window, with a line above: "Win32 assembly is get!". Think about it, we have written out with compilation, so we have reason to be happy for writing a simple win32 program. (Translator Note: If we can use each line in DOS, we have a reason to write, then we have reason to be proud of yourself.) Well, let's take a look at the source code above. We define the strings of two NULL ends at .DATA "segmentation". We used two constants: null and mb_ok. These constants are defined in the Windows.inc file and use constants to make your program have better readability. The AddR operator is used to pass the address of the label to the called function, which can only be used in the Invoke statement, such as you can't use it to secure the address to the register or variable, if you want to do this, use Offset symbol. There is a difference between OFFSET and ADDR:

AddR cannot handle forward reference, Offset can. The so-called forward reference refers to: The definition of the label is after the Invoke statement, such as in the following example: Invoke MessageBox, Null, Addr MsgboxText, Addr MsgBoxCaption, MB_OK ... Msgboxcaption DB "ICZelion Tutorial No.2", 0msgboxText DB "Win32 Assembly is Great!", 0 If you use Addr instead of Offset, the MASM will report an error. AddR can handle local variables and OFFSET cannot be. The local variable is only assigned memory space in the stack at runtime. The Offset is interpreted by the compiler when compiling, which obviously cannot use Offset to allocate memory space at runtime. The processing of the compiler is the first check that the overall or local variable is processed. If the global variable is placed in the target file, this is the same as OFFSET, if the local variable is executed, the following instruction sequence is generated before executing the INVOKE statement. : Lea Eax, Localvarpush EAX Because the LEA instructions can determine the valid address of the label at runtime, there is a sequence of instructions to ensure that the invoke is executed correctly.

转载请注明原文地址:https://www.9cbs.com/read-4682.html

New Post(0)