Why the built-in assembler GCC requires information about clobbing, but MSVC does not

I do not understand how this should work.

The GCC built-in assembler is a pain to get right, but very specific with respect to labeling information about clobbing, so that the compiler knows what you are doing.

The Microsoft Visual C ++ inline assember is very easy to use (it always seems Just Work), but I have no idea what guarantees or assumptions it makes about your code.

Does VC ++ perform "automatic discovery", which registers are down? How does he know how registers and stack pointer will be changed? Are there any suggestions? If so, how do you circumvent these assumptions?

+8
c gcc inline-assembly visual-c ++
source share
2 answers

As for why the GCC does not do this the way MSVC does, there are several reasons:

  • GCC is a reconfigurable compiler, but the assembly syntax is just raw text. In order for clot detection to be automatic, GCC had to analyze the assembler language to understand which registers were clogged (including implicitly knocked down by instructions whose operation codes are not called register). This should work in all architectures. GCC does not currently analyze assembly language; it just inserts it into the assembly after performing % substitutions. The idea is to generate and avoid parsing.

  • In the built-in GCC assembler, flush registers are an exception, not a rule . The reason is that it is a more complex language than in MSVC. The GCC built-in assembly language allocates registers to you. Therefore, you usually do not use something like %eax directly, but rather code like %0 , for which GCC replaces the available register. (And for this, the compiler does not need to understand assembly language! You express restrictions that guarantee that GCC replaces the corresponding register for %0 , which is suitable for use.) You only need clobber if your assembly code overwrites hard-coded registers, and not if it rewrites the output operands allocated to you by GCC .

Note that with the built-in GCC assembly, you don’t need to write code that loads assembly language operands from C expressions that produce their initial values, or that stores your resulting operands in C assignments. For example, you just say that there must be an input operand type "r" (register), which is obtained from the expression foo->bar + 1 . GCC selects a register and generates code to load from foo->bar + 1 , and then replaces the %0 occurrences in the assembly template with the name of this register.

+19
source share

Quote from the docs :

When using __asm ​​to write assembly language in C / C ++ functions, you do not need to save the registers EAX, EBX, ECX, EDX, ESI or EDI. For example, in the POWER2.C example in Writing Functions Using the Built-in Assembly , the power2 function does not store the value in the EAX register. However, using these registers will affect the quality of the code, because the register allocator cannot use them to store values ​​through __asm ​​blocks. In addition, using EBX, ESI or EDI in the built-in assembler, you force the compiler to save and restore these registers in the prolog and epilogue of the function.

You must save other registers that you use (for example, DS, SS, SP, BP and flag registers) for the scope of the __asm ​​block. You must save the ESP and EBP registers if you have no reason to change them (for example, to switch stacks). Also see Optimizing the Embedded Assembly .

+4
source share

All Articles