This article describes the Embedded Assembly syntax in detail from the basic syntax, the format of embedded assembly, and the extended Embedded Assembly format. It should be noted that GCC uses at&t's Assembly format. Basic syntax There are several differences in syntax. ★Register naming principles At&t: % eax intel: eax ★Source/destination operand order At&t: movl % eax, % EBX intel: mov EBX, eax ★Constant/immediate Number Format At&t: movl $ _ value, % EBX intel: mov eax, _ value Put the _ value address in the eax register At&t: movl $ 0xd00d, % EBX intel: mov EBX, 0xd00d ★Operand length identifier At&t: movw % ax, % BX intel: mov BX, ax ★Addressing Mode At&t: immed32 (basepointer, indexpointer, indexscale) Intel: [basepointer indexpointer * indexscale imm32) Linux uses a 32-bit linear address in protection mode. Therefore, you do not need to consider the segment: Offset issue when calculating the address. The address in the above formula should be: Imm32 basepointer indexpointer * indexscale The following are some examples: ★Direct addressing At&t: _ booga; _ Booga is a global C variable. Note that adding $ indicates address reference, and not adding $ indicates value reference. Note: For local variables, You can reference them through the stack pointer. Intel: [_ booga] ★Register indirect addressing At&t: (% eax) Intel: [eax] ★Address Change Addressing At&t: _ variable (% eax) Intel: [eax _ variable] At&t: _ array (, % eax, 4) Intel: [eax * 4 _ array] At&t: _ array (% EBX, % eax, 8) Intel: [EBX eax * 8 _ array] 2. Basic Embedded Assembly The basic embedded assembly is very simple, generally in the following format ASM (statements ); Example: ASM (NOP); ASM (CLI ); ASM and _ ASM _ are exactly the same. If there are multiple lines of assembly, NT must be added for each line, for example: ASM (pushl % eaxnt Movl $0, % eaxnt Popl % eax ); In fact, GCC needs to print the content of ASM (...) to the Assembly file when processing the assembly, so it is necessary to control the format. For example: ASM (movl % eax, % EBX ); ASM (xorl % EBX, % EDX ); ASM (movl $0, _ booga ); In the above example, we changed the values of edX and EBX in the Assembly, but due to the special processing method of GCC, the Assembly file is first formed and then handed over to the gas for assembly, therefore, gas does not know that we have changed the values of edX and EBX. If the context of the program needs to be saved by EDX or EBX, this will cause serious consequences. the same problem exists for Variable _ Booga. to solve this problem, we need to use the extended in-row Assembly syntax. 3-extended in-line assembly The extended in-row assembly is similar to Watcom. The basic format is: ASM (Statements: output_regs: input_regs: clobbered_regs ); Clobbered_regs indicates the changed register. The following is an example (for convenience, I use global variables ): Int COUNT = 1; Int value = 1; Int Buf [10]; Void main () { ASM ( CLD NT Rep NT Stosl : : C (count), A (value), D (BUF [0]) : % ECx, % EDI ); } The compilation code is as follows: Movl count, % ECx Movl value, % eax Movl Buf, % EDI # App ClD Rep Stosl # No_app CLD, rep, and STOs do not need to be explained. The functions of these statements are to write Count value to Buf. The statement after the colon indicates the input, output, and changed registers. With a colon, the compiler will know what registers your commands need and change, This allows you to optimize register allocation. The symbol C (count) indicates to put the value of count into the ECX register. Similar: A eax B EBX C ECx D edX S ESI D EDI I constant value, (0-31) Q, R registers dynamically allocated G eax, EBX, ECx, EDX, or memory variable A combines eax and EDX into a 64-bit register (use long longs) We can also let GCC select the appropriate register. Example: ASM (Leal (% 1, % 1), % 0 : = R (X) : 0 (x )); This code implements fast multiplication of 5 x. The compilation code is as follows: Movl X, % eax # App Leal (% eax, % eax, 4), % eax # No_app Movl % eax, X Notes: 1. Use Q to indicate that the compiler allocates registers from eax, EBX, ECx, and EDX. Use R to indicate that the compiler allocates registers from eax, EBX, ECx, EDX, ESI, and EDI. 2. We don't have to put the registers allocated by the compiler into the changed register list, because the registers have remembered them. 3. = indicates the output register, which must be used in this way. 4. Number % N usage: registers represented by numbers are mapped to R or Q requests in the order of appearance and left-to-right If we want to reuse the R or Q request registers, we can use them. 5. If fixed registers are forcibly used, for example, EBX instead of % 1 ASM (Leal (% EBX, % EBX, 4), % 0 : = R (X) : 0 (x )); Note that two % s should be used, because the syntax of one % has been used by % N. The following describes the letter 4854-4855 problem: 1. What are the special meanings of variable underscores and double underscores? An underscore indicates a global variable, but it doesn't matter if it is not added in GCC. 2. What does the above definition mean when a meeting is called as follows? # DEFINE _ syscall1 (type, name, type1, arg1) Type name (type1 arg1) { Long _ res; /* _ Res should be a global variable */ _ ASM _ volatile (INT $0x80 /* Volatile means that optimization is not allowed, so that the compiler compiles Code strictly according to your Assembly Code */ : = A (_ res) /* Generate code movl % eax, _ res */ : 0 (_ nR _ # name), B (long) (arg1 ))); /* If I remember correctly, here # indicates two macro exhibitions. Replace name with the actual system call name, and then expand _ nR. Then put the expanded constant into eax, And put arg1 into EBX */ If (_ res> = 0) Return (type) _ res; Errno =-_ res; Return-1; } |