Use Inline Argument in Visual C ++

zhaozj2021-02-17  53

Use Inline Argument in Visual C

Author: Yonsm a, inline assembly advantages and disadvantages because of the use in in Visual C inline assembler does not need additional compiler and linker, and can handle some things in Visual C can not handle, and can be used in C / C in Variables, so it is very convenient. Inline assembly is mainly used in the following occasions: 1. Use assembly language write functions; 2. Very high-speed code requirements; 3. Direct access to hardware in the device driver; 4. "Naked" CALL initialization and end code. //(."Naked ", understanding it, but I don't know how to translate ^ _ ^, probably do not need C / C compiler (self-proportional smart) generated functions initialization and closed code, please see MSDN" Naked functions " Description) Inline assembly code is not easy to transplant, if your program is intended to run on different types of machines (such as X86 and Alpha), should try to avoid using inline assembly. At this time you can use MASM because MASM supports more convenient macro and data indicators. Second, the inline assembly keyword is included in the Visual C , which is the __asm ​​keyword, this keyword has two methods: 1. Simple __asm ​​block __asm ​​{MOV Al, 2 MOV DX, 0xD007 OUT Al , DX} 2. Plus __asm ​​keyword __ASM MOV AL, 2 __ASM MOV DX, 0XD007 __ASM MOV DX, 0xD007 __ASM Out Al, DX before each assembly instruction, so you can put the assembly instruction in the same Dot: __ASM MOV AL, 2 __ASM MOV DX, 0xD007 __ASM OUT Al, DX obviously, the first method and the C / C style is consistent, and there are many other advantages, so the first method is recommended. Not like "{}" in C / C , "{}" from __ ASM block does not affect the scope of the C / C variable. At the same time, __ ASM blocks can nested, nested nor affect the scope of the variable. Third, use assembly language in __ASM block 1. Inline Continuous Command Set Intel 486 instruction set in Jedius, allowing MMX instructions. The instructions that are not supported can be defined using the _emit pseudo command (_emit directive instructions below). 2. MASM Expression Inline assembly can use the expression in MASM. For example: MOV EAX, 1. 3. Data indicators and operators Although the __ASM block allows the C / C data types and objects, it cannot define data objects with MASM indicators and operators. It is particularly pointed out that the definition indicator in the __ ASM block is not allowed: DB, DW, DD, DQ, DT, DB, DW, DD, DQ, DT, DB, and DUP and THIS operators are not allowed. The MASM structure and records 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 supported, it supports Even and Align. These indicators are added to the NOP (empty operation) instruction in assembly code when needed. boundary. This makes it possible to have higher efficiency when some processors are taking instructions.

5. MASM Macro Index Inline Continent is not macro assembly, and cannot use MASM macro (Macro, Rept, IRC, IRP, and ENDM) and macro (<>,!, &,%, And.type). 6. Segment Description Must use the register to explain that the leapfrog must explicitly explain, such as ES: [BX]. 7. Type and Variable Size we can use Length to get the number of elements in the array in C / C , if not an array, the result is one. Use size to get the size of the variables in C / C , the size of a variable is the product of Length and Type. TYPE is used to get a variable size, if it is an array, the size of a single element in an array. 8. Note You can use C / C annotations, but it is recommended to use ASM annotations, ie ";". 9._Emit Pseudo-Directive_emit directive equivalent to DB in MASM, but only one byte can be defined at a time, such as: __asm ​​{jmp _codeofasm _emit 0x00; define the data of the mix in the code segment _emit 0x01 _codeofaSM:; Here is the code _emit 0x90 NOP instruction} IV, using C / C language elements C / C in __ASM blocks can be mixed with assembly, and the internal assembly can use C / C variables and many other C / C elements. The following C / C elements can be used in the __asm ​​block: 1. Symbol, including reference numerals, variables, and function names; 2. Constants, including symbol constants and enumeration (ENUM) members; 3. Macro definition and pre-processing indicators ; 4. Note, including "/ * /" and "//"; 5. type name, including all types 6.typedef MASM legitimate name, like PTR, tYPE, specific structural member or members such enumeration General operator. In the __ASM block, the base count method of C / C or ASM can be used (such as 0x100 and 100 h). __ASM blocks cannot be used in the << C / C operator. C / C and MASM universal operators, such as "*" and "[]" operators, are considered to be an operator of assembly language. For example: int Array [10]; __ASM MOV Array [6], BX; Store BX At Array 6 (Not Scaled) Array [6] = 0; / * STORE 0 At Array 12 (Scaled) * / * Tips: Inline assembly, you can use the Type operator to make it as C consistency. For example, the following two statements are the same: __asm ​​Mov Array [6 * Type Int], 0; Store 0 At Array 12 Array [6] = 0; / * Store 0 At Array 12 * / Inline Continuous Body Two variables directly cited C / C . Any symbol can be referenced in the __ASM block, including the variable name.

