First, advantages
Using inline assembly can be embedded in the C / C code, and no additional assembly and connection steps are required. In Visual C , the inline assembly is a built-in compiler, so there is no need to configure an independent assembly tool such as MASM. Here, we will introduce related knowledge of intra Visual C in Visual Studio .NET 2003 (if it is an early version, there may be some access).
Inline assembly code can use C / C variables and functions, so it can be easily integrated into the C / C code. It can do some tasks that are very cumbersome or impossible to use C / C alone.
The use of inline assembly includes:
Write a specific function using assembly language; write code for speed requirements; directly access hardware in the device driver; write the initialization and end code of the Naked function.
Second, keywords
Use the inline assembly to use the __asm keyword, which can appear in any place that allows the C / C statement to appear. Let's see some examples:
Simple __asm block:
__ASM {MOV Al, 2 MOV DX, 0xD007 OUT AL, DX}
Add __ASM keyword before each assembly instruction:
__ASM MOV AL, 2 __ASM MOV DX, 0XD007 __ASM OUT Al, DX
Because __asm keyword is a statement separator, you can put multiple assembly instructions in the same line:
__ASM MOV AL, 2 __ASM MOV DX, 0XD007 __ASM OUT Al, DX
Obviously, the first method is consistent with the style of C / C , and the assembly code and C / C code are clearly separated, and the repeated input __asm keyword is also avoided, so the first method is recommended.
Unlike "{}" in C / C , "{}" from __ ASM block does not affect the scope of the C / C variable. At the same time, __ ASM blocks can nested, and nesting does not affect the range of variables.
In order to have the same meaning as the low version of Visual C , _ASM and __ASM have the same meaning. In addition, Visual C supports standard C ASM keywords, but it does not generate any instructions, which only allows the compiler that does not have compilation errors. To use the inline assembly, you must use __asm instead of the ASM keyword.
Third, assembly language
Directive set
Inline assembly supports all instructions of Intel Pentium 4 and AMD Athlon. More other processors can be created by the _emit directive (_emit directive instructions below).
2. MASM expression
In the inner assembly code, all MASM expressions (MASM expressions are used to calculate a value or a combination of operators and operands of an address).
3. Data indicator and operator
Although the __ASM block allows the use of C / C data types and objects, it cannot use MASM indicators and operators to define data objects. It is particularly pointed out that the definition indicators (DB, DW, DD, DQ, DQ, DT, DT, DT, DT, DT, DT, DT, DT, DT, DT, DT, DT, DT, DT, DT, DT, DT, and DT,) are not allowed to use DUP and THIS operators. The structural and records in Masm are no longer valid, and the inline assembly does not accept struc, record, width or mask. 4. Even and align indicators
Although the intangible deployment does not support most MASM indicators, it supports Even and Align. When needed, these indicators are added to the NOP instruction (empty operation) in the assembly code to align the label to a particular boundary. This makes it possible to have higher efficiency when some processors are taking instructions.
5. MASM macro
Inline assembly is not macro assembly, and cannot use MASM macro (Macro, Rept, IRC, IRP, and ENDM) and macro (<>,!, &,%, And.type).
6. Segment
You must use a register instead of the name to specify the segment (the segment name "_text" is invalid). Also, the section must explicitly explain, such as ES: [EBX].
7. Type and variable size
In the interiors, you can use Length, Size and Type to get the size of C / C variables and types. * Length operator is used to get the number of elements of the C / C in the middle group (if not an array, the result is 1). * The Size operator can get the size of the C / C variable (the size of a variable is the product of Length and Type). * TYPE operators can return the size of the C / C type and variables (if the variable is an array, it gets the size of a single element in the array).
For example, an 8-dimensional integer variable is defined in the program:
INT IARRAY [8];
The following is the correlation value of the IARRAY and its elements obtained in C and assembly expressions:
__asm c size
Length IaRray Sizeof (IARRAY) / Sizeof (IaRray [0]) 8 Size IaRray Sizeof (IARRAY) 32 TYPE IARRAY SIZEOF (IARRAY [0]) 4
8. Note
An annotation of assembly languages can be used in the inline assembly, ie ";". E.g:
__ASM MOV Eax, Offset PBBUFF; Load Address of PBBUFF
Because the C / C macro will begin to a logical row, in order to avoid confusion brought by the assembly language annotation in the macro, the inline depicted annotation is also allowed to use the C / C annotation.
9. _EMIT Pseudo Directive
_EMIT directive equivalent to DB in MASM, but _emit can only define one byte in the current code segment (.text segment) at a time. E.g:
__ASM {JMP _CodeLabel
_Emit 0x00; define data mixed in code segment_emit 0x01
_Codelabel:; Here is the code _emit 0x90; NOP instruction} 10. Register use
In general, it cannot be assumed that a register has known values when the __ASM block begins. The value of the register will not guarantee that the __ASM block is kept from the __ASM block from the __asm block.
If a function declares as a __fastcall call mode, its parameter will pass through the register instead of the stack. This will cause the __ASM block to generate a problem because the function cannot be inform with which parameter is in which register is. If the function receives the parameters in Eax and stores a value into Eax immediately, the original parameter will be lost. In addition, in all the functions of __fastcall, the ECX register must always be retained. In order to avoid the above conflicts, the function containing the __asm block should not be declared as __fastcall call mode.
Tip: If you use Eax, EBX, ECX, EDX, ESI, and EDI registers, you don't need to save it. But if you use the DS, SS, SP, BP, and flag registers, you should save these registers with PUSH. Tip: If the program is changed in the program, it must be restored to the original value.
Fourth, use C / C elements
1. Available C / C elements
C / C and assembly language can be mixed, and C / C variables and many other C / C elements can be used in the interiors.
Symbols, including reference numerals, variables, and function names; constants, including symbol constants and enumerated members; macro definitions and pre-processing indicators; annotations, "/ ** /" and "//"; type name, including all MASM Legal types; typedef names, usually use PTR and Type operators, or use the specified structure or enumeration member.
In the interior assembly, the C / C or the base count method of the assembly language can be used. For example, 0x100 and 100 h are equal.
2. Operator use
C / C operators such as "<<" cannot be used in the inline collection. However, C / C and MASM shared operators (such as "*" and "[]" operators are considered to be an operator of assembly language, which is available. for example:
INT IARRAY [10];
__ASM MOV IARRAY [6], BX; Store BX At IaRray 6 (Not Scaled) IARRAY [6] = 0; // Store 0 At IaRray 12 (Scaled)
Tip: In the interior assembly, you can use the TYPE operator to make it coincide with C / C . For example, the following two statements are the same:
__ASM MOV IARRAY [6 * TYPE INT], 0; Store 0 at IaRray 12 IARRAY [6] = 0; // Store 0 At IaRray 12
3. C / C symbol use
In the __ASM block, you can reference all C / C symbols within the scope of action, including variable name, function name, and label. But you cannot access member functions of the C class.
Below is some restrictions on the use of C / C symbols in the intraline assembly: Each assembled statement can only contain a C / C symbol. In a compilation instruction, multiple symbols can only appear in the length, Type or SIZE expression. The reference function in __ASM block must be declared first. Otherwise, the compiler will not distinguish the function name and label in the __asm block. In the __asm block, it cannot be used for MASM, which is the C / C symbol (not case sensitive). The MASM reserved word contains the instruction name (such as a PUSH) and register name (such as ESI). The structure and joint label cannot be identified in the __ASM block.
4. Access the data in C / C
A very large convenience of the inline assembly is that it can use the name to reference the C / C variable. For example, if the C / C variable IVAR is within the scope of action:
__ASM MOV Eax, Ivar; Stores The Value of Ivar in EAX
If the class, structure, or enumeration member in C / C has a unique name, in the __ASM block, it can be accessed only by the member name (omitted "." Operator's variable name or TypeDef name). However, if the member is not unique, you must add a variable name or typedef name before "." Operator. For example, the following two structures have SameName this member variable:
Struct first_type {char * pszweasel; int SameName;
Struct second_type {int tenton; long seatiname;
If you declare the variables as follows:
Struct first_type fttest; struct second_type sttemp;
Then, all places where the SameName member must use because SameName is not unique. In addition, since the above PSZWeasel variable has a unique name, you can use its member name to reference it:
__ASM {MOV EBX, OFFSET FTTEST MOV ECX, [EBX] fttest.samename; "fttest" MOV ESI, [EBX]. pszweasel; "fttest"}
Tip: The omitted variable name is only for writing code, and the generated assembly instruction is still the same.
5. Write functions with internal exchange
If you write a function with an internal issue, it is very easy to pass the parameters and return a value. Look at the example below, compare functions written in independent compilation and inline export:
PowerASM.ASM; Compute the power of an integer
PUBLIC GetPowerAsm _TEXT SEGMENT WORD PUBLIC 'CODE' GetPowerAsm PROC PUSH EBP; Save EBP MOV EBP, ESP; Move ESP into EBP so we can refer; to arguments on the stack MOV EAX, [EBP 4]; Get first argument MOV ECX, [EBP 6]; Get Second Argument SHL EAX, Cl; EAX = EAX * (2 ^ CL) POP EBP; Restore EBP RET; RETURN WITH SUM in EAX GetPowerASM ENDP _TEXT ENDS ENDC / C Function Generally with stacks to pass parameters, So the above functions need to access its parameters (in MASM or other assembly tools) through the stack position (in MASM or other assembly tools, also allowed to access the stack parameters and local stack variables).
The following procedure is written in intraline:
// PowerC.c
#include
INT getPowerc (int inum, int ipower);
Int main () {Printf ("3 Times 2 to the Power of 5 IS% D / N", GetPowerc (3, 5));
INT getPowerc (int inum, int ipower) {__ASM {Mov Eax, Inum; Get First Argument Mov ECX, IPower; Get Second Argument SHL Eax, Cl; Eax = Eax * (2 to The Power Of Cl)} // Return with Result in eax}
The getPowerC function written in the intra DIPE can reference its parameters through the parameter name. Since the getPowerc function does not perform C Return statement, the compiler will give a warning message, we can ban the generated this warning via #pragma Warning.
One of the use of the inline assembly is to write the initialization and end code of the Naked function. For a general function, the compiler will automatically help us generate the initialization of the function (build parameter pointer and allocate part variables) and end code (balance stack and return a value, etc.). Use the inline assembly, we can write a clean and net function. Of course, at this time we have to do some work about the function initialization and sweep. E.g:
Void __declspec (Naked) MynakeDFunction () {// Naked Functions Must Provide Their Own Prolog. __ASM {Push EBP MOV ESP, EBP SUB ESP, __LOCAL_SIZE}.
// and we must provide epilog. __ASM {pop eBP Ret}}
6. Call the C / C function
The C / C function called the declaration in the inline conveyor is __cdecl mode (default) must be cleared by the caller to clear the parameter stack. The following is an example of calling a C / C function:
#include
Char szformat [] = "% s / n"; char szhello [] = "hello"; char szworld [] = "world";
Void main () {__ASM {Mov Eax, Offset Szworld Push Eax Mov Eax, Offset Szhello Push Eax Mov Eax, Offset Szformat Push Eax Call Printf
// Infused 3 parameters in the stack, adjust the stack add ESP, 12}} after calling the function.
Tip: The parameter is pressed into the stack in the order from right left.
If you call the __stdcall method, you don't need to clear the stack yourself. Because the return instruction of this function is RET N, the stack is automatically cleared. Most Windows API functions are __stdcall call mode (except WSPRINTF, etc.), the following is an example of calling the Messagebox function:
#include
TCHAR G_TSZAPPNAME [] = text ("API Test");
Void main () {tchar tszhello [] = text ("Hello, World!");
__asm {PUSH MB_OK OR MB_ICONINFORMATION PUSH OFFSET g_tszAppName; global variables OFFSET LEA EAX, tszHello; local variables LEA PUSH EAX PUSH 0 CALL DWORD PTR [MessageBox]; note that this is not CALL MessageBox, it calls the function address relocation through} } Tip: You can access C member variables unrestricted, but you cannot access the C member function.
7. Definition __asm block is C / C macro
Use the C / C macro to easily insert assembly code into the source code. But this requires additional notes because the macro will be extended to a logical row. In order not to have problems, please write macros as follows:
Use the curly brackets to surround the __ASM block; put the __ASM keyword before each assembly instruction; use the classic C style annotation ("/ * comment * /"), do not use assembly-style annotations ("; comment" ) Or a single line of C / C annotation ("// comment");
For example, the following defines a simple macro:
#define portio __ASM / / * port output * / / {/ __ASM MOV Al, 2 / __ASM MOV DX, 0xD007 / __ASM OUT DX, Al /}
At first glance, the three __asm keywords behind it seem to be extra. In fact, they need, because the macro will be extended to a single line:
__ASM / * Port Output * / {__ASM MOV AL, 2 __ASM MOV DX, 0XD007 __ASM OUT DX, Al}
As you can see from the extended code, the third and fourth __asm keywords are required (as a statement separator). In the __asm block, only the __asm keyword, and communus will be considered a statement separator, but because a statement block defined as a macro will be considered a logical row, it is necessary to use __asm key before each instruction. word.
Brackets are also needed, if it is omitted, the compiler will not know where the assembly code is ended, and the C / C statement behind the __ ASM block looks considered to be a compilation instruction.
Also because the cause of the macro show, the assembly style annotation ("; comment") and a single line of C / C comments may also occur. To avoid these errors, please use the classic C style annotation ("/ * comment * /") when defined __asm block is macro.
The macro written by the C / C macro __ASM block can also have parameters. Unlike the C / C macro, __ ASM macro cannot return a value, so this macro cannot be used as a C / C expression. Don't call this type of macro without selectively. For example, call assembly language macros in a function that is declared as __fastcall may result in unpredictable results (see the description of the foregoing).
8. Transfer
You can use GOTO to jump to the label in the __ASM block in C / C , or you can jump into the __ASM block in the __asm block or outside. The label in the __ASM block is not case sensitive (instructions, indicators, etc. are not case sensitive). E.g:
Void myfunction () {goto c_dest; / * correct * / goto c_dest; / * error * /
Goto a_dest; / * correct * / goto a_dest; / * correct * /
__ASM {JMP C_DEST; correct JMP C_DEST; error
JMP A_DEST; correct JMP A_DEST; correct
A_DEST:; __ASM Number}
C_DEST: / * C / C Number * / Return;}
Do not use the function name as a label, otherwise it will be jumped into the function, not the label. For example, since EXIT is a function of C / C , the following turn will not go to the EXIT label:
; Error: Use the function name as the label JNE EXIT...
Dollar symbol "$" is used to specify the current command position, which is often used in condition jumps, for example:
JNE $ 5; The length of the instruction below is 5 bytes JMP _Label Nop; $ 5, the jump is here.... _Label:.
V. Use independent compilation in Visual C projects
Inline assembly code is not easy to transplant, if your program intends to run on different types of machines (such as X86 and Alpha), you may need to use specific machine code in different modules. At this time you can use MASM (Microsoft Macro Assembler) because MASM supports more convenient macros and data indicators.
Here is a brief introduction to the steps of calling MASM compiling independent assembly files in Visual Studio .NET 2003.
In the Visual C project, add the .asm file written by MASM. In the Solution Explorer, right click on this file, select the Properties menu item, in the Properties dialog box, click "Custom Build Steps", set the following items:
Command line: ml.exe / NOLOGO / C / COFF "-fo $ (intDir) / $ (InputName) .Obj" "$ (InputPath)" Output: $ (INTDIR) / $ (InputName) .Obj If you want to generate debugging Information, you can join the "/ zi" parameter in the command line, and you can generate .lst and .sbr files as needed.
If you want to call the Windows API in your assembly file, you can download the Masm32 package from the Internet (including the MASM assembly tool, very complete Windows API header file / library file, utility macro, and a large number of Win32 assembly examples, etc.). Accordingly, the "/ i x: / masm32 / incrude" parameter should be added to the command line to specify the path of the Windows API assembly header file (.inc). The home page of Masm32 is: http://www.masm32.com, you can download the latest version of Masm32 pack.
Click here to download document attachments, including TXT / Word / PDF version of documents, as well as examples of interior assembly and independent assembly.