Use Inline Argument in Visual C ++

zhaozj2021-02-16  101

Repost. Save. 1. Advantages use inline assembly to embed assembly language instructions in 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: * Writing a specific function using assembly language; * Writing a code for speed requirements; * Access the hardware directly in the device driver; * Write the initialization and end code of the NAKED function. Second, the keyword uses inline assembly to use the __asm ​​keyword, which can appear in any place that allows C / C statements. Let's see some examples: * Simple __asm ​​block: __ASM {MOV Al, 2 MOV DX, 0xD007 OUT Al, DX} * before adding __asm ​​keywords 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 It is consistent with the style of C / C , and the assembly code and C / C code are clearly separated, and the 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 1. Inline container supports all instructions of Intel Pentium 4 and AMD Athlon in Inline Connection. More other processors can be created by the _emit directive (_emit directive instructions below). 2. MASM Expressions Inline assembly code, you can use all MASM expressions (MASM expressions are used to calculate a value or a combination of operators and operands of an address). 3. Data indicators and operators 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 most MASM indicators are not supported, 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. The MASM macro pointer is not a macro assembly, which cannot use the MASM macro (Macro, Rept, IRC, IRP, and ENDM) and macro (<>,!, &,%, And.type). 6. Segments must use registers instead of name to specify (segment name "_text" is invalid). Also, the section must explicitly explain, such as ES: [EBX]. 7. Type and variable size Inline assembly, you can use Length, Size and Type to get the C / C variable and type big? * Length operator is used to get the number of elements of the C / C in the middle group (if not An array, then 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 type variable is defined in the program: INT IARRAY [8]; the following is the correlation value of the IARRAY and its elements obtained in the C and assembly expressions: __asm ​​c size length otray sizeof (IARRAY) / SIZEOF IARRAY [0]) 8 Size IaRray SizeOf (IARRAY) 32 TYPE IARRAY SIZEOF (IARRAY [0]) 4 8. Comment Inline Connection You can use assembly language notes, ie ";". For example: __ASM MOV EAX, Offset PBBUFF; Load Address of PBBUFF Because the C / C macro will expand into a logical row, in order to avoid confusion brought by assembly language annotations in the macro, the inline assembly is also allowed to use C / C Style annotation. 9. _emit Pseudo Directive_emit pseudo-instructions equivalent to DB in MASM, but _emit can only define one byte in the current code segment (.text segment) at a time. For example: __ASM {jmp _codelabel _emit 0x00; define the data of the mix in the code segment _emit 0x01 _codelabel:; here is the code _emit 0x90; NOP instruction} 10. Register usage Generally, can't assume that a register starts at the __asm ​​block There is known value. 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 changes the direction flags for STD and CLDs, it must be restored to the original value. Fourth, using C / C elements 1. Available C / C element C / C and assembly language can be mixed, and C / C variables can be used in the inner assembly, and many other C / C elements, including: * symbols, Includes labels, variables, and function names; * constants, including symbol constants and enumeration type members; * macro definition and pre-processing indicators; * Comments, "/ ** /" and "//"; * Type name, including The legal types in all MASMs; * TypeDef names, usually use the 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 uses inner linker that cannot use a C / C operator such as "<<". 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 aaray [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 match 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 usage 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 the __asm ​​block must be declared first.

Otherwise, the compiler will not distinguish the function name and label in the __asm ​​block. * C / C symbols (not case sensitive) for Masm cannot be used in the __asm ​​block. 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. A very convenient connection to the inline assembly in the data in C / C 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 __asm ​​block You can access only the variable name or TypeDef name before the operator can be accessed by the member 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 having SameName member variable: struct FIRST_TYPE {char * pszWeasel; int SameName;}; struct SECOND_TYPE {int iWonton; long SameName;}; If you press the variables declared in the following manner: struct FIRST_TYPE ftTest; struct SECOND_TYPE Sttemp; then, all places where all reference SameName members must use, because SameName is not unique. In addition, since the above PSZWeasel variable has a unique name, you can only reference it with its member name: __ASM {MOV EBX, OFFSET FTTEST MOV ECX, [EBX] fttest.sameName; "fttest" Mov ESI, [ EBX]. Pszweasel; "fttest"} * prompt: omitted the variable name is only for writing code, 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 parameters and return a value.

Looking at the examples below, comparing the functions written with independent compilation and inline quotation:; 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 END C / C Function typically uses stacks to deliver parameters, so the above function needs to access its parameters (in MASM or others) in MASM or others. In assembly tools, the stack parameters and local stack variables are allowed via names. The following procedure is written in intangible documents: // 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 internal exchange 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.

For example: 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 Inline Communication Call Declaration as __cdecl mode (default) C / C function must be cleared by the caller to clear the parameter stack, below is a call C / C function example: #include char 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}} * prompt: parameter is from right left. Press the stack. 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 (outside 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! "); __Asm {push mb_ok or mb_iconinformation push offset g_tszappname; global variable with offset lea eax, tszhello; local variable with Lea Push Eax Push 0 Call DWord PTR [MessageBox]; note that this is not Call MessageBox, but calls the repositioned function address}} * Tip: You can access the C member variables without restrictions, but you cannot access the C member function. 7. Define __ASM blocks for C / C macros Use C / C macros 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 macro as follows: * Use parentheses to put __asm ​​blocks; * Put __ASM keyword before each assembly instruction; * Use classic C style annotation ("/ * comment * / ") Do not use assembly-style annotations ("; comment ") or a single line of C / C annotation (" // comment "); for an example, the following defines a simple macro: #define portio __ASM / / * Port outprut * / / / {/ __ASM MOV AL, 2 / __ASM MOV DX, 0xD007 / __ASM Out DX, Al /} At first glance, the three __asm ​​keywords seem to be redundant. 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} It can be seen 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. Turkey 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).

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

New Post(0)