If the class, structure, or enumeration member in C / C has a unique name, if the variable is not specified or the TypeDef name before ".", The __ASM block can only be referenced in the __asm ​​block. 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 same_name member variable: struct first_type {char * weasel; int same_name;}; struct second_type {int wonton; long same_name;}; if the variable declared by the following: struct first_type hal; struct second_type oat Then, all places where all references Same_name members must use the variable name because Same_Name is not unique. In addition, the Weasel variable above has a unique name, you can use its member name to reference it: __ASM {MOV EBX, OFFSET HAL MOV ECX, [EBX] hal.same_name; must use 'Hal' Mov ESI, [EBX ] .weasel; I can omit 'Hal'}, omitted the variable name is only for the convenience of writing code, and the generated assembly instruction is still the same. You can access C member variables unrestricted, but you cannot call C member functions. V. Use of registers Generally, when the __ASM block begins, the register is empty and cannot save the value of the register between two __asm. (This is what I said on MSDN. I found it when I actually use it. But it is "general", I am special :)) If a function is declared into __fastcall, the parameters will be put In the register, this will bring questions to the management of registers. So, if you want to declare a function to __fastcall, you must save the ECX register. In order to avoid the above conflicts, do not have a __ASM block in the function of the __fastcall. If you use the / GR compilation option (which globes become __fastcall), declare each function into __cdecl or __stdcall, this property tells the compiler to use traditional C methods. If you use EAX, EBX, ECX, EDX, ESI, and EDI registers, you don't need to save it; but if you use DS, SS, SP, BP, and Sign Registers, you should save these registers. If the program changes the direction flag for STD and CLD, you must return it to the original value. Sixth, the jump can use Goto to transfer to the __ASM block in the __ASM block in the __ASM block in the __ASM block, can also be transmitted to the __asm ​​block and outside the label. The label in the __ASM block is not case sensitive (instructions, indicators, etc. are not case sensitive).

Example: void func () {goto c_dest; / * legal * / goto c_dest; / * error * / goto a_dest; / * legal * / goto a_DEST; / * legal * / __ASM {JMP C_DEST; legal JMP C_Dest; MSDN Speaking legal, but I compiled in vs.NET, think that this is not legal JMP A_DEST; legal JMP A_DEST; legal A_DEST:; __ASM label} c_dest: / * c} should not use the function name as a label, Otherwise, it will jump to the function execution rather than the label. As shown below: Error: Using the function name as the label JNE EXIT... EXIT:; Below is more ASM code Dollar symbol $ to specify the current location, as used below, often used for condition jump: JNE $ 5; The length of the instruction below is 5 bytes JMP Farlabel; $ 5, jump to here. Function example: #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 // Inline Continuous Symposion C Function must clear the stack // Clear the stack with the unused EBX register, or Add ESP, 12 POP EBX POP EBX POP EBX}} Note: The function parameter is from right to left. You cannot access class member functions in C , but you can access the Extern "C" function.

If you call the Windows API function, you don't need to clear the stack. () {Char Szhello [] = "Hello, World!"; __ASM {Push Mb_ok or MB_ICONInInformation Push Offset Szappname; global variable with offset lea eax, szhello; local variables LEA PUSH EAX PUSH 0 CALL DWORD PTR [MessageBoxa]; Here, I have spent a big discount, I found that it is not a call messageboxa}} Generally, in Visual C is used to improve the speed, so these function calls should be written as C / C . 8. An example below is written in the C language in VS.NET (ie, VC7). First build a project, put the following code in the .C file in the project, and do not need special settings, you can compile.

