views:

76

answers:

4
  int main(void)
  {
   int x = 10, y;

asm ("movl %1, %%eax;"
     "movl %%eax, %0;"
    :"=r"(y)    /* y is output operand */
    :"r"(x)     /* x is input operand */
    :"%eax");   /* %eax is clobbered register */
  }

what is r(y) here also why %% is used before eax. generally single % is used right ?

A: 

I can't answer all of this, but a clobbered register is one that will get used somewhere in the computation in a way that will destroy its current value. So if the caller wants to use the current value later, it needs to save it somehow.

In asm directives like this, when you write the assembly you figure out which registers are going to be clobbered by it; you then tell the compiler this (as shown in your example), and the compiler does what it has to do to preserve the current value of that register if necessary. The compiler knows a lot about how values in registers and elsewhere will be used for later computations, but it usually can't analyse embedded assembly. So you do the analysis yourself and the compiler uses the clobbering information to safely incorporate the assembly into its optimisation choices.

Edmund
A: 

Try this tutorial. It covers everything you ask: for example, try section 6 - it explains constraints quite well, and what the "=" sign is for. Even the concept of clobbered registers is covered (section 5.3).

Matthew Iselin
The code sample in this question appears to be the third example from section 5 of that tutorial... :-)
Laurence Gonsalves
@Laurence If the OP is in fact using that tutorial, this question merely indicates he/she has not yet read the entire tutorial, as every point is answered in the tutorial.
Matthew Iselin
+1  A: 

Okay, this is gcc inline assembler which very powerful but difficult to understand.

First off, the % char is a special char. It lets you define register and number placeholders (mor on this later). Unfortunately the % is also used to as part of a register name (such as %EAX) so in gcc inline assembler you have to use two percent chars if you want to name a register.

%0, %1 and %2 (ect..) are placeholder input and output operands. These are defined in the list followed by the assembler string. In your example %0 becomes a placeholder for y, and %1 becomes a placeholder for x. The compiler will make sure the variables will be in the registers for input operands before the asm-code gets executed, and it will make sure the output operand will get written to the variable specified in the output operand list.

Now you should get an idea what r(y) is: It is an input operand that reserves a register for the variable y and assigns it to the placeholder %1 (because it is the second operand listed after the inline assembler string). There are lots of other placeholder types. m lets you specify a memory location, and if I'm not mistaken i can be used for numeric constants. You'll find them all listed in the gcc documentation.

Then there is the clobber list. This list is important! It lists all registers, flags, memory-locations ect that gets modified in your assembler code (such as the EAX in your example). If you get this wrong the optimizer will not know what has been modified and it is very likely that you end up with code that doesn't work.

Your example is by the way almost pointless. It just loads the value X into a register and assigns this register to EAX. Afterwards EAX gets stored into another register which will then later become your y variable. So all it does is a simple assignment:

y = x;

A last thing: If you have worked with Intel-style assembler before: You have to read the arguments backwards. For all instructions the source operand is the one following the instruction itself, and the target operand is the one on the right of the comma. Compared to Intel syntax this is exactly the other way around.

Nils Pipenbrinck
+1  A: 

The lines with "r" or "=r" are operand constraints. The "=" means output operand. Essentially, this:

:"=r"(y)
:"r"(x)

means that %0 (ie: the first operand) corresponds to y and is for output, and %1 (the second operand) corresponds to x.

A single % is normally used in AT&T syntax assembly, but for inline assembly the single % is used for operand references (eg: %0, %1) while a double % is used for literal register references. Think of it like the way you have to use a double % in a printf format if you want a literal % in the output.

A clobbered register is a register whose value will be modified by the assembly code. As you can see from the code, eax is written to. You need to tell gcc about this so that it knows that the compiled code can't keep anything it needs for later in eax when it's about to invoke this assembly.

Laurence Gonsalves