// Prerequisite #include // global variable hwnd g_hwnd; hinstance g_hinst; tchar sztemp [1024]; tchar szappname [] = "crc32 sample"; // function declared DWORD GETCRC32 (const Byte * Pbdata, int nSize); int WINAPI WinMain (hINSTANCE hInstance, hINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow); LRESULT CALLBACK WindowProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); // main function int WINAPI WinMain (hINSTANCE hInstance, hINSTANCE hPrevInstance , LPSTR lpCmdLine, int iCmdShow) {MSG msg; WNDCLASSEX wndClassEx; g_hInst = hInstance; wndClassEx.cbSize = sizeof (WNDCLASSEX); wndClassEx.style = CS_VREDRAW | CS_HREDRAW; wndClassEx.lpfnWndProc = (WNDPROC) WindowProc; wndClassEx.cbClsExtra = 0; wndClassEx.cbWndExtra = 0; wndClassEx.hInstance = g_hInst; wndClassEx.hIcon = LoadIcon (NULL, IDI_APPLICATION); wndClassEx.hCursor = LoadCursor (NULL, IDC_ARROW); wndClassEx.hbrBackgroun d = (HBRUSH) (COLOR_WINDOW); wndClassEx.lpszMenuName = NULL; wndClassEx.lpszClassName = szAppName; wndClassEx.hIconSm = NULL; RegisterClassEx (& wndClassEx); g_hWnd = CreateWindowEx (0, szAppName, szAppName, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT, 300, 70, NULL, NULL, g_hInst, NULL); ShowWindow (g_hWnd, iCmdShow); UpdateWindow (g_hWnd); while (GetMessage (& msg, NULL, 0, 0)) {TranslateMessage (& msg); DispatchMessage (& MSG); Return (INT) msg.wparam;

} // main window callback LRESULT CALLBACK WindowProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {switch (uMsg) {case WM_CREATE: CreateWindowEx (WS_EX_CLIENTEDGE, "EDIT", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_NOHIDESEL | WS_OVERLAPPED, 7, 12, 220, 22, hWnd, (HMENU) 1000, g_hInst, NULL); CreateWindowEx (0, "BUTTON", "& OK", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_OVERLAPPED | BS_FLAT, 244, 12, 40, 20, hwnd, (hmenu) IDOK, G_HINST, NULL); Break; Case WM_COMMAND: Switch (WPARAM)) {CASE IDOK: GetdlgitemText (g_hwnd, 1000, sztemp 100, 800); WSPrintf (SzTemp) "The CRC32 check code of the string in the current text box is: 0x% lx", getCrc32 (SzTemp 100, (int) Strlen (SzTemp 100))); MessageBox (g_hwnd, sztemp, szappname, MB_ok | MB_ICONIONITIONMATION Break; Case WM_DESTROY: POSTQUITMESSAGE (0); Break; Default: Return (DEFWIND, UMSG, WPARAM, LPARAM);} Return (0);} // getCrc32: Stermers CRC32 check code // parameters: // PBDATA: Point to byte stream buffer first address // nsize: byte stream length // // Return Value: // Byte stream CRC32 check code // // Here you use the surfactist CRC32 check The code, this part is the reference to the Lao Luo's article "Spear and Shield's Comparative (2) - CRC Principles".

Please refer to: http://asp.7i24.com/netcool/LAOLUO/Article_iD=15 ////////////////> Use the inline collection code, fully use The registers, speeds, and conveniences in the CPU are the use of C / C not multi -/ DWORD getCrc32 (const Byte * pbdata, int nsize) {dWord dwcrc32table [256]; __ASM // This intra-line assembly is initialized CRC32 Table {MOV ECX, 256 _NextTable: Lea Eax, [ECX-1] Push ECX MOV ECX, 8 _Nextbit: SHR Eax, 1 JNC _Notcarry XOR Eax, 0xedb88320 _notcarry: DEC ECX JNZ _NEXTBIT POP ECX MOV [DWCRC32TABLE ECX * 4 - 4], EAX DEC ECX JNZ _NEXTTABLE} __ASM // The following is to ask CRC32 check code {MOV EAX, -1 MOV EBX, PBData or EBX, EBX JZ _DONE MOV ECX, NSIZE OR ECX, ECX JZ _DONE _NEXTBYTE: MOV DL, [Ebx] XOR DL, Al Movzx EDX, DL SHR EAX, 8 XOR EAX, [DWCRC32TABLE EDX * 4] Inc EBX LOOP _NEXTBYTE _DONE: NOT EAX}} Nine, and later, I originally intended to write a comprehensive example of various inner linjui subscribers. Because I dragged the habit of the pull, although Dreamtheater has repeatedly urged it, it is still inevitably. If there is anything wrong or unknown, welcome criticism to refer to and discuss together (QQ: 123018).

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

New Post(